diff --git a/lc-continuity/README.md b/lc-continuity/README.md index 56b64f2efae83254a35dc2c31c5b618a30b9aa34..a930a5175c86f478545d46ec1d4a147868b93d31 100644 --- a/lc-continuity/README.md +++ b/lc-continuity/README.md @@ -1,52 +1,309 @@ -# gipsy danger +## Issue Tracking -Gipsy is the super-build for the mk6 C-language codeline. This codeline builds on the work of Continuity and libmecha. -mk3 and mk4 codelines for those products are available from the historic "csrc" git repo. +https://ticket.leigh-co.com/projects/4e7a58ce-10f8-4420-8d92-4e7c97f5e7da -It is the philosophy of the build that there is no intelligence or configuration provided in the root directory (gypsy/), -other than selecting which modules will build in a given environment. Therefore, every subdirectory of gipsy should be able -to have cmake (or whatever local build tool) run independently. +## Binaries -## Building +A binary distribution of Continuity mk4 with all the modules except the Oracle / Postgres / Dynamo connectors is available at smb://fs1/library/leighco-dist -### Linux & MacOS Command Line +## Compiling +### mk4 ~~~ -cmake . +./configure make ~~~ -### XCode +### mk5 +~~~ +cmake CMakeLists.txt +make +~~~ + +## Required Packages ~~~ -cmake . -GXcode +dnf install -y libuuid libuuid-devel pcre pcre-devel +dnf install -y tcl tcl-devel tk tk-devel ~~~ -### Clion +## mod/m3 Internet radio -Open the gipsy directory into CLion as a project. +mod/m3 is a module written by Eric Lindvall for the Continuity server. mod/3m implements an Internat radio station supporting the Shoutcast protocol, which is detailed elsewhere. mod/m3 supports playing randomly from a list of MP3 files of various bitrates. It is not a requirement that all MP3 files played be of the same bitrate. (I do not recall if VBR MP3s are supported or not). mod/m3 is unique among shoutcast servers in that it ensures that all clients are hearing the same thing at the same time. If a client falls behind due to network or other latency, mod/m3 will skip that client ahead to the "present" time. -## Adding Modules +### Enduser Pages -### Test-Application Example +mod/m3 supports dynamic HTML pages that allow endusers to interact with the radio station. It is possible to: list the state of the playlist, skip the song that is currently playing, see the current track information, and to schedule a mp3 to play even if it is not part of the playlist. This functionality is all implemented through TCL functions which are exposed through the mod/tcl module. -~~~ -cmake_minimum_required(VERSION 3.6) -project(hello) +The content for these HTML pages have been lost to the mists of time, so it is currently a TBD to re-create them. The C functions for the TCL bindings are: -set(CMAKE_C_STANDARD 99) -add_executable(hello main.c) -target_link_libraries(hello LINK_PUBLIC mecha) ~~~ +0000000000005b99 t m3_tcl_add_track +0000000000005a5d t m3_tcl_get_displayname +00000000000059df t m3_tcl_get_loser +0000000000005aa4 t m3_tcl_get_users +0000000000005966 T m3_tcl_init +0000000000005c96 t m3_tcl_reload_playlist +0000000000005b16 t m3_tcl_skip_track +~~~ + +The *m3_client* handler is written so that it will answer any request to the server from not a browser (based crudely on the user-agent). So there is no defined shoutcast URL, rather, any URL on the server not in the browser path will retrieve the stream. If the client is determined to be a browser, and it has requested something outside of the browser URL, then it will be redirected to the base browser URL. At that point, a different module like mod/site can pickup serving website content. This allows self-hosting the enduser HTML pages. + +If the HTML pages are created, then they must be served through mod/tcl & mod/site in the typical way. + +### Playlist File -### Mecha-Dependent Library Example +The playlist file is apparently in M3U format but in reality a plaintext file listing the full paths to the MP3 files to stream is sufficient. Adding meta-data to this file is not productive. The file is loaded the first time a shoutcast client connects, or, when *m3_tcl_reload_playlist* is called. Of course, the server can always simply be restarted, but this will disconnect any connected shoutcast clients. + +The playlist mechanic is such that when the playlist is loaded, it is randomized. mod/m3 will then play that shuffled playlist from top to bottom. When it gets to the end, it re-shuffles the playlist again. This ensures that, given uninterrupted operation, that every track will be heard at least once, and, also, that the order is always fresh, so endusers will not be able to predict what song comes after any given track. Contrast this to, for example, iTunes which seems to exhibit the behavior that it randomizes once when the playlist is modified, and then not again thereafter, so subsequent plays get the same shuffle order. + +### Configuration + +The configuration takes place in two parts. Multiple radio stations may be configured on the same Continuity instance. The first piece of configuration is a block which is associated with a given site. This defines the general operation of the radio station, such as where to find the playlist file containing the MP3s to stream. The second piece of configuration is including the *m3_client* service handler. + +mod/m3 uses the site_id attribute in the transaction block to correlate a request with a mod/m3 server instance, so this attribute must be set. The simplest way to do this is by using mod/site and the *siteFset_siteid* translation function. This can be seen in the working configuration example below. + +### Example ~~~ -cmake_minimum_required(VERSION 3.6) -project(libexample) -set(CMAKE_C_STANDARD 99) -set(SOURCE_FILES example.c example.h) -add_library(libadif STATIC ${SOURCE_FILES}) -target_link_libraries(libadif LINK_PUBLIC mecha) -target_include_directories(libexample PUBLIC .) + + + + ../lib/image + ../lib/db + ../lib/cmd + ../lib/http + ../lib/site + ../lib/m3 + ../lib/tcl + + + + + + 5 + 80 + + + + + 5 + 80 + httpFhandler + + + + + + + + + Sites + + + index.html + + + + + + + + + + + + + + + + + + + + /tmp + + + + /var/www/html + + /opt/music/m3.m3u + /radio/ + + LEIGH&CO RADIO + m3.leigh-co.com/radio/currently_playing.html + + + + + + application/postscript + audio/x-aiff + audio/x-aiff + audio/x-aiff + application/x-aim + application/astound + application/x-asap + audio/basic + video/msvideo + application/octet-stream + image/bmp + application/x-netcdf + internal/cgi + application/x-fortezza-ckl + application/java-vm + application/x-cpio + application/x-mscardfile + application/x-pkcs7-crl + application/x-csh + text/css + application/msword + application/x-dot + drawing/x-dwf + image/vng + dynamo-internal/template + dynamo-internal/dynjava + application/pre-encrypted + application/postscript + audio/echospeech + audio/echospeech + application/x-earthtime + text/x-setext + application/x-envoy + image/fif + application/x-maker + video/isivideo + image/gif + application/x-gtar + application/x-hdf + application/winhlp + application/mac-binhex40 + text/html + text/html + x-conference/x-cooltalk + image/ief + image/ifs + internal/php4 + application/x-NET-Install + application/java-archive + image/jpeg + dynamo-internal/html + dynamo-internal/html + image/jpeg + image/jpeg + image/jpeg + application/x-javascript + application/x-javascript-config + application/x-javascript;charset=UTF + dynamo-internal/plain + dynamo-internal/plain + audio/x-liveaudio + application/x-latex + application/fastman + application/x-msmediaview + application/x-msmediaview + application/x-troff-man + dynamo-internal/map + application/mbedlet + application/x-msaccess + application/x-troff-me + application/x-mif + audio/mid + audio/midi + application/x-mif + application/x-msmoney + application/x-mocha + application/x-mocha + video/quicktime + video/x-sgi-movie + video/quicktime + video/x-mpeg2 + video/mpeg + video/mpeg + video/mpeg + video/mpeg + video/x-mpeg2 + video/mpeg + application/x-troff-ms + application/x-netcdf + application/oda + audio/x-pac + audio/x-epac + image/x-portable-bitmap + image/x-photo-cd + application/pdf + image/x-portable-graymap + internal/php4 + image/jpeg + image/jpeg + application/x-pl + image/png + image/x-portable-anymap + application/vnd.ms-powerpoint + image/x-portable_pixmap + application/vnd.ms-powerpoint + application/vnd.ms-powerpoint + application/x-ns-proxy-autoconfig + application/postscript + application/x-mspublisher + video/quicktime + audio/x-pn-realaudio + audio/x-pn-realaudio + image/x-cmu-raster + image/x-rgb + application/x-troff + application/msword + text/richtext + application/x-msschedule + application/java-serialized-object + application/x-sh + application/x-shar + application/x-stuffit + x-salsa + application/studiom + application/astround + audio/basic + application/x-sprite + application/x-sprite + application/x-wais-source + image/vng + x-world/x-svr + text/x-speech + application/x-troff + application/x-tar + application/x-timbuktu + application/timbuktu + internal/tcl + application/x-tex + application/x-texinfo + application/x-texinfo + image/tiff + image/tiff + application/x-tkined + application/x-tkined + application/x-troff + application/x-msterminal + text/tab-seperated-values + video/mpeg + video/vivo + video/vivo + x-world/x-vrt + audio/x-wav + application/msword + application/x-msmetafile + x-world/x-vrml + video/wavelet + image/x-xbitmap + application/vnd.ms-excel + application/vnd.ms-excel + application/vnd.ms-excel + application/vnd.ms-excel + application/vnd.ms-excel + application/vnd.ms-excel + image/x-xpixmap + image/x-xwindowdump + application/zip + + + ~~~ diff --git a/lc-continuity/mk4/CVS/Entries b/lc-continuity/mk4/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..93673e60b9c331989ef20d8f32d5c0b2596eb13d --- /dev/null +++ b/lc-continuity/mk4/CVS/Entries @@ -0,0 +1,28 @@ +/Makefile.in/1.8/Fri May 21 14:06:10 2004//Tmk4_mod6_rc2 +/buildconf/1.1.2.1/Fri Jul 9 14:05:35 2004//Tmk4_mod6_rc2 +/config.guess/1.1/Wed May 19 18:34:28 2004//Tmk4_mod6_rc2 +/config.sub/1.1/Wed May 19 18:34:28 2004//Tmk4_mod6_rc2 +/configure.in/1.5/Wed May 19 21:02:58 2004//Tmk4_mod6_rc2 +/install-sh/1.1/Wed May 19 18:34:28 2004//Tmk4_mod6_rc2 +D/continuity//// +D/doc//// +D/httpclient//// +D/lib//// +D/mobility-client//// +D/modbeacon//// +D/modcommand//// +D/moddb//// +D/moddynamo//// +D/modexample//// +D/modharmony//// +D/modhtaccess//// +D/modhttp//// +D/modimage//// +D/modjava//// +D/modm3//// +D/modmobility//// +D/modoracle//// +D/modradius//// +D/modsite//// +D/modssl//// +D/modtcl//// diff --git a/lc-continuity/mk4/CVS/Repository b/lc-continuity/mk4/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..2a3f2448db9e1326f1ca5615a8535d22412d6ddc --- /dev/null +++ b/lc-continuity/mk4/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc diff --git a/lc-continuity/mk4/CVS/Root b/lc-continuity/mk4/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/CVS/Tag b/lc-continuity/mk4/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/Makefile.in b/lc-continuity/mk4/Makefile.in new file mode 100644 index 0000000000000000000000000000000000000000..88a9596e9150f4bbff60e2e4738a7c4b981b3079 --- /dev/null +++ b/lc-continuity/mk4/Makefile.in @@ -0,0 +1,52 @@ +# $Id: Makefile.in,v 1.8 2004/05/21 14:06:10 aleigh Exp $ + +MODS=@MODS@ +#LIBS=@LIBS@ +LIBS= +CONT_FLAGS=-fPIC + +world: continuity/bin/continuity libs modules + +libs: + for dir in $(LIBS); do \ + $(MAKE) -C $$dir; \ + done + +libs_clean: + for dir in $(LIBS); do \ + $(MAKE) -C $$dir clean; \ + done + +modules: modules_depend + for dir in $(MODS); do \ + $(MAKE) -C $$dir; \ + done + +modules_depend: .modules_depended + +.modules_depended: + for dir in $(MODS); do \ + cp $$dir/Makefile.in $$dir/Makefile; \ + $(MAKE) -C $$dir depend; \ + done + touch .modules_depended + +modules_clean: + for dir in $(MODS); do \ + $(MAKE) -C $$dir clean; \ + done + +continuity/bin/continuity: continuity/Makefile + (cd continuity ; make) + +continuity/configure: continuity/configure.in + (cd continuity ; autoconf) + +continuity/Makefile: continuity/configure continuity/mecha/Makefile.in continuity/cont/Makefile.in + (cd continuity ; ./configure) + +count: + find . -name '*.c' | grep -v tcl8.3.4 | grep -v jpeg-6b | grep -v pcre | xargs wc -l | grep total + +clean: modules_clean + $(MAKE) -C continuity clean diff --git a/lc-continuity/mk4/buildconf b/lc-continuity/mk4/buildconf new file mode 100644 index 0000000000000000000000000000000000000000..8a7b0208b887fbc85d1a3ae8583be7b7161eabf0 --- /dev/null +++ b/lc-continuity/mk4/buildconf @@ -0,0 +1,4 @@ +#!/bin/sh + +autoconf + diff --git a/lc-continuity/mk4/config.guess b/lc-continuity/mk4/config.guess new file mode 100644 index 0000000000000000000000000000000000000000..81688c4cf1a4a470eb9f1166cc5146dbc69c8404 --- /dev/null +++ b/lc-continuity/mk4/config.guess @@ -0,0 +1,1284 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000 +# Free Software Foundation, Inc. + +version='2000-07-27' + +# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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. + +# Written by Per Bothner . +# Please send patches to . +# +# 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. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit system type (host/target name). +# +# Only a few systems have been added to this list; please add others +# (but try to keep the structure clean). +# + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of this system. + +Operation modes: + -h, --help print this help, then exit + -V, --version print version number, then exit" + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case "$1" in + --version | --vers* | -V ) + echo "$version" ; exit 0 ;; + --help | --h* | -h ) + echo "$usage"; exit 0 ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + exec >&2 + echo "$me: invalid option $1" + echo "$help" + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +# Use $HOST_CC if defined. $CC may point to a cross-compiler +if test x"$CC_FOR_BUILD" = x; then + if test x"$HOST_CC" != x; then + CC_FOR_BUILD="$HOST_CC" + else + if test x"$CC" != x; then + CC_FOR_BUILD="$CC" + else + CC_FOR_BUILD=cc + fi + fi +fi + + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 8/24/94.) +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 + +dummy=dummy-$$ +trap 'rm -f $dummy.c $dummy.o $dummy; exit 1' 1 2 15 + +# 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. + # Determine the machine/vendor (is the vendor relevant). + case "${UNAME_MACHINE}" in + amiga) machine=m68k-unknown ;; + arm32) machine=arm-unknown ;; + atari*) machine=m68k-atari ;; + sun3*) machine=m68k-sun ;; + mac68k) machine=m68k-apple ;; + macppc) machine=powerpc-apple ;; + hp3[0-9][05]) machine=m68k-hp ;; + ibmrt|romp-ibm) machine=romp-ibm ;; + *) machine=${UNAME_MACHINE}-unknown ;; + esac + # The Operating System including object format. + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep __ELF__ >/dev/null + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + # The OS release + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + # 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 0 ;; + alpha:OSF1:*:*) + if test $UNAME_RELEASE = "V4.0"; then + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + fi + # 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. + cat <$dummy.s + .data +\$Lformat: + .byte 37,100,45,37,120,10,0 # "%d-%x\n" + + .text + .globl main + .align 4 + .ent main +main: + .frame \$30,16,\$26,0 + ldgp \$29,0(\$27) + .prologue 1 + .long 0x47e03d80 # implver \$0 + lda \$2,-1 + .long 0x47e20c21 # amask \$2,\$1 + lda \$16,\$Lformat + mov \$0,\$17 + not \$1,\$18 + jsr \$26,printf + ldgp \$29,0(\$26) + mov 0,\$16 + jsr \$26,exit + .end main +EOF + $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null + if test "$?" = 0 ; then + case `./$dummy` in + 0-0) + UNAME_MACHINE="alpha" + ;; + 1-0) + UNAME_MACHINE="alphaev5" + ;; + 1-1) + UNAME_MACHINE="alphaev56" + ;; + 1-101) + UNAME_MACHINE="alphapca56" + ;; + 2-303) + UNAME_MACHINE="alphaev6" + ;; + 2-307) + UNAME_MACHINE="alphaev67" + ;; + esac + fi + rm -f $dummy.s $dummy + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit 0 ;; + 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 0 ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit 0 ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit 0;; + amiga:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit 0 ;; + arc64:OpenBSD:*:*) + echo mips64el-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + arc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + hkmips:OpenBSD:*:*) + echo mips-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + pmax:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sgi:OpenBSD:*:*) + echo mips-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + wgrisc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit 0 ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit 0;; + SR2?01:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit 0;; + 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 0 ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit 0 ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + i86pc:SunOS:5.*:*) + echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + 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 0 ;; + 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 0 ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit 0 ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(head -1 /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 0 ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit 0 ;; + atari*:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + # 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 0 ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit 0 ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit 0 ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit 0 ;; + sun3*:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mac68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme88k:OpenBSD:*:*) + echo m88k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit 0 ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit 0 ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit 0 ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + 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 $dummy.c -o $dummy \ + && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ + && rm $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + echo mips-mips-riscos${UNAME_RELEASE} + exit 0 ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit 0 ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit 0 ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit 0 ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit 0 ;; + 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 0 ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit 0 ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit 0 ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit 0 ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit 0 ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit 0 ;; + ????????: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 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i?86:AIX:*:*) + echo i386-ibm-aix + exit 0 ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + echo rs6000-ibm-aix3.2.5 + 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 0 ;; + *:AIX:*:4) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | head -1 | awk '{ print $1 }'` + if /usr/sbin/lsattr -EHl ${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=4.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit 0 ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit 0 ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit 0 ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit 0 ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit 0 ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit 0 ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit 0 ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit 0 ;; + 9000/[34678]??:HP-UX:*:*) + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + 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 $dummy.c -o $dummy 2>/dev/null ) && HP_ARCH=`./$dummy` + rm -f $dummy.c $dummy + esac + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit 0 ;; + 3050*:HI-UX:*:*) + 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 $dummy.c -o $dummy && ./$dummy && rm $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + echo unknown-hitachi-hiuxwe2 + exit 0 ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit 0 ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit 0 ;; + *9??*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit 0 ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit 0 ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit 0 ;; + i?86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit 0 ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit 0 ;; + hppa*:OpenBSD:*:*) + echo hppa-unknown-openbsd + exit 0 ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit 0 ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit 0 ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit 0 ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit 0 ;; + CRAY*X-MP:*:*:*) + echo xmp-cray-unicos + exit 0 ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} + exit 0 ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ + exit 0 ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*T3E:*:*:*) + echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY-2:*:*:*) + echo cray2-cray-unicos + exit 0 ;; + F300:UNIX_System_V:*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "f300-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit 0 ;; + F301:UNIX_System_V:*:*) + echo f301-fujitsu-uxpv`echo $UNAME_RELEASE | sed 's/ .*//'` + exit 0 ;; + hp300:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + i?86:BSD/386:*:* | i?86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit 0 ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:FreeBSD:*:*) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit 0 ;; + *:OpenBSD:*:*) + echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + exit 0 ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit 0 ;; + i*:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit 0 ;; + 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 i386-pc-interix + exit 0 ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit 0 ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit 0 ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + *:GNU:*:*) + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit 0 ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit 0 ;; + *:Linux:*:*) + + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + ld_help_string=`cd /; ld --help 2>&1` + ld_supported_emulations=`echo $ld_help_string \ + | sed -ne '/supported emulations:/!d + s/[ ][ ]*/ /g + s/.*supported emulations: *// + s/ .*// + p'` + case "$ld_supported_emulations" in + *ia64) + echo "${UNAME_MACHINE}-unknown-linux" + exit 0 + ;; + i?86linux) + echo "${UNAME_MACHINE}-pc-linux-gnuaout" + exit 0 + ;; + elf_i?86) + TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" + ;; + i?86coff) + echo "${UNAME_MACHINE}-pc-linux-gnucoff" + exit 0 + ;; + sparclinux) + echo "${UNAME_MACHINE}-unknown-linux-gnuaout" + exit 0 + ;; + armlinux) + echo "${UNAME_MACHINE}-unknown-linux-gnuaout" + exit 0 + ;; + elf32arm*) + echo "${UNAME_MACHINE}-unknown-linux-gnuoldld" + exit 0 + ;; + armelf_linux*) + echo "${UNAME_MACHINE}-unknown-linux-gnu" + exit 0 + ;; + m68klinux) + echo "${UNAME_MACHINE}-unknown-linux-gnuaout" + exit 0 + ;; + elf32ppc | elf32ppclinux) + # Determine Lib Version + cat >$dummy.c < +#if defined(__GLIBC__) +extern char __libc_version[]; +extern char __libc_release[]; +#endif +main(argc, argv) + int argc; + char *argv[]; +{ +#if defined(__GLIBC__) + printf("%s %s\n", __libc_version, __libc_release); +#else + printf("unkown\n"); +#endif + return 0; +} +EOF + LIBC="" + $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null + if test "$?" = 0 ; then + ./$dummy | grep 1\.99 > /dev/null + if test "$?" = 0 ; then + LIBC="libc1" + fi + fi + rm -f $dummy.c $dummy + echo powerpc-unknown-linux-gnu${LIBC} + exit 0 + ;; + shelf_linux) + echo "${UNAME_MACHINE}-unknown-linux-gnu" + exit 0 + ;; + esac + + if test "${UNAME_MACHINE}" = "alpha" ; then + cat <$dummy.s + .data + \$Lformat: + .byte 37,100,45,37,120,10,0 # "%d-%x\n" + + .text + .globl main + .align 4 + .ent main + main: + .frame \$30,16,\$26,0 + ldgp \$29,0(\$27) + .prologue 1 + .long 0x47e03d80 # implver \$0 + lda \$2,-1 + .long 0x47e20c21 # amask \$2,\$1 + lda \$16,\$Lformat + mov \$0,\$17 + not \$1,\$18 + jsr \$26,printf + ldgp \$29,0(\$26) + mov 0,\$16 + jsr \$26,exit + .end main +EOF + LIBC="" + $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null + if test "$?" = 0 ; then + case `./$dummy` in + 0-0) + UNAME_MACHINE="alpha" + ;; + 1-0) + UNAME_MACHINE="alphaev5" + ;; + 1-1) + UNAME_MACHINE="alphaev56" + ;; + 1-101) + UNAME_MACHINE="alphapca56" + ;; + 2-303) + UNAME_MACHINE="alphaev6" + ;; + 2-307) + UNAME_MACHINE="alphaev67" + ;; + esac + + objdump --private-headers $dummy | \ + grep ld.so.1 > /dev/null + if test "$?" = 0 ; then + LIBC="libc1" + fi + fi + rm -f $dummy.s $dummy + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} ; exit 0 + elif test "${UNAME_MACHINE}" = "mips" ; then + cat >$dummy.c < /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif +#ifdef __MIPSEB__ + printf ("%s-unknown-linux-gnu\n", argv[1]); +#endif +#ifdef __MIPSEL__ + printf ("%sel-unknown-linux-gnu\n", argv[1]); +#endif + return 0; +} +EOF + $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + elif test "${UNAME_MACHINE}" = "s390"; then + echo s390-ibm-linux && exit 0 + else + # Either a pre-BFD a.out linker (linux-gnuoldld) + # or one that does not give us useful --help. + # GCC wants to distinguish between linux-gnuoldld and linux-gnuaout. + # If ld does not provide *any* "supported emulations:" + # that means it is gnuoldld. + echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations:" + test $? != 0 && echo "${UNAME_MACHINE}-pc-linux-gnuoldld" && exit 0 + + case "${UNAME_MACHINE}" in + i?86) + VENDOR=pc; + ;; + *) + VENDOR=unknown; + ;; + esac + # Determine whether the default compiler is a.out or elf + cat >$dummy.c < +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif +#ifdef __ELF__ +# ifdef __GLIBC__ +# if __GLIBC__ >= 2 + printf ("%s-${VENDOR}-linux-gnu\n", argv[1]); +# else + printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]); +# endif +# else + printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]); +# endif +#else + printf ("%s-${VENDOR}-linux-gnuaout\n", argv[1]); +#endif + return 0; +} +EOF + $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 + fi ;; +# 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. + i?86:DYNIX/ptx:4*:*) + echo i386-sequent-sysv4 + exit 0 ;; + 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 0 ;; + 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 0 ;; + i?86:*:5:7*) + # Fixed at (any) Pentium or better + UNAME_MACHINE=i586 + if [ ${UNAME_SYSTEM} = "UnixWare" ] ; then + echo ${UNAME_MACHINE}-sco-sysv${UNAME_RELEASE}uw${UNAME_VERSION} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE} + fi + exit 0 ;; + 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|egrep Release|sed -e 's/.*= //')` + (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit 0 ;; + i?86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit 0 ;; + 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 i386. + echo i386-pc-msdosdjgpp + exit 0 ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit 0 ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit 0 ;; + 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 0 ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit 0 ;; + M68*:*:R3V[567]*:*) + test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; + 3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*: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 0 + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4 && exit 0 ;; + m68*:LynxOS:2.*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit 0 ;; + i?86:LynxOS:2.*:* | i?86:LynxOS:3.[01]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + rs6000:LynxOS:2.*:* | PowerPC:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit 0 ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + *: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 0 ;; + PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit 0 ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit 0 ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit 0 ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit 0 ;; + news*:NEWS-OS:*:6*) + echo mips-sony-newsos6 + exit 0 ;; + 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 0 ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit 0 ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit 0 ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit 0 ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit 0 ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit 0 ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + *:Darwin:*:*) + echo `uname -p`-apple-darwin${UNAME_RELEASE} + exit 0 ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + if test "${UNAME_MACHINE}" = "x86pc"; then + UNAME_MACHINE=pc + fi + echo `uname -p`-${UNAME_MACHINE}-nto-qnx + exit 0 ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit 0 ;; + NSR-W:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit 0 ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit 0 ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit 0 ;; + *: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 0 ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +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"); 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) + printf ("vax-dec-bsd\n"); exit (0); +#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 $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm $dummy.c $dummy && exit 0 +rm -f $dummy.c $dummy + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } + +# 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 0 ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + c34*) + echo c34-convex-bsd + exit 0 ;; + c38*) + echo c38-convex-bsd + exit 0 ;; + c4*) + echo c4-convex-bsd + exit 0 ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess version = $version + +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: "version='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/lc-continuity/mk4/config.sub b/lc-continuity/mk4/config.sub new file mode 100644 index 0000000000000000000000000000000000000000..945a7f4b8588f5328dc68461f1706008ac873859 --- /dev/null +++ b/lc-continuity/mk4/config.sub @@ -0,0 +1,1324 @@ +#! /bin/sh +# Configuration validation subroutine script, version 1.1. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000 +# Free Software Foundation, Inc. + +version='2000-08-07' + +# 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., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, 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 . +# +# 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. + +# 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 + -V, --version print version number, then exit" + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case "$1" in + --version | --vers* | -V ) + echo "$version" ; exit 0 ;; + --help | --h* | -h ) + echo "$usage"; exit 0 ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + exec >&2 + echo "$me: invalid option $1" + echo "$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit 0;; + + * ) + 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*) + 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) + os= + basic_machine=$1 + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -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/'` + ;; + -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. + tahoe | i860 | ia64 | m32r | m68k | m68000 | m88k | ns32k | arc | arm \ + | arme[lb] | armv* | pyramid | mn10200 | mn10300 | tron | a29k \ + | 580 | i960 | h8300 \ + | x86 | ppcbe | mipsbe | mipsle | shbe | shle | armbe | armle \ + | hppa | hppa1.0 | hppa1.1 | hppa2.0 | hppa2.0w | hppa2.0n \ + | hppa64 \ + | alpha | alphaev[4-8] | alphaev56 | alphapca5[67] \ + | alphaev6[78] \ + | we32k | ns16k | clipper | i370 | sh | sh[34] \ + | powerpc | powerpcle \ + | 1750a | dsp16xx | pdp11 | mips16 | mips64 | mipsel | mips64el \ + | mips64orion | mips64orionel | mipstx39 | mipstx39el \ + | mips64vr4300 | mips64vr4300el | mips64vr4100 | mips64vr4100el \ + | mips64vr5000 | miprs64vr5000el | mcore \ + | sparc | sparclet | sparclite | sparc64 | sparcv9 | v850 | c4x \ + | thumb | d10v | d30v | fr30 | avr) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | z8k | v70 | h8500 | w65 | pj | pjl) + ;; + + # 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[234567]86) + 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. + # FIXME: clean up the formatting here. + vax-* | tahoe-* | i[234567]86-* | i860-* | ia64-* | m32r-* | m68k-* | m68000-* \ + | m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | arm-* | c[123]* \ + | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \ + | power-* | none-* | 580-* | cray2-* | h8300-* | h8500-* | i960-* \ + | xmp-* | ymp-* \ + | x86-* | ppcbe-* | mipsbe-* | mipsle-* | shbe-* | shle-* | armbe-* | armle-* \ + | hppa-* | hppa1.0-* | hppa1.1-* | hppa2.0-* | hppa2.0w-* \ + | hppa2.0n-* | hppa64-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphapca5[67]-* \ + | alphaev6[78]-* \ + | we32k-* | cydra-* | ns16k-* | pn-* | np1-* | xps100-* \ + | clipper-* | orion-* \ + | sparclite-* | pdp11-* | sh-* | powerpc-* | powerpcle-* \ + | sparc64-* | sparcv9-* | sparc86x-* | mips16-* | mips64-* | mipsel-* \ + | mips64el-* | mips64orion-* | mips64orionel-* \ + | mips64vr4100-* | mips64vr4100el-* | mips64vr4300-* | mips64vr4300el-* \ + | mipstx39-* | mipstx39el-* | mcore-* \ + | f301-* | armv*-* | s390-* | sv1-* | t3e-* \ + | m88110-* | m680[01234]0-* | m683?2-* | m68360-* | z8k-* | d10v-* \ + | thumb-* | v850-* | d30v-* | tic30-* | c30-* | fr30-* \ + | bs2000-* | tic54x-* | c54x-*) + ;; + # 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 + ;; + 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 + ;; + 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 + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + 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 | ymp) + basic_machine=ymp-cray + os=-unicos + ;; + cray2) + basic_machine=cray2-cray + os=-unicos + ;; + [ctj]90-cray) + basic_machine=c90-cray + os=-unicos + ;; + crds | unos) + basic_machine=m68k-crds + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + 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 + ;; + 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[34567]86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i[34567]86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i[34567]86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i[34567]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 + ;; + i386-go32 | go32) + basic_machine=i386-unknown + os=-go32 + ;; + i386-mingw32 | mingw32) + basic_machine=i386-unknown + os=-mingw32 + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mipsel*-linux*) + basic_machine=mipsel-unknown + os=-linux-gnu + ;; + mips*-linux*) + basic_machine=mips-unknown + os=-linux-gnu + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + mmix*) + basic_machine=mmix-knuth + os=-mmixware + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + msdos) + basic_machine=i386-unknown + os=-msdos + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + 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 + ;; + np1) + basic_machine=np1-gould + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + 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 + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pentium | p5 | k5 | k6 | nexen) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon) + basic_machine=i686-pc + ;; + pentiumii | pentium2) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexen-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=rs6000-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/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sparclite-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=t3e-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + 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 + ;; + xmp) + basic_machine=xmp-cray + os=-unicos + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + z8k-*-coff) + basic_machine=z8k-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 + ;; + mips) + if [ x$os = x-linux-gnu ]; then + basic_machine=mips-unknown + else + basic_machine=mips-mips + fi + ;; + romp) + basic_machine=romp-ibm + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh3 | sh4) + base_machine=sh-unknown + ;; + sparc | sparcv9) + 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 + ;; + c4x*) + basic_machine=c4x-none + os=-coff + ;; + *) + 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. + -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* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ + | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i[34567]86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto*) + os=-nto-qnx + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -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 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -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) + os=-mint + ;; + -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 + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + 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 + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-ibm) + os=-aix + ;; + *-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 + ;; + f301-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 + ;; + -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 + ;; + -ptx*) + vendor=sequent + ;; + -vxsim* | -vxworks*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -*MiNT) + vendor=atari + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "version='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/lc-continuity/mk4/configure.in b/lc-continuity/mk4/configure.in new file mode 100644 index 0000000000000000000000000000000000000000..c9f9531aee90e3b47e0e82fb9d27c0f93e04434d --- /dev/null +++ b/lc-continuity/mk4/configure.in @@ -0,0 +1,27 @@ +AC_INIT(continuity/configure.in) + +AC_ARG_ENABLE(causality,dnl +[ --enable-causality Build Causality and associated modules], +docausality=yes) + +AC_CANONICAL_SYSTEM + +echo "target_cpu: $target_cpu" +echo "target_os: $target_os" + +case "$target_os" in +*) + MODS="modcommand moddb modhttp modsite modtcl modbeacon modimage modm3" + LIBS="lib/aura" + + if test "$docausality" = "yes" ; then + echo "Building w/ Causality" + LIBS="$LIBS lib/causality lib/causality-client" + MODS="$MODS" + fi +;; +esac + +AC_SUBST(MODS) +AC_SUBST(LIBS) +AC_OUTPUT(Makefile) diff --git a/lc-continuity/mk4/continuity/.cvsignore b/lc-continuity/mk4/continuity/.cvsignore new file mode 100644 index 0000000000000000000000000000000000000000..39915d09c959833f6fe3a780138e06f612558bbd --- /dev/null +++ b/lc-continuity/mk4/continuity/.cvsignore @@ -0,0 +1,5 @@ +autom4te.cache +configure +config.log +config.status +Makefile diff --git a/lc-continuity/mk4/continuity/CVS/Entries b/lc-continuity/mk4/continuity/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..9a1eb198bc828c965cbb35bbc5a10fa96b563698 --- /dev/null +++ b/lc-continuity/mk4/continuity/CVS/Entries @@ -0,0 +1,15 @@ +/.cvsignore/1.1/Thu Mar 11 01:11:48 2004//Tmk4_mod6_rc2 +/ChangeLog/1.23/Tue Dec 30 16:21:06 2003//Tmk4_mod6_rc2 +/Makefile.in/1.11/Wed May 19 19:49:55 2004//Tmk4_mod6_rc2 +/TODO/1.14/Fri May 21 20:53:44 2004//Tmk4_mod6_rc2 +/config.guess/1.1.1.1/Wed Oct 1 20:43:36 2003//Tmk4_mod6_rc2 +/config.sub/1.1.1.1/Wed Oct 1 20:43:36 2003//Tmk4_mod6_rc2 +/configure.in/1.30/Thu Jun 3 14:40:29 2004//Tmk4_mod6_rc2 +/install-sh/1.1.1.1/Wed Oct 1 20:43:36 2003//Tmk4_mod6_rc2 +/todoc/1.24/Thu May 13 14:11:25 2004//Tmk4_mod6_rc2 +D/bin//// +D/cont//// +D/include//// +D/lib//// +D/mecha//// +D/pcre//// diff --git a/lc-continuity/mk4/continuity/CVS/Repository b/lc-continuity/mk4/continuity/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..6470a57721ff6cba6261302410212f1cafb63b0a --- /dev/null +++ b/lc-continuity/mk4/continuity/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/continuity diff --git a/lc-continuity/mk4/continuity/CVS/Root b/lc-continuity/mk4/continuity/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/continuity/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/continuity/CVS/Tag b/lc-continuity/mk4/continuity/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/continuity/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/continuity/ChangeLog b/lc-continuity/mk4/continuity/ChangeLog new file mode 100644 index 0000000000000000000000000000000000000000..8f20ab7a01866b01e414be0ca9b30211ffc7cd75 --- /dev/null +++ b/lc-continuity/mk4/continuity/ChangeLog @@ -0,0 +1,659 @@ +# $Id: ChangeLog,v 1.23 2003/12/30 16:21:06 aleigh Exp $ + +- Mark 4 mod 1 rc3 + ++ Added lstFset_badd() + ++ Added memFdup() + +- Mark 4 mod 1 rc3 + +- Mark 4 mod 1 rc2 + ++ Added memFalloc, memFfree, memFrealloc in mecha. + ++ Converted bcopy() to memFcopy() in mecha. + ++ Converted bzero() to memFclear() in mecha. + ++ Changed #include directives in mecha to include the literal path. + +- Mark 4 mod 1 rc1 + ++ XML Parser now supports comments + ++ Added int utlFip_match(unsigned int ipa, unsigned int ipb, unsigned int netmask) + ++ Fixed an issue where bspFdestroy() could double-destruct a user data + pointer. + ++ Fixed an issue where a blank extension would trigger an assertion + in siteFfind_mimetype. + ++ New function xmlFcreate_list(); + ++ SSL support via OpenSSL Library + ++ Removed OpenBSD, FreeBSD configuration targets + ++ Removed old un-used functions checks from configure + ++ Changed utlFhttp_time_print() to be recursive. + ++ added mem.c + ++ Added dynFreset() + ++ Removed version information from mod/http + ++ Removed version information from mod/site + +- Mark 4 mod 0 + ++ Changed the format of the output line when a library is linked + ++ Solved a synchronization problem in the thread-pool. + ++ Added fleFget_size(), fleFload_file() + ++ Added strFis_whitespace() + ++ Removed old qry API + ++ Moved qryF* into qry.c + ++ Added netTreader *netFreader_init(void), void netFreader_free(netTreader *reader); + ++ disF* interface moved to dis.c + ++ Moved b64, bsp, bus, crc, dyn, fle, hsh, log, lst, rnd, str, thr, + tls, uid and utl to new "mechanism" library. + ++ pckF* interface moved to lst.c / lstF* + ++ uuidF* interface moved to uid.c / uidF* + ++ utlF* interface moved into utl.c + ++ hshFlist_* interface moved to hsh_dep.c + ++ utlFurl_encode() and utlFurl_decode() now return int status instead + of a pointer to the string. The encoded string can be found inside + the dynbuffer. + ++ Added dynFgetstr(), dynFgetlen() + ++ Seperated the lstFlist* code into lst_void.c + ++ strFdup() deprecated, strFcopy() instead. + ++ Changed types in networking functions; size_t -> ssize_t + ++ Disabled delayed-thread-creation in the thread pools. + +- Mark 3 mod 7 + ++ mod/php: Country-code now added as $_SERVER["country_code"] if present in the + transaction. + ++ Added hash iterator code. + ++ Added new code bus.c for a bus data structure. + ++ Added new raw hashing calls for hashing void pointers where + the object representing the name is not a text string. + ++ Added a new set of convinience hashing calls for dealing with + integer keys. + ++ Added mod/outboard, for two-task IPC processing. + ++ Added unsigned int rndFnumber (void) + ++ Added new IPC handling code built on the SysV message queue interface. + + + +- Mark 3 mod 6 + ++ Removed the annoying size debug message. + ++ Removed "did not find mime-type" message. + ++ Added _netFwritef which takes char *fmt, va_list + ++ Added httpFwritef() which takes *fmt, ... + ++ Code re-formatting and error message updating for tpool.c + ++ tpool now tracks in-use threads, and started threads, via the tpool structure. + ++ Removed dispatcher startup messages. + ++ Removed the triggering message on timeout sockets. + ++ Modified the thread-pool so that threads are only created when there are less than the max + number of configured threads, but, the no threads are available to process a work element. + Threads will still never be destroyed. This will allow people to set relatively high thread + maximums while only using the resources they actually need. + ++ Removed continuity startup broadcast messages. + ++ Removed mod/http short request message. + ++ Updated release header for http.h, which was missing httpFread() + ++ Removed mod/oracle checkin/checkout messages. + + + +- Mark 3 mod 5 + ++ Removed the pthread_cond functionality under LINUX for the startup wait. + instead the threads pin every 500ms checking the startup condition. On Linux + if threads go into pthread_cond_wait, then the process changes uid and triggers + the conditional, the blocked threads do not fire. + ++ Modified crt paths to support the Forte 7 compiler + ++ Checks for -lresolv, inet_aton() moved here + ++ New ip= option for dispatcher to set the bind IP. Defaults to + 0 (*) if unset in the configuration. + ++ Brought back BUG 10022 + ++ Fixed a problem in the php POST read function that was preventing + file upload from working properly. + + + +- Mark 3 mod 4 + + + Improved interior header files. + + + Removed a bug in hshFvoid_del() + + + Removed old dead ring code. + + + Started transitioning error messages to use sterror() + + + -Wall now default for GCC builds + + = Moved REQ_ constants from continuity.h into mod/http. + + + Added new transaction status REQ_HEADERSENT. + + = httpFstart_response no() longer sends the headers. + + + httpFhandler now calls httpFsend_response() if the transaction finishes + and the status is still REQ_STARTED. + + + Added netFwrite_two() and netFwritev() + + + mod/general do_error() now calls httpFsend_response() + + + reponse headers now arrive in same packet as the first data. + + + moved REQ_* and included new netF() functions in the release headers. + + + re-instituted TCP_NODELAY + + + I/O completly remodeled to use poll() and to guarantee read to worker threads + + + New profiling capability: define CAPI_PROFILE in continuity.h + + + New options for the dispatcher, threads and queue. + + + Failure to dlopen() a .so is now a fatal error. + + + +- Mark 3 mod 3 + + ID PRODUCT_OS SUBPRODUCT SDESC +---------- ---------- ---------- --------------------------------------------- + 10003 generic modhttp 404 needs to happen in send_file + 10009 darwin6.1 modphp php won't compile on OSX + 10011 generic modhttp docpath not documented + 10013 generic modhttp req_uri vanished + 10014 darwin6.2 continuity xfrFmmap does not work on OSX + + + +- Mark 3 mod 1 + + + +- Mark 3 Mod 0 + + + Added stub code for mod/tcl_http + + + Re-Introduced mod/tcl. Rewrote the module so that it supposed the concept + of Tcl Worlds, which allow for multiple things to use interpreter pools. + + + Introduced mod/voice, a VRU processing platform. + + + Moved the rdwr code from compat into core, as this is going to be used on all + the platforms due to semantical difficulties with the way the unlock function + is called. + + + Build makefile.in's now take care to ./configure + + + Deprecated the incr stat function. + + + mod/tcl now has a sketched out interface for multiple TCL worlds. + + + Cleaned up dispatcher to have a single interface. + + + continuity no longer takes the -p or -a options. + + + Removed all the modules from the build except for TCL. + The TCL module is going to be genericized to only offer + the TCL functionality without any HTTP functions. + + + Removed include/capi.h. This file is now deprecated. + The public module include will be continuity.h for the platform, + with the addition of http.h for the webserver functionality. + + + Removed balance.c and associated functions. + + + Removed qry functions that used qryTent. The lstTset interface + is now the only supported interface. + + + Removed dead symlink call from file.c + + + Removed http.c, and all functions from dl.c, net.c, xfer.c, etc that + referenced httpTtrans. + + + +- mk2 mod15 + + + Added client_read variable to the httpTtrans structure for keeping + track of post reads. + + + +- mk2 mod14 + + + Error dump page now contains the hostname. + + + Dialer now supports pgmid parameter. + + + +- 2.0.13 + + + New -u option for setting user. + + + dispatcher split up to setup / run phase, to allow + setuid activity after the ports are bound. + + + check-type strips trailing slashes. + + + New TCL command ta_http_query_get + + + httpTtrans now contains a new element. OLD MODULES + WILL HAVE TO BE RECOMPILED. + + + dynFappend() was not actually honoring len on copy. + + + HTTP 201 response was malformed. + + + Solaris target now is enabled for pre-fetching. + + + Continuity now has a single-shot build which provides marked + optimization performance. + + + utlFurl_decode now converts +'s into spaces + + + ID based messages, which will eventually be backed by some form of + loaded NLS. + + + Certain situations resulting in a valid result->error from TCL + that did not have a global error would result in a crash. + + + New mod/general function redirect_master, allowing for + site-level redirection. + + + New mod/general function travel_page which is a simple + virtual URL that will redirect to a provided URL. + + + New mod/general function ipsec_check which will allow for + site based IP access lists. + + + New mod/general function lower_uri which will take the URI + in t->vars and make it all lowercase for case insensitive + websites. + + + pthread_rwlock compatability interface now changed to be more + like the POSIX standard. rdwr calls are now not included unless + the pthread_rwlock interface is missing on the platform. + + + +- 2.0.12 + + + New tav_ vector TCL commands. + + + Fixed broken BSP subsystem. + + + Introduced new hsh.c void interface that will eventually + replace the old API. + + + if-modified-since and last-modified now work properly + with sendfile + + + mod/tcl now traps init script errors. + + + mod/tcl all aspects of TCL error trapping are now useful and + verbose, TCL script backtraces are provided. + + + dl.c no longer logs loaded shared library loads. + + + TCL now does the right thing in regards to TLS. + + + Unbroke TLS/Oracle. + + + tls now uses UUID for memory handle. + + + Created a thread to run the mmap cleanup every 60 seconds. This will + prevent the server from accumulating maps over time. + + + Fixed an overflow in the UUID handler which could cause a crash. + + + +- 2.0.11 + + + mod/beacon now adds memory information to tasF (Solaris) + + + mod/beacon now adds CPU metrics (Solaris) + + + Added w_err_eagain, w_err_estale, and w_err_epipe counters + in net.0 + + + +- 2.0.10 + + + Changed the http short request error to a warning. + + + mod/general's logging format is changed back to match + CDP's 1.1 by the inclusion of two placeholder values. + + + mod/general now creates access log files that always have + two digit values for day and year. + + + mod/general now appends the hostname of the machine on the end + of the access log. + + + Additional changes to support 64-bits. + + + Fixed broken dispatcher behavior which was causing the server + to pipeline. + + + httpFparse now URL decodes the path parameter before inserting + it into t->vars + + + +- 2.0.9 + + + Replaced dynamic memory handling in the TCL commands + + + I/O is now non-blocking + + + Added mod/beacon + + + Modifications for 64-bit + + + Added a statistics interface for use with the rrd + tool, and other applications. + + + New TCL commands: ta_urlencode, ta_urldecode + + + +- 2.0.8 + + + mod/general, created do_404 for generic 404 handling. find_index + will now 404 if the request was for a directory but no matching + index pages were found. + + + Added a new module, mod/image, which is essnetially libjpeg + with some TCL binder functions. + + + tclFinit now takes arg init= which specifies tcl loadfile + + + New TCL commands: ta_db_open, ta_db_select, ta_db_getrow, + ta_jpg_getsize + + + Removed broken and useless structure defenitions from tcl_pub.h + + + Restructured the TLS system to take dynamic cleanup handlers, + and to allocate the classes at runtime. + + + Added a select() timeout function for the reads, 5 seconds. + + + Removed the extra trailing space from utlFlocal_time(). + + + Introduced cdog watchdog program. + + + +- 2.0.7 + + + Log output now includes time. + + + Fixed a bug in commonlog that would cause the timezone offset + to appear as a random, corrupted string. + + + mod/general now exits at startup if it cannot load the + instance.cfg. + + + Hardened http parser. + + + Added new functions qryFlst_parse(), utlFurl_encode(), + utlFurl_decode(), dynFfree(), utlFlocal_time(), uuidFgenerate_str() + + + Added new TCL functions: tcl_http_var_set, tcl_http_res_set, + tcl_http_req_set, ta_pwd, ta_http_vars_get, ta_http_req_get, + ta_http_res_get. + + + Fixed a structure containment problem in mod/tcl, due to an + improper assignment with dyn command. Thanks eric. + + + Fixed a leak. The handler has to free the passed disTconn + structure. + + + Added dynFappend_print() + + + Moved back to an emphasis on shlibs, with RTLD_GLOBAL on + Linux and Solaris allowing x-calls between modules. + + + MMC system now logs %d/errno rather than %m + + + MMC system now logs the logFmsg() service rather than logging + errors to syslog. + + + t->vars:path is now cleaned of extra slashes before it's added + to the set. + + + Removed an extra space after the time from the mod/general + access log. + + + OpenBSD port is being dropped because their linker does not support + --no-whole-archive, which breaks the continuity link. + + + Re-Organized distribution, with bin, lib, and include directories. + + + Added a new function, dlFmap_funcs that can be called from the + module.cfg with a funcs= argument. This will map functions from + RTLD_DEFAULT, rather than a shared library. This is required to + call functions in the core build from the module.cfg + + + Moved to .a compilation format. On installation the end-user + will perform the final link step. This allows for linking + against arbitrary end-user libraries, as well as providing a + mechanism to allow the libraries to cross-call one another without + the performance penalties or hassles of going through dlsym. + + + mod/tcl is now included in the standard distribution. + + + send_file now returns the content-length. + + + mod/tcl is now functional for embedded pages. + + + Added proper functiond decl's to stat.h + + + Moved mod/tcl source in. + + + Added mod/oracle, and OCI based Oracle interface library. + + + +- 2.0.6 (v2.00 p6) + + + Changing version numbering to a more realistic style. + + + Modified build message. Continuity is now + "Continuity Enterprise Edition". Build message also now + reflects Production/Development and 320-bit/64-bit. + + + Modified the server variable on the return HTTP response + to include the version number rather than a hardcoded 2.00 + + + Generalized the dispatcher so that alternative handlers + can be registered. + + + +- v2.00 p5 + + + Added ability for modules to get transaction with + httpFthread_gettrans(void). This is implemented through TLS + and was required for modtcl. + + + Changed the req_line buffer in httpFparse to 1k. + + + Added netFwrite() as documented. + + + removed dietlibc options from configure + + + t->cli_ipv4_address is now guaranteed to be host order. This was + causing problems with the logs on little endian platforms. + + + utlFip_to_str was not formatting the IP address properly. + + + Number of threads and runq size are now tunable from module.cfg using + set_option. The parameters are "threads" and "runq_size". + + + New global configuration calls, get_option and set_option. + + + +- v2.00 p4 + + + continuity now supports the -a option, for binding to a specific IP + address. + + + The list code had two issues: one, it was losing entries on realloc + and it was over-freeing one entry. Well. realloc() with mtmalloc is still + broken. Here's the deal, at this point I think mtmalloc is just fucked + after you realloc() memory and it changes it out from under you. This is + too bad because mtmalloc is really fast. + + + httpFparse was not properly storing the HTTP request variables + in t->req_hdrs, problems such as spacing and cutting values at the ':' + + + mod/general now looks for group.siteid instead of siteid.group + + + Hard 404 page now sets the type as text/html + + + Fixed the return values from httpFparse, which was possible causing + bad requests to make it through to processing. + + + mod/general now includes find_index, which will for a configured list + of index pages for requests that are directories. + + + mod/general no longer tries to log the country code for the request. + The ccode is only present when mod/iplk is running, and mod/iplk is + proprietary to CyberDataProcessing. + + + Moved the WLOG call into the http handler from the http + cleanup code, because WLOG was being called for aborted + and broken connections. + + + On OpenBSD, thrFsleep() now locks the mutex before calling + pthread_cond_timeout. Apparently OBSd requires the mutex be + locked, or, it returns EINVAL. + + + accept() trapping eith EINTR will call intr_handler() on OpenBSD. This is + so that ctl+c will interrupt the running process properly. + + + Modified the way the fputs weirdness trap works in mod/general/log.c + + + +- v2.00 p3 + + + PHP4 no longer leaks. + + + Significantly improved the thread pooling performance. + + + removed cache miss message from utlFtime + + + Thread pooling is now the default. This is generally a good idea, + I suppose, but it's basically being required by PHP which can't + deal with threads that are destroyed. + + + dl.c will now try preprending _ to the function names if they are not + found. This helps on platforms like openbsd which insist on putting a + leading underscore in the fn names for shared libraries. + + + No longer trying to use sigignore at all. + + + find_pathinfo now sets the type to internal/directory for directories, + regardless of extension. + + + find_pathinfo will now 302 uri's for directories that are missing their + trailing / + + + Linux builds now sense mmap() properly. Before they were using a read() + loop as a fallback, causing horrible performance. + + + mod/general/log.c was expecting fputs() to be the num bytes written. + On Linux, this just seems to return 1 on success. #ifdef'd around the + return check. + + + +- v2.00 p2 + + + dl now honors type= setting for the service functions. The function + will only run if the type for the request is in the comma seperated list. + To run for all types, do not specify type. + + + pathinfo now returns a hard 404 error when the stat() fails. + + + trans now carries started, which indicates at which point the request + is at. Dispatch won't run the obj or service classes unless started + is 0. + + + Source now uses capi.h, the public API header file. Duplicate + defenitions removed from the other headers. + + + Added an -enable-diet target, which is broken, because + diet-libc SUCKS AND MUST BE DESTROYED + + + Inclusion of strings.h is now based on configure. strings.h + is discouraged by diet libc on Linux. + + + xfr.c no longer uses pwrite, because pwrite()ing a socket under + RH7 is not legal, and it was pointless anyways. + + + -c now works properly rather than opening "module.cfg" regardless. + +- v2.00 p1 diff --git a/lc-continuity/mk4/continuity/Makefile.in b/lc-continuity/mk4/continuity/Makefile.in new file mode 100644 index 0000000000000000000000000000000000000000..faa0fab5fd0cf9bdca4c5d06e9f5c5af54aa976d --- /dev/null +++ b/lc-continuity/mk4/continuity/Makefile.in @@ -0,0 +1,33 @@ +# $Id: Makefile.in,v 1.11 2004/05/19 19:49:55 aleigh Exp $ + +world: pcre/Makefile + (cd pcre ; $(MAKE)) + (cd mecha ; $(MAKE)) + (cd cont ; $(MAKE)) + +clean: + (cd mecha ; $(MAKE) clean) + (cd cont ; $(MAKE) clean) + +realclean: clean + (cd pcre; $(MAKE) clean) + + +pcre/Makefile: + (cd pcre; ./configure); + +count: + (find . -name '*.[ch]' | xargs wc -l) + +dist: world + mkdir -p dist/bin + mkdir -p dist/lib + mkdir -p dist/include + cp bin/continuity bin/cdog dist/bin + cp bin/*-dist dist/bin + cp -r include/*.h dist/include + cp -r lib/*.a lib/*.so lib/env.mk lib/build.mk lib/*.xml dist/lib +depend: + (cd mecha ; $(MAKE) depend) + (cd cont ; $(MAKE) depend) + diff --git a/lc-continuity/mk4/continuity/TODO b/lc-continuity/mk4/continuity/TODO new file mode 100644 index 0000000000000000000000000000000000000000..2d76aa7796169169534a479d3807c4427c3fd04f --- /dev/null +++ b/lc-continuity/mk4/continuity/TODO @@ -0,0 +1,3 @@ +$Header: /san01/cvs/ashpool/csrc/continuity/TODO,v 1.14 2004/05/21 20:53:44 aleigh Exp $ + +Excessively long URLs do not generate a protocol error. diff --git a/lc-continuity/mk4/continuity/bin/.cvsignore b/lc-continuity/mk4/continuity/bin/.cvsignore new file mode 100644 index 0000000000000000000000000000000000000000..38dc3a683c89747dd5f84a2fce922b99061b1d19 --- /dev/null +++ b/lc-continuity/mk4/continuity/bin/.cvsignore @@ -0,0 +1,2 @@ +continuity +cdog diff --git a/lc-continuity/mk4/continuity/bin/CVS/Entries b/lc-continuity/mk4/continuity/bin/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..b8c0cc28dce4c23b4509f2d89a1845b4bbb10ffd --- /dev/null +++ b/lc-continuity/mk4/continuity/bin/CVS/Entries @@ -0,0 +1,13 @@ +/.cvsignore/1.1/Thu Mar 11 01:11:48 2004//Tmk4_mod6_rc2 +/base.xml/1.4/Tue Jun 22 15:54:36 2004//Tmk4_mod6_rc2 +/beacon.xml/1.3/Wed May 12 14:37:52 2004//Tmk4_mod6_rc2 +/config.xml/1.27/Sun May 16 20:29:59 2004//Tmk4_mod6_rc2 +/config.xml-dist/1.6/Wed May 12 15:20:48 2004//Tmk4_mod6_rc2 +/dotnet.xml/1.3/Tue Jun 22 15:54:36 2004//Tmk4_mod6_rc2 +/dynamo.xml/1.6/Tue Feb 24 04:38:42 2004//Tmk4_mod6_rc2 +/harmony.xml/1.5/Wed May 12 14:29:44 2004//Tmk4_mod6_rc2 +/phpdev.xml/1.5/Tue Feb 24 04:38:42 2004//Tmk4_mod6_rc2 +/radius.xml/1.4/Fri May 14 15:21:24 2004//Tmk4_mod6_rc2 +/ssl.xml/1.3/Sun May 16 20:29:59 2004//Tmk4_mod6_rc2 +/winkfep.xml/1.10/Tue Jun 22 15:54:36 2004//Tmk4_mod6_rc2 +D diff --git a/lc-continuity/mk4/continuity/bin/CVS/Repository b/lc-continuity/mk4/continuity/bin/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..01b86c53b05bfbbee75e23261c176c2d918e11b1 --- /dev/null +++ b/lc-continuity/mk4/continuity/bin/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/continuity/bin diff --git a/lc-continuity/mk4/continuity/bin/CVS/Root b/lc-continuity/mk4/continuity/bin/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/continuity/bin/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/continuity/bin/CVS/Tag b/lc-continuity/mk4/continuity/bin/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/continuity/bin/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/continuity/bin/base.xml b/lc-continuity/mk4/continuity/bin/base.xml new file mode 100644 index 0000000000000000000000000000000000000000..1fbffa2eb42396c68150618f4e0ff04eb68a6ae7 --- /dev/null +++ b/lc-continuity/mk4/continuity/bin/base.xml @@ -0,0 +1,236 @@ + + + + + + ../lib/http + ../lib/cmd + ../lib/site + ../lib/beacon + + + + + + + + + 8000 + httpFhandler + + + + + + + + + + Sites + + + index.html,index.php + + + + + + + text/plain + + + + + + + + + + + + + + + + /tmp + + + + /web/content/_default/_default + http://www.postfin.com/ + + + + + + + application/postscript + audio/x-aiff + audio/x-aiff + audio/x-aiff + application/x-aim + application/astound + application/x-asap + audio/basic + video/msvideo + application/octet-stream + image/bmp + application/x-netcdf + internal/cgi + application/x-fortezza-ckl + application/java-vm + application/x-cpio + application/x-mscardfile + application/x-pkcs7-crl + application/x-csh + text/css + application/msword + application/x-dot + drawing/x-dwf + image/vng + dynamo-internal/template + dynamo-internal/dynjava + application/pre-encrypted + application/postscript + audio/echospeech + audio/echospeech + application/x-earthtime + text/x-setext + application/x-envoy + image/fif + application/x-maker + video/isivideo + image/gif + application/x-gtar + application/x-hdf + application/winhlp + application/mac-binhex40 + text/html + text/html + x-conference/x-cooltalk + image/ief + image/ifs + internal/php4 + application/x-NET-Install + application/java-archive + image/jpeg + dynamo-internal/html + dynamo-internal/html + image/jpeg + image/jpeg + image/jpeg + application/x-javascript + application/x-javascript-config + application/x-javascript;charset=UTF + dynamo-internal/plain + dynamo-internal/plain + audio/x-liveaudio + application/x-latex + application/fastman + application/x-msmediaview + application/x-msmediaview + application/x-troff-man + dynamo-internal/map + application/mbedlet + application/x-msaccess + application/x-troff-me + application/x-mif + audio/mid + audio/midi + application/x-mif + application/x-msmoney + application/x-mocha + application/x-mocha + video/quicktime + video/x-sgi-movie + video/quicktime + video/x-mpeg2 + video/mpeg + video/mpeg + video/mpeg + video/mpeg + video/x-mpeg2 + video/mpeg + application/x-troff-ms + application/x-netcdf + application/oda + audio/x-pac + audio/x-epac + image/x-portable-bitmap + image/x-photo-cd + application/pdf + image/x-portable-graymap + internal/php4 + image/jpeg + image/jpeg + application/x-pl + image/png + image/x-portable-anymap + application/vnd.ms-powerpoint + image/x-portable_pixmap + application/vnd.ms-powerpoint + application/vnd.ms-powerpoint + application/x-ns-proxy-autoconfig + application/postscript + application/x-mspublisher + video/quicktime + audio/x-pn-realaudio + audio/x-pn-realaudio + image/x-cmu-raster + image/x-rgb + application/x-troff + application/msword + text/richtext + application/x-msschedule + application/java-serialized-object + application/x-sh + application/x-shar + application/x-stuffit + x-salsa + application/studiom + application/astround + audio/basic + application/x-sprite + application/x-sprite + application/x-wais-source + image/vng + x-world/x-svr + text/x-speech + application/x-troff + application/x-tar + application/x-timbuktu + application/timbuktu + internal/tcl + application/x-tex + application/x-texinfo + application/x-texinfo + image/tiff + image/tiff + application/x-tkined + application/x-tkined + application/x-troff + application/x-msterminal + text/tab-seperated-values + video/mpeg + video/vivo + video/vivo + x-world/x-vrt + audio/x-wav + application/msword + application/x-msmetafile + x-world/x-vrml + video/wavelet + image/x-xbitmap + application/vnd.ms-excel + application/vnd.ms-excel + application/vnd.ms-excel + application/vnd.ms-excel + application/vnd.ms-excel + application/vnd.ms-excel + image/x-xpixmap + image/x-xwindowdump + application/zip + + + diff --git a/lc-continuity/mk4/continuity/bin/beacon.xml b/lc-continuity/mk4/continuity/bin/beacon.xml new file mode 100644 index 0000000000000000000000000000000000000000..91b1dd8f54628c12fb8044f18d73f112e184c4ec --- /dev/null +++ b/lc-continuity/mk4/continuity/bin/beacon.xml @@ -0,0 +1,32 @@ + + + + ../lib/http + ../lib/beacon + + + + + + 8 + 8000 + httpFhandler + + + + + + + + + + + + + + + + + + + diff --git a/lc-continuity/mk4/continuity/bin/config.xml b/lc-continuity/mk4/continuity/bin/config.xml new file mode 100644 index 0000000000000000000000000000000000000000..e1d067fe4f01321daee604701c960a2608250b73 --- /dev/null +++ b/lc-continuity/mk4/continuity/bin/config.xml @@ -0,0 +1,221 @@ + + + + + + ../lib/cmd + ../lib/http + ../lib/site + + + + + + 5 + 8000 + + + + + 5 + 8000 + httpFhandler + + + + + + + + + + + + + + + + + + + + + /tmp + + + + /web/content/_default/_default + http://www.postfin.com/ + + + + application/postscript + audio/x-aiff + audio/x-aiff + audio/x-aiff + application/x-aim + application/astound + application/x-asap + audio/basic + video/msvideo + application/octet-stream + image/bmp + application/x-netcdf + internal/cgi + application/x-fortezza-ckl + application/java-vm + application/x-cpio + application/x-mscardfile + application/x-pkcs7-crl + application/x-csh + text/css + application/msword + application/x-dot + drawing/x-dwf + image/vng + dynamo-internal/template + dynamo-internal/dynjava + application/pre-encrypted + application/postscript + audio/echospeech + audio/echospeech + application/x-earthtime + text/x-setext + application/x-envoy + image/fif + application/x-maker + video/isivideo + image/gif + application/x-gtar + application/x-hdf + application/winhlp + application/mac-binhex40 + text/html + text/html + x-conference/x-cooltalk + image/ief + image/ifs + internal/php4 + application/x-NET-Install + application/java-archive + image/jpeg + dynamo-internal/html + dynamo-internal/html + image/jpeg + image/jpeg + image/jpeg + application/x-javascript + application/x-javascript-config + application/x-javascript;charset=UTF + dynamo-internal/plain + dynamo-internal/plain + audio/x-liveaudio + application/x-latex + application/fastman + application/x-msmediaview + application/x-msmediaview + application/x-troff-man + dynamo-internal/map + application/mbedlet + application/x-msaccess + application/x-troff-me + application/x-mif + audio/mid + audio/midi + application/x-mif + application/x-msmoney + application/x-mocha + application/x-mocha + video/quicktime + video/x-sgi-movie + video/quicktime + video/x-mpeg2 + video/mpeg + video/mpeg + video/mpeg + video/mpeg + video/x-mpeg2 + video/mpeg + application/x-troff-ms + application/x-netcdf + application/oda + audio/x-pac + audio/x-epac + image/x-portable-bitmap + image/x-photo-cd + application/pdf + image/x-portable-graymap + internal/php4 + image/jpeg + image/jpeg + application/x-pl + image/png + image/x-portable-anymap + application/vnd.ms-powerpoint + image/x-portable_pixmap + application/vnd.ms-powerpoint + application/vnd.ms-powerpoint + application/x-ns-proxy-autoconfig + application/postscript + application/x-mspublisher + video/quicktime + audio/x-pn-realaudio + audio/x-pn-realaudio + image/x-cmu-raster + image/x-rgb + application/x-troff + application/msword + text/richtext + application/x-msschedule + application/java-serialized-object + application/x-sh + application/x-shar + application/x-stuffit + x-salsa + application/studiom + application/astround + audio/basic + application/x-sprite + application/x-sprite + application/x-wais-source + image/vng + x-world/x-svr + text/x-speech + application/x-troff + application/x-tar + application/x-timbuktu + application/timbuktu + internal/tcl + application/x-tex + application/x-texinfo + application/x-texinfo + image/tiff + image/tiff + application/x-tkined + application/x-tkined + application/x-troff + application/x-msterminal + text/tab-seperated-values + video/mpeg + video/vivo + video/vivo + x-world/x-vrt + audio/x-wav + application/msword + application/x-msmetafile + x-world/x-vrml + video/wavelet + image/x-xbitmap + application/vnd.ms-excel + application/vnd.ms-excel + application/vnd.ms-excel + application/vnd.ms-excel + application/vnd.ms-excel + application/vnd.ms-excel + image/x-xpixmap + image/x-xwindowdump + application/zip + + + diff --git a/lc-continuity/mk4/continuity/bin/config.xml-dist b/lc-continuity/mk4/continuity/bin/config.xml-dist new file mode 100644 index 0000000000000000000000000000000000000000..52edc2dbc40c243858115e36d020e76278439de8 --- /dev/null +++ b/lc-continuity/mk4/continuity/bin/config.xml-dist @@ -0,0 +1,228 @@ + + + + ../lib/cmd + ../lib/http + ../lib/site + + + + + + 8000 + httpFhandler + + + + + + + + + Sites + + + index.html,index.php + + + + + + + text/plain + + + + + + + + + + + + + + + + + /web/logs + + + + /Users/aleigh/public_html + + foo.com + + + + + application/postscript + audio/x-aiff + audio/x-aiff + audio/x-aiff + application/x-aim + application/astound + application/x-asap + audio/basic + video/msvideo + application/octet-stream + image/bmp + application/x-netcdf + internal/cgi + application/x-fortezza-ckl + application/java-vm + application/x-cpio + application/x-mscardfile + application/x-pkcs7-crl + application/x-csh + text/css + application/msword + application/x-dot + drawing/x-dwf + image/vng + dynamo-internal/template + dynamo-internal/dynjava + application/pre-encrypted + application/postscript + audio/echospeech + audio/echospeech + application/x-earthtime + text/x-setext + application/x-envoy + image/fif + application/x-maker + video/isivideo + image/gif + application/x-gtar + application/x-hdf + application/winhlp + application/mac-binhex40 + text/html + text/html + x-conference/x-cooltalk + image/ief + image/ifs + internal/php4 + application/x-NET-Install + application/java-archive + image/jpeg + dynamo-internal/html + dynamo-internal/html + image/jpeg + image/jpeg + image/jpeg + application/x-javascript + application/x-javascript-config + application/x-javascript;charset=UTF + dynamo-internal/plain + dynamo-internal/plain + audio/x-liveaudio + application/x-latex + application/fastman + application/x-msmediaview + application/x-msmediaview + application/x-troff-man + dynamo-internal/map + application/mbedlet + application/x-msaccess + application/x-troff-me + application/x-mif + audio/mid + audio/midi + application/x-mif + application/x-msmoney + application/x-mocha + application/x-mocha + video/quicktime + video/x-sgi-movie + video/quicktime + video/x-mpeg2 + video/mpeg + video/mpeg + video/mpeg + video/mpeg + video/x-mpeg2 + video/mpeg + application/x-troff-ms + application/x-netcdf + application/oda + audio/x-pac + audio/x-epac + image/x-portable-bitmap + image/x-photo-cd + application/pdf + image/x-portable-graymap + internal/php4 + image/jpeg + image/jpeg + application/x-pl + image/png + image/x-portable-anymap + application/vnd.ms-powerpoint + image/x-portable_pixmap + application/vnd.ms-powerpoint + application/vnd.ms-powerpoint + application/x-ns-proxy-autoconfig + application/postscript + application/x-mspublisher + video/quicktime + audio/x-pn-realaudio + audio/x-pn-realaudio + image/x-cmu-raster + image/x-rgb + application/x-troff + application/msword + text/richtext + application/x-msschedule + application/java-serialized-object + application/x-sh + application/x-shar + application/x-stuffit + x-salsa + application/studiom + application/astround + audio/basic + application/x-sprite + application/x-sprite + application/x-wais-source + image/vng + x-world/x-svr + text/x-speech + application/x-troff + application/x-tar + application/x-timbuktu + application/timbuktu + internal/tcl + application/x-tex + application/x-texinfo + application/x-texinfo + image/tiff + image/tiff + application/x-tkined + application/x-tkined + application/x-troff + application/x-msterminal + text/tab-seperated-values + video/mpeg + video/vivo + video/vivo + x-world/x-vrt + audio/x-wav + application/msword + application/x-msmetafile + x-world/x-vrml + video/wavelet + image/x-xbitmap + application/vnd.ms-excel + application/vnd.ms-excel + application/vnd.ms-excel + application/vnd.ms-excel + application/vnd.ms-excel + application/vnd.ms-excel + image/x-xpixmap + image/x-xwindowdump + application/zip + + + diff --git a/lc-continuity/mk4/continuity/bin/dotnet.xml b/lc-continuity/mk4/continuity/bin/dotnet.xml new file mode 100644 index 0000000000000000000000000000000000000000..30ae8c47535d55eaadb8b404f7e229652291de8a --- /dev/null +++ b/lc-continuity/mk4/continuity/bin/dotnet.xml @@ -0,0 +1,246 @@ + + + + ../lib/http + ../lib/cmd + ../lib/site + ../lib/modmobility + + + + + + 1 + 8000 + + + + 1 + 8000 + httpFhandler + 64 + + + + + + + + + + index.html,index.aspx,index.cgi,index.php + + + + + + + text/plain + + + + + + internal/asp-net + /opt/mono/bin/mono --debug modmono.exe + + + internal/cgi + modcgi + + + + + + + + + + + + + + + /www/logs/w2.5stops.com + + + + /web/content/ta/postfin + + + + application/postscript + audio/x-aiff + audio/x-aiff + audio/x-aiff + application/x-aim + application/astound + application/x-asap + audio/basic + video/msvideo + application/octet-stream + image/bmp + application/x-netcdf + internal/cgi + application/x-fortezza-ckl + application/java-vm + application/x-cpio + application/x-mscardfile + application/x-pkcs7-crl + application/x-csh + text/css + application/msword + application/x-dot + drawing/x-dwf + image/vng + dynamo-internal/template + dynamo-internal/dynjava + application/pre-encrypted + application/postscript + audio/echospeech + audio/echospeech + application/x-earthtime + text/x-setext + application/x-envoy + image/fif + application/x-maker + video/isivideo + image/gif + application/x-gtar + application/x-hdf + application/winhlp + application/mac-binhex40 + text/html + text/html + x-conference/x-cooltalk + image/ief + image/ifs + internal/php4 + application/x-NET-Install + application/java-archive + image/jpeg + dynamo-internal/html + dynamo-internal/html + image/jpeg + image/jpeg + image/jpeg + application/x-javascript + application/x-javascript-config + application/x-javascript;charset=UTF + dynamo-internal/plain + dynamo-internal/plain + audio/x-liveaudio + application/x-latex + application/fastman + application/x-msmediaview + application/x-msmediaview + application/x-troff-man + dynamo-internal/map + application/mbedlet + application/x-msaccess + application/x-troff-me + application/x-mif + audio/mid + audio/midi + application/x-mif + application/x-msmoney + application/x-mocha + application/x-mocha + video/quicktime + video/x-sgi-movie + video/quicktime + video/x-mpeg2 + video/mpeg + video/mpeg + video/mpeg + video/mpeg + video/x-mpeg2 + video/mpeg + application/x-troff-ms + application/x-netcdf + application/oda + audio/x-pac + audio/x-epac + image/x-portable-bitmap + image/x-photo-cd + application/pdf + image/x-portable-graymap + internal/php4 + image/jpeg + image/jpeg + application/x-pl + image/png + image/x-portable-anymap + application/vnd.ms-powerpoint + image/x-portable_pixmap + application/vnd.ms-powerpoint + application/vnd.ms-powerpoint + application/x-ns-proxy-autoconfig + application/postscript + application/x-mspublisher + video/quicktime + audio/x-pn-realaudio + audio/x-pn-realaudio + image/x-cmu-raster + image/x-rgb + application/x-troff + application/msword + text/richtext + application/x-msschedule + application/java-serialized-object + application/x-sh + application/x-shar + application/x-stuffit + x-salsa + application/studiom + application/astround + audio/basic + application/x-sprite + application/x-sprite + application/x-wais-source + image/vng + x-world/x-svr + text/x-speech + application/x-troff + application/x-tar + application/x-timbuktu + application/timbuktu + internal/tcl + application/x-tex + application/x-texinfo + application/x-texinfo + image/tiff + image/tiff + application/x-tkined + application/x-tkined + application/x-troff + application/x-msterminal + text/tab-seperated-values + video/mpeg + video/vivo + video/vivo + x-world/x-vrt + audio/x-wav + application/msword + application/x-msmetafile + x-world/x-vrml + video/wavelet + image/x-xbitmap + application/vnd.ms-excel + application/vnd.ms-excel + application/vnd.ms-excel + application/vnd.ms-excel + application/vnd.ms-excel + application/vnd.ms-excel + image/x-xpixmap + image/x-xwindowdump + application/zip + + internal/asp-net + internal/asp-net + internal/asp-net + internal/asp-net + + + + diff --git a/lc-continuity/mk4/continuity/bin/dynamo.xml b/lc-continuity/mk4/continuity/bin/dynamo.xml new file mode 100644 index 0000000000000000000000000000000000000000..a0d92736feb7bc74ec7ee9342ee260f1df263fb2 --- /dev/null +++ b/lc-continuity/mk4/continuity/bin/dynamo.xml @@ -0,0 +1,239 @@ + + + + ../lib/http.so + ../lib/site.so + ../lib/dynamo.so + + + + + + + + 10.2.2.97 + 8880 + + + 8000 + httpFhandler + + + + + + + + + index.html,index.php,index.jhtml + + + + + + + text/plain + + + + + + dynamo-internal/html + + + dynamo-internal/template + + + dynamo-internal/plain + + + dynamo-internal/map + + + + + + + + + + + + + /web/logs + + + + /web02/content/lexitrans/sitecancel/ + + + + application/postscript + audio/x-aiff + audio/x-aiff + audio/x-aiff + application/x-aim + application/astound + application/x-asap + audio/basic + video/msvideo + application/octet-stream + image/bmp + application/x-netcdf + internal/cgi + application/x-fortezza-ckl + application/java-vm + application/x-cpio + application/x-mscardfile + application/x-pkcs7-crl + application/x-csh + application/x-pointplus + application/msword + application/x-dot + drawing/x-dwf + image/vng + dynamo-internal/template + dynamo-internal/dynjava + application/pre-encrypted + application/postscript + audio/echospeech + audio/echospeech + application/x-earthtime + text/x-setext + application/x-envoy + image/fif + application/x-maker + video/isivideo + image/gif + application/x-gtar + application/x-hdf + application/winhlp + application/mac-binhex40 + text/html + text/html + x-conference/x-cooltalk + image/ief + image/ifs + internal/php4 + application/x-NET-Install + application/java-archive + image/jpeg + dynamo-internal/html + dynamo-internal/html + image/jpeg + image/jpeg + image/jpeg + application/x-javascript + application/x-javascript-config + application/x-javascript;charset=UTF + dynamo-internal/plain + dynamo-internal/plain + audio/x-liveaudio + application/x-latex + application/fastman + application/x-msmediaview + application/x-msmediaview + application/x-troff-man + dynamo-internal/map + application/mbedlet + application/x-msaccess + application/x-troff-me + application/x-mif + audio/mid + audio/midi + application/x-mif + application/x-msmoney + application/x-mocha + application/x-mocha + video/quicktime + video/x-sgi-movie + video/quicktime + video/x-mpeg2 + video/mpeg + video/mpeg + video/mpeg + video/mpeg + video/x-mpeg2 + video/mpeg + application/x-troff-ms + application/x-netcdf + application/oda + audio/x-pac + audio/x-epac + image/x-portable-bitmap + image/x-photo-cd + application/pdf + image/x-portable-graymap + internal/php4 + image/jpeg + image/jpeg + application/x-pl + image/png + image/x-portable-anymap + application/vnd.ms-powerpoint + image/x-portable_pixmap + application/vnd.ms-powerpoint + application/vnd.ms-powerpoint + application/x-ns-proxy-autoconfig + application/postscript + application/x-mspublisher + video/quicktime + audio/x-pn-realaudio + audio/x-pn-realaudio + image/x-cmu-raster + image/x-rgb + application/x-troff + application/msword + text/richtext + application/x-msschedule + application/java-serialized-object + application/x-sh + application/x-shar + application/x-stuffit + x-salsa + application/studiom + application/astround + audio/basic + application/x-sprite + application/x-sprite + application/x-wais-source + image/vng + x-world/x-svr + text/x-speech + application/x-troff + application/x-tar + application/x-timbuktu + application/timbuktu + internal/tcl + application/x-tex + application/x-texinfo + application/x-texinfo + image/tiff + image/tiff + application/x-tkined + application/x-tkined + application/x-troff + application/x-msterminal + text/tab-seperated-values + video/mpeg + video/vivo + video/vivo + x-world/x-vrt + audio/x-wav + application/msword + application/x-msmetafile + x-world/x-vrml + video/wavelet + image/x-xbitmap + application/vnd.ms-excel + application/vnd.ms-excel + application/vnd.ms-excel + application/vnd.ms-excel + application/vnd.ms-excel + application/vnd.ms-excel + image/x-xpixmap + image/x-xwindowdump + application/zip + + + diff --git a/lc-continuity/mk4/continuity/bin/harmony.xml b/lc-continuity/mk4/continuity/bin/harmony.xml new file mode 100644 index 0000000000000000000000000000000000000000..0d26f18f191a1205ab3877c10e2843419b34e198 --- /dev/null +++ b/lc-continuity/mk4/continuity/bin/harmony.xml @@ -0,0 +1,244 @@ + + + + + + ../lib/cmd + ../lib/http + ../lib/site + ../lib/harmony + + + + + aleighf00 + + 5 + 8000 + + + + 5 + 8000 + httpFhandler + + + + 8001 + cmdFhandler + + + 5050 + + + + + + + + Sites + + + index.html,index.php + + + + + + + text/plain + + + + + + + + + + + + + + + + /tmp + + + + /web/content/_default/_default + http://www.postfin.com/ + www.test.com + + + + application/postscript + audio/x-aiff + audio/x-aiff + audio/x-aiff + application/x-aim + application/astound + application/x-asap + audio/basic + video/msvideo + application/octet-stream + image/bmp + application/x-netcdf + internal/cgi + application/x-fortezza-ckl + application/java-vm + application/x-cpio + application/x-mscardfile + application/x-pkcs7-crl + application/x-csh + application/x-pointplus + application/msword + application/x-dot + drawing/x-dwf + image/vng + dynamo-internal/template + dynamo-internal/dynjava + application/pre-encrypted + application/postscript + audio/echospeech + audio/echospeech + application/x-earthtime + text/x-setext + application/x-envoy + image/fif + application/x-maker + video/isivideo + image/gif + application/x-gtar + application/x-hdf + application/winhlp + application/mac-binhex40 + text/html + text/html + x-conference/x-cooltalk + image/ief + image/ifs + internal/php4 + application/x-NET-Install + application/java-archive + image/jpeg + dynamo-internal/html + dynamo-internal/html + image/jpeg + image/jpeg + image/jpeg + application/x-javascript + application/x-javascript-config + application/x-javascript;charset=UTF + dynamo-internal/plain + dynamo-internal/plain + audio/x-liveaudio + application/x-latex + application/fastman + application/x-msmediaview + application/x-msmediaview + application/x-troff-man + dynamo-internal/map + application/mbedlet + application/x-msaccess + application/x-troff-me + application/x-mif + audio/mid + audio/midi + application/x-mif + application/x-msmoney + application/x-mocha + application/x-mocha + video/quicktime + video/x-sgi-movie + video/quicktime + video/x-mpeg2 + video/mpeg + video/mpeg + video/mpeg + video/mpeg + video/x-mpeg2 + video/mpeg + application/x-troff-ms + application/x-netcdf + application/oda + audio/x-pac + audio/x-epac + image/x-portable-bitmap + image/x-photo-cd + application/pdf + image/x-portable-graymap + internal/php4 + image/jpeg + image/jpeg + application/x-pl + image/png + image/x-portable-anymap + application/vnd.ms-powerpoint + image/x-portable_pixmap + application/vnd.ms-powerpoint + application/vnd.ms-powerpoint + application/x-ns-proxy-autoconfig + application/postscript + application/x-mspublisher + video/quicktime + audio/x-pn-realaudio + audio/x-pn-realaudio + image/x-cmu-raster + image/x-rgb + application/x-troff + application/msword + text/richtext + application/x-msschedule + application/java-serialized-object + application/x-sh + application/x-shar + application/x-stuffit + x-salsa + application/studiom + application/astround + audio/basic + application/x-sprite + application/x-sprite + application/x-wais-source + image/vng + x-world/x-svr + text/x-speech + application/x-troff + application/x-tar + application/x-timbuktu + application/timbuktu + internal/tcl + application/x-tex + application/x-texinfo + application/x-texinfo + image/tiff + image/tiff + application/x-tkined + application/x-tkined + application/x-troff + application/x-msterminal + text/tab-seperated-values + video/mpeg + video/vivo + video/vivo + x-world/x-vrt + audio/x-wav + application/msword + application/x-msmetafile + x-world/x-vrml + video/wavelet + image/x-xbitmap + application/vnd.ms-excel + application/vnd.ms-excel + application/vnd.ms-excel + application/vnd.ms-excel + application/vnd.ms-excel + application/vnd.ms-excel + image/x-xpixmap + image/x-xwindowdump + application/zip + + + diff --git a/lc-continuity/mk4/continuity/bin/phpdev.xml b/lc-continuity/mk4/continuity/bin/phpdev.xml new file mode 100644 index 0000000000000000000000000000000000000000..6b2c29a2adba19a9315955b7be39f9483f711e2e --- /dev/null +++ b/lc-continuity/mk4/continuity/bin/phpdev.xml @@ -0,0 +1,231 @@ + + + + ../lib/http.so + ../lib/site.so + ../../p/php-src/.libs/libphp5 + + + + + + + + + 8000 + httpFhandler + + + + + + + + Sites + + + index.html,index.php + + + + + + + text/plain + + + + + internal/php4 + + + + + + + + + + + + + /web/logs + + + + /web/content/ta/tessier/ + + foo.com + + + + + application/postscript + audio/x-aiff + audio/x-aiff + audio/x-aiff + application/x-aim + application/astound + application/x-asap + audio/basic + video/msvideo + application/octet-stream + image/bmp + application/x-netcdf + internal/cgi + application/x-fortezza-ckl + application/java-vm + application/x-cpio + application/x-mscardfile + application/x-pkcs7-crl + application/x-csh + text/css + application/msword + application/x-dot + drawing/x-dwf + image/vng + dynamo-internal/template + dynamo-internal/dynjava + application/pre-encrypted + application/postscript + audio/echospeech + audio/echospeech + application/x-earthtime + text/x-setext + application/x-envoy + image/fif + application/x-maker + video/isivideo + image/gif + application/x-gtar + application/x-hdf + application/winhlp + application/mac-binhex40 + text/html + text/html + x-conference/x-cooltalk + image/ief + image/ifs + internal/php4 + application/x-NET-Install + application/java-archive + image/jpeg + dynamo-internal/html + dynamo-internal/html + image/jpeg + image/jpeg + image/jpeg + application/x-javascript + application/x-javascript-config + application/x-javascript;charset=UTF + dynamo-internal/plain + dynamo-internal/plain + audio/x-liveaudio + application/x-latex + application/fastman + application/x-msmediaview + application/x-msmediaview + application/x-troff-man + dynamo-internal/map + application/mbedlet + application/x-msaccess + application/x-troff-me + application/x-mif + audio/mid + audio/midi + application/x-mif + application/x-msmoney + application/x-mocha + application/x-mocha + video/quicktime + video/x-sgi-movie + video/quicktime + video/x-mpeg2 + video/mpeg + video/mpeg + video/mpeg + video/mpeg + video/x-mpeg2 + video/mpeg + application/x-troff-ms + application/x-netcdf + application/oda + audio/x-pac + audio/x-epac + image/x-portable-bitmap + image/x-photo-cd + application/pdf + image/x-portable-graymap + internal/php4 + image/jpeg + image/jpeg + application/x-pl + image/png + image/x-portable-anymap + application/vnd.ms-powerpoint + image/x-portable_pixmap + application/vnd.ms-powerpoint + application/vnd.ms-powerpoint + application/x-ns-proxy-autoconfig + application/postscript + application/x-mspublisher + video/quicktime + audio/x-pn-realaudio + audio/x-pn-realaudio + image/x-cmu-raster + image/x-rgb + application/x-troff + application/msword + text/richtext + application/x-msschedule + application/java-serialized-object + application/x-sh + application/x-shar + application/x-stuffit + x-salsa + application/studiom + application/astround + audio/basic + application/x-sprite + application/x-sprite + application/x-wais-source + image/vng + x-world/x-svr + text/x-speech + application/x-troff + application/x-tar + application/x-timbuktu + application/timbuktu + internal/tcl + application/x-tex + application/x-texinfo + application/x-texinfo + image/tiff + image/tiff + application/x-tkined + application/x-tkined + application/x-troff + application/x-msterminal + text/tab-seperated-values + video/mpeg + video/vivo + video/vivo + x-world/x-vrt + audio/x-wav + application/msword + application/x-msmetafile + x-world/x-vrml + video/wavelet + image/x-xbitmap + application/vnd.ms-excel + application/vnd.ms-excel + application/vnd.ms-excel + application/vnd.ms-excel + application/vnd.ms-excel + application/vnd.ms-excel + image/x-xpixmap + image/x-xwindowdump + application/zip + + + diff --git a/lc-continuity/mk4/continuity/bin/radius.xml b/lc-continuity/mk4/continuity/bin/radius.xml new file mode 100644 index 0000000000000000000000000000000000000000..313cfeca5d86ebfeba0b315358fc262413dec13b --- /dev/null +++ b/lc-continuity/mk4/continuity/bin/radius.xml @@ -0,0 +1,42 @@ + + + + ../lib/radius + + + + + + + + + + + + + + User-Namestring + Passwordstring + CHAP-Passwordstring + NAS-IP-Addressipaddr + NAS-Portinteger + Service-Typeinteger + Framed-Protocolinteger + Framed-IP-Addressipaddr + Framed-IP-Netmaskipaddr + Framed-Routinginteger + Filter-Idstring + Framed-MTUinteger + Framed-Compressioninteger + Login-IP-Hostipaddr + Login-Serviceinteger + Login-TCP-Portinteger + Reply-Messagestring + Callback-Numberstring + Callback-Idstring + Framed-routestring + Framed-IPX-Networkipaddr + Statestring + + + diff --git a/lc-continuity/mk4/continuity/bin/ssl.xml b/lc-continuity/mk4/continuity/bin/ssl.xml new file mode 100644 index 0000000000000000000000000000000000000000..1f3adc0a2119b0e2457dd0beb89d1849c659ac2f --- /dev/null +++ b/lc-continuity/mk4/continuity/bin/ssl.xml @@ -0,0 +1,235 @@ + + + + + + ../lib/http.so + ../lib/site.so + ../lib/ssl.so + + + + + + + + ../../modssl/server.pem + password + httpFhandler + + + 8000 + sslFhandler + + + + + + + + + Sites + + + index.html,index.php + + + + + + + text/plain + + + + + + + + + + + + + + + + /tmp + + + + /web/content/_default/_default + http://www.postfin.com/ + + + + application/postscript + audio/x-aiff + audio/x-aiff + audio/x-aiff + application/x-aim + application/astound + application/x-asap + audio/basic + video/msvideo + application/octet-stream + image/bmp + application/x-netcdf + internal/cgi + application/x-fortezza-ckl + application/java-vm + application/x-cpio + application/x-mscardfile + application/x-pkcs7-crl + application/x-csh + text/css + application/msword + application/x-dot + drawing/x-dwf + image/vng + dynamo-internal/template + dynamo-internal/dynjava + application/pre-encrypted + application/postscript + audio/echospeech + audio/echospeech + application/x-earthtime + text/x-setext + application/x-envoy + image/fif + application/x-maker + video/isivideo + image/gif + application/x-gtar + application/x-hdf + application/winhlp + application/mac-binhex40 + text/html + text/html + x-conference/x-cooltalk + image/ief + image/ifs + internal/php4 + application/x-NET-Install + application/java-archive + image/jpeg + dynamo-internal/html + dynamo-internal/html + image/jpeg + image/jpeg + image/jpeg + application/x-javascript + application/x-javascript-config + application/x-javascript;charset=UTF + dynamo-internal/plain + dynamo-internal/plain + audio/x-liveaudio + application/x-latex + application/fastman + application/x-msmediaview + application/x-msmediaview + application/x-troff-man + dynamo-internal/map + application/mbedlet + application/x-msaccess + application/x-troff-me + application/x-mif + audio/mid + audio/midi + application/x-mif + application/x-msmoney + application/x-mocha + application/x-mocha + video/quicktime + video/x-sgi-movie + video/quicktime + video/x-mpeg2 + video/mpeg + video/mpeg + video/mpeg + video/mpeg + video/x-mpeg2 + video/mpeg + application/x-troff-ms + application/x-netcdf + application/oda + audio/x-pac + audio/x-epac + image/x-portable-bitmap + image/x-photo-cd + application/pdf + image/x-portable-graymap + internal/php4 + image/jpeg + image/jpeg + application/x-pl + image/png + image/x-portable-anymap + application/vnd.ms-powerpoint + image/x-portable_pixmap + application/vnd.ms-powerpoint + application/vnd.ms-powerpoint + application/x-ns-proxy-autoconfig + application/postscript + application/x-mspublisher + video/quicktime + audio/x-pn-realaudio + audio/x-pn-realaudio + image/x-cmu-raster + image/x-rgb + application/x-troff + application/msword + text/richtext + application/x-msschedule + application/java-serialized-object + application/x-sh + application/x-shar + application/x-stuffit + x-salsa + application/studiom + application/astround + audio/basic + application/x-sprite + application/x-sprite + application/x-wais-source + image/vng + x-world/x-svr + text/x-speech + application/x-troff + application/x-tar + application/x-timbuktu + application/timbuktu + internal/tcl + application/x-tex + application/x-texinfo + application/x-texinfo + image/tiff + image/tiff + application/x-tkined + application/x-tkined + application/x-troff + application/x-msterminal + text/tab-seperated-values + video/mpeg + video/vivo + video/vivo + x-world/x-vrt + audio/x-wav + application/msword + application/x-msmetafile + x-world/x-vrml + video/wavelet + image/x-xbitmap + application/vnd.ms-excel + application/vnd.ms-excel + application/vnd.ms-excel + application/vnd.ms-excel + application/vnd.ms-excel + application/vnd.ms-excel + image/x-xpixmap + image/x-xwindowdump + application/zip + + + diff --git a/lc-continuity/mk4/continuity/bin/winkfep.xml b/lc-continuity/mk4/continuity/bin/winkfep.xml new file mode 100644 index 0000000000000000000000000000000000000000..500bcfc2956081deb22a3600737c014362780ca1 --- /dev/null +++ b/lc-continuity/mk4/continuity/bin/winkfep.xml @@ -0,0 +1,305 @@ + + + + + ../lib/cmd + ../lib/db + ../lib/oracle + ../lib/http + ../lib/site + ../lib/iplk + ../lib/dial + ../lib/wink + ../lib/beacon + ../lib/dynamo + + + + + loadonly + + + nodb + + + 10.2.2.96 + 8880 + + + 256 + 8000 + httpFhandler + + + + + + + + + + + + + + index.html,index.php + + + + + + + text/plain + + + + + + internal/cdp-dialer + + dynamo-internal/html + dynamo-internal/plain + dynamo-internal/template + dynamo-internal/map + dynamo-internal/java + + + + + + + + + + + + + + /web02/log/continuity/iris + + + + + 204.177.92.204 + 204.177.92.209 + 207.17.53.244 + + + + + /web02/content/enm/dialers/ + + 204.177.92.205 + 207.17.53.245 + + + target + + + + + /web02/content/enm/dialers/ + + 204.177.92.208 + 207.17.53.246 + 207.17.53.247 + 207.17.53.248 + + + + + /web02/content/cfarm/general/ + + 204.177.92.207 + + + + + /web02/content/enm/dialers/ + + 204.177.92.198 + + + + + /web02/content/cfarm/general + + foo.com + + + + + + + + internal/cdp-dialer + application/postscript + audio/x-aiff + audio/x-aiff + audio/x-aiff + application/x-aim + application/astound + application/x-asap + audio/basic + video/msvideo + application/octet-stream + image/bmp + application/x-netcdf + internal/cgi + application/x-fortezza-ckl + application/java-vm + application/x-cpio + application/x-mscardfile + application/x-pkcs7-crl + application/x-csh + application/x-pointplus + application/msword + application/x-dot + drawing/x-dwf + image/vng + dynamo-internal/template + dynamo-internal/dynjava + application/pre-encrypted + application/postscript + audio/echospeech + audio/echospeech + application/x-earthtime + text/x-setext + application/x-envoy + image/fif + application/x-maker + video/isivideo + image/gif + application/x-gtar + application/x-hdf + application/winhlp + application/mac-binhex40 + text/html + text/html + x-conference/x-cooltalk + image/ief + image/ifs + internal/php4 + application/x-NET-Install + application/java-archive + image/jpeg + dynamo-internal/html + dynamo-internal/html + image/jpeg + image/jpeg + image/jpeg + application/x-javascript + application/x-javascript-config + application/x-javascript;charset=UTF + dynamo-internal/plain + dynamo-internal/plain + audio/x-liveaudio + application/x-latex + application/fastman + application/x-msmediaview + application/x-msmediaview + application/x-troff-man + dynamo-internal/map + application/mbedlet + application/x-msaccess + application/x-troff-me + application/x-mif + audio/mid + audio/midi + application/x-mif + application/x-msmoney + application/x-mocha + application/x-mocha + video/quicktime + video/x-sgi-movie + video/quicktime + video/x-mpeg2 + video/mpeg + video/mpeg + video/mpeg + video/mpeg + video/x-mpeg2 + video/mpeg + application/x-troff-ms + application/x-netcdf + application/oda + audio/x-pac + audio/x-epac + image/x-portable-bitmap + image/x-photo-cd + application/pdf + image/x-portable-graymap + internal/php4 + image/jpeg + image/jpeg + application/x-pl + image/png + image/x-portable-anymap + application/vnd.ms-powerpoint + image/x-portable_pixmap + application/vnd.ms-powerpoint + application/vnd.ms-powerpoint + application/x-ns-proxy-autoconfig + application/postscript + application/x-mspublisher + video/quicktime + audio/x-pn-realaudio + audio/x-pn-realaudio + image/x-cmu-raster + image/x-rgb + application/x-troff + application/msword + text/richtext + application/x-msschedule + application/java-serialized-object + application/x-sh + application/x-shar + application/x-stuffit + x-salsa + application/studiom + application/astround + audio/basic + application/x-sprite + application/x-sprite + application/x-wais-source + image/vng + x-world/x-svr + text/x-speech + application/x-troff + application/x-tar + application/x-timbuktu + application/timbuktu + internal/tcl + application/x-tex + application/x-texinfo + application/x-texinfo + image/tiff + image/tiff + application/x-tkined + application/x-tkined + application/x-troff + application/x-msterminal + text/tab-seperated-values + video/mpeg + video/vivo + video/vivo + x-world/x-vrt + audio/x-wav + application/msword + application/x-msmetafile + x-world/x-vrml + video/wavelet + image/x-xbitmap + application/vnd.ms-excel + application/vnd.ms-excel + application/vnd.ms-excel + application/vnd.ms-excel + application/vnd.ms-excel + application/vnd.ms-excel + image/x-xpixmap + image/x-xwindowdump + application/zip + + + diff --git a/lc-continuity/mk4/continuity/config.guess b/lc-continuity/mk4/continuity/config.guess new file mode 100644 index 0000000000000000000000000000000000000000..81688c4cf1a4a470eb9f1166cc5146dbc69c8404 --- /dev/null +++ b/lc-continuity/mk4/continuity/config.guess @@ -0,0 +1,1284 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000 +# Free Software Foundation, Inc. + +version='2000-07-27' + +# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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. + +# Written by Per Bothner . +# Please send patches to . +# +# 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. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit system type (host/target name). +# +# Only a few systems have been added to this list; please add others +# (but try to keep the structure clean). +# + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of this system. + +Operation modes: + -h, --help print this help, then exit + -V, --version print version number, then exit" + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case "$1" in + --version | --vers* | -V ) + echo "$version" ; exit 0 ;; + --help | --h* | -h ) + echo "$usage"; exit 0 ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + exec >&2 + echo "$me: invalid option $1" + echo "$help" + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +# Use $HOST_CC if defined. $CC may point to a cross-compiler +if test x"$CC_FOR_BUILD" = x; then + if test x"$HOST_CC" != x; then + CC_FOR_BUILD="$HOST_CC" + else + if test x"$CC" != x; then + CC_FOR_BUILD="$CC" + else + CC_FOR_BUILD=cc + fi + fi +fi + + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 8/24/94.) +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 + +dummy=dummy-$$ +trap 'rm -f $dummy.c $dummy.o $dummy; exit 1' 1 2 15 + +# 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. + # Determine the machine/vendor (is the vendor relevant). + case "${UNAME_MACHINE}" in + amiga) machine=m68k-unknown ;; + arm32) machine=arm-unknown ;; + atari*) machine=m68k-atari ;; + sun3*) machine=m68k-sun ;; + mac68k) machine=m68k-apple ;; + macppc) machine=powerpc-apple ;; + hp3[0-9][05]) machine=m68k-hp ;; + ibmrt|romp-ibm) machine=romp-ibm ;; + *) machine=${UNAME_MACHINE}-unknown ;; + esac + # The Operating System including object format. + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep __ELF__ >/dev/null + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + # The OS release + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + # 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 0 ;; + alpha:OSF1:*:*) + if test $UNAME_RELEASE = "V4.0"; then + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + fi + # 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. + cat <$dummy.s + .data +\$Lformat: + .byte 37,100,45,37,120,10,0 # "%d-%x\n" + + .text + .globl main + .align 4 + .ent main +main: + .frame \$30,16,\$26,0 + ldgp \$29,0(\$27) + .prologue 1 + .long 0x47e03d80 # implver \$0 + lda \$2,-1 + .long 0x47e20c21 # amask \$2,\$1 + lda \$16,\$Lformat + mov \$0,\$17 + not \$1,\$18 + jsr \$26,printf + ldgp \$29,0(\$26) + mov 0,\$16 + jsr \$26,exit + .end main +EOF + $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null + if test "$?" = 0 ; then + case `./$dummy` in + 0-0) + UNAME_MACHINE="alpha" + ;; + 1-0) + UNAME_MACHINE="alphaev5" + ;; + 1-1) + UNAME_MACHINE="alphaev56" + ;; + 1-101) + UNAME_MACHINE="alphapca56" + ;; + 2-303) + UNAME_MACHINE="alphaev6" + ;; + 2-307) + UNAME_MACHINE="alphaev67" + ;; + esac + fi + rm -f $dummy.s $dummy + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit 0 ;; + 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 0 ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit 0 ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit 0;; + amiga:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit 0 ;; + arc64:OpenBSD:*:*) + echo mips64el-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + arc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + hkmips:OpenBSD:*:*) + echo mips-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + pmax:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sgi:OpenBSD:*:*) + echo mips-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + wgrisc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit 0 ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit 0;; + SR2?01:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit 0;; + 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 0 ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit 0 ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + i86pc:SunOS:5.*:*) + echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + 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 0 ;; + 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 0 ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit 0 ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(head -1 /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 0 ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit 0 ;; + atari*:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + # 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 0 ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit 0 ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit 0 ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit 0 ;; + sun3*:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mac68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme88k:OpenBSD:*:*) + echo m88k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit 0 ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit 0 ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit 0 ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + 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 $dummy.c -o $dummy \ + && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ + && rm $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + echo mips-mips-riscos${UNAME_RELEASE} + exit 0 ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit 0 ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit 0 ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit 0 ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit 0 ;; + 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 0 ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit 0 ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit 0 ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit 0 ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit 0 ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit 0 ;; + ????????: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 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i?86:AIX:*:*) + echo i386-ibm-aix + exit 0 ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + echo rs6000-ibm-aix3.2.5 + 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 0 ;; + *:AIX:*:4) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | head -1 | awk '{ print $1 }'` + if /usr/sbin/lsattr -EHl ${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=4.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit 0 ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit 0 ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit 0 ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit 0 ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit 0 ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit 0 ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit 0 ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit 0 ;; + 9000/[34678]??:HP-UX:*:*) + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + 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 $dummy.c -o $dummy 2>/dev/null ) && HP_ARCH=`./$dummy` + rm -f $dummy.c $dummy + esac + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit 0 ;; + 3050*:HI-UX:*:*) + 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 $dummy.c -o $dummy && ./$dummy && rm $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + echo unknown-hitachi-hiuxwe2 + exit 0 ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit 0 ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit 0 ;; + *9??*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit 0 ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit 0 ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit 0 ;; + i?86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit 0 ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit 0 ;; + hppa*:OpenBSD:*:*) + echo hppa-unknown-openbsd + exit 0 ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit 0 ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit 0 ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit 0 ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit 0 ;; + CRAY*X-MP:*:*:*) + echo xmp-cray-unicos + exit 0 ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} + exit 0 ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ + exit 0 ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*T3E:*:*:*) + echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY-2:*:*:*) + echo cray2-cray-unicos + exit 0 ;; + F300:UNIX_System_V:*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "f300-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit 0 ;; + F301:UNIX_System_V:*:*) + echo f301-fujitsu-uxpv`echo $UNAME_RELEASE | sed 's/ .*//'` + exit 0 ;; + hp300:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + i?86:BSD/386:*:* | i?86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit 0 ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:FreeBSD:*:*) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit 0 ;; + *:OpenBSD:*:*) + echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + exit 0 ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit 0 ;; + i*:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit 0 ;; + 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 i386-pc-interix + exit 0 ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit 0 ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit 0 ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + *:GNU:*:*) + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit 0 ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit 0 ;; + *:Linux:*:*) + + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + ld_help_string=`cd /; ld --help 2>&1` + ld_supported_emulations=`echo $ld_help_string \ + | sed -ne '/supported emulations:/!d + s/[ ][ ]*/ /g + s/.*supported emulations: *// + s/ .*// + p'` + case "$ld_supported_emulations" in + *ia64) + echo "${UNAME_MACHINE}-unknown-linux" + exit 0 + ;; + i?86linux) + echo "${UNAME_MACHINE}-pc-linux-gnuaout" + exit 0 + ;; + elf_i?86) + TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" + ;; + i?86coff) + echo "${UNAME_MACHINE}-pc-linux-gnucoff" + exit 0 + ;; + sparclinux) + echo "${UNAME_MACHINE}-unknown-linux-gnuaout" + exit 0 + ;; + armlinux) + echo "${UNAME_MACHINE}-unknown-linux-gnuaout" + exit 0 + ;; + elf32arm*) + echo "${UNAME_MACHINE}-unknown-linux-gnuoldld" + exit 0 + ;; + armelf_linux*) + echo "${UNAME_MACHINE}-unknown-linux-gnu" + exit 0 + ;; + m68klinux) + echo "${UNAME_MACHINE}-unknown-linux-gnuaout" + exit 0 + ;; + elf32ppc | elf32ppclinux) + # Determine Lib Version + cat >$dummy.c < +#if defined(__GLIBC__) +extern char __libc_version[]; +extern char __libc_release[]; +#endif +main(argc, argv) + int argc; + char *argv[]; +{ +#if defined(__GLIBC__) + printf("%s %s\n", __libc_version, __libc_release); +#else + printf("unkown\n"); +#endif + return 0; +} +EOF + LIBC="" + $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null + if test "$?" = 0 ; then + ./$dummy | grep 1\.99 > /dev/null + if test "$?" = 0 ; then + LIBC="libc1" + fi + fi + rm -f $dummy.c $dummy + echo powerpc-unknown-linux-gnu${LIBC} + exit 0 + ;; + shelf_linux) + echo "${UNAME_MACHINE}-unknown-linux-gnu" + exit 0 + ;; + esac + + if test "${UNAME_MACHINE}" = "alpha" ; then + cat <$dummy.s + .data + \$Lformat: + .byte 37,100,45,37,120,10,0 # "%d-%x\n" + + .text + .globl main + .align 4 + .ent main + main: + .frame \$30,16,\$26,0 + ldgp \$29,0(\$27) + .prologue 1 + .long 0x47e03d80 # implver \$0 + lda \$2,-1 + .long 0x47e20c21 # amask \$2,\$1 + lda \$16,\$Lformat + mov \$0,\$17 + not \$1,\$18 + jsr \$26,printf + ldgp \$29,0(\$26) + mov 0,\$16 + jsr \$26,exit + .end main +EOF + LIBC="" + $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null + if test "$?" = 0 ; then + case `./$dummy` in + 0-0) + UNAME_MACHINE="alpha" + ;; + 1-0) + UNAME_MACHINE="alphaev5" + ;; + 1-1) + UNAME_MACHINE="alphaev56" + ;; + 1-101) + UNAME_MACHINE="alphapca56" + ;; + 2-303) + UNAME_MACHINE="alphaev6" + ;; + 2-307) + UNAME_MACHINE="alphaev67" + ;; + esac + + objdump --private-headers $dummy | \ + grep ld.so.1 > /dev/null + if test "$?" = 0 ; then + LIBC="libc1" + fi + fi + rm -f $dummy.s $dummy + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} ; exit 0 + elif test "${UNAME_MACHINE}" = "mips" ; then + cat >$dummy.c < /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif +#ifdef __MIPSEB__ + printf ("%s-unknown-linux-gnu\n", argv[1]); +#endif +#ifdef __MIPSEL__ + printf ("%sel-unknown-linux-gnu\n", argv[1]); +#endif + return 0; +} +EOF + $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + elif test "${UNAME_MACHINE}" = "s390"; then + echo s390-ibm-linux && exit 0 + else + # Either a pre-BFD a.out linker (linux-gnuoldld) + # or one that does not give us useful --help. + # GCC wants to distinguish between linux-gnuoldld and linux-gnuaout. + # If ld does not provide *any* "supported emulations:" + # that means it is gnuoldld. + echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations:" + test $? != 0 && echo "${UNAME_MACHINE}-pc-linux-gnuoldld" && exit 0 + + case "${UNAME_MACHINE}" in + i?86) + VENDOR=pc; + ;; + *) + VENDOR=unknown; + ;; + esac + # Determine whether the default compiler is a.out or elf + cat >$dummy.c < +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif +#ifdef __ELF__ +# ifdef __GLIBC__ +# if __GLIBC__ >= 2 + printf ("%s-${VENDOR}-linux-gnu\n", argv[1]); +# else + printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]); +# endif +# else + printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]); +# endif +#else + printf ("%s-${VENDOR}-linux-gnuaout\n", argv[1]); +#endif + return 0; +} +EOF + $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 + fi ;; +# 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. + i?86:DYNIX/ptx:4*:*) + echo i386-sequent-sysv4 + exit 0 ;; + 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 0 ;; + 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 0 ;; + i?86:*:5:7*) + # Fixed at (any) Pentium or better + UNAME_MACHINE=i586 + if [ ${UNAME_SYSTEM} = "UnixWare" ] ; then + echo ${UNAME_MACHINE}-sco-sysv${UNAME_RELEASE}uw${UNAME_VERSION} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE} + fi + exit 0 ;; + 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|egrep Release|sed -e 's/.*= //')` + (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit 0 ;; + i?86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit 0 ;; + 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 i386. + echo i386-pc-msdosdjgpp + exit 0 ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit 0 ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit 0 ;; + 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 0 ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit 0 ;; + M68*:*:R3V[567]*:*) + test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; + 3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*: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 0 + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4 && exit 0 ;; + m68*:LynxOS:2.*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit 0 ;; + i?86:LynxOS:2.*:* | i?86:LynxOS:3.[01]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + rs6000:LynxOS:2.*:* | PowerPC:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit 0 ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + *: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 0 ;; + PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit 0 ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit 0 ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit 0 ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit 0 ;; + news*:NEWS-OS:*:6*) + echo mips-sony-newsos6 + exit 0 ;; + 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 0 ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit 0 ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit 0 ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit 0 ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit 0 ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit 0 ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + *:Darwin:*:*) + echo `uname -p`-apple-darwin${UNAME_RELEASE} + exit 0 ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + if test "${UNAME_MACHINE}" = "x86pc"; then + UNAME_MACHINE=pc + fi + echo `uname -p`-${UNAME_MACHINE}-nto-qnx + exit 0 ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit 0 ;; + NSR-W:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit 0 ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit 0 ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit 0 ;; + *: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 0 ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +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"); 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) + printf ("vax-dec-bsd\n"); exit (0); +#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 $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm $dummy.c $dummy && exit 0 +rm -f $dummy.c $dummy + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } + +# 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 0 ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + c34*) + echo c34-convex-bsd + exit 0 ;; + c38*) + echo c38-convex-bsd + exit 0 ;; + c4*) + echo c4-convex-bsd + exit 0 ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess version = $version + +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: "version='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/lc-continuity/mk4/continuity/config.sub b/lc-continuity/mk4/continuity/config.sub new file mode 100644 index 0000000000000000000000000000000000000000..945a7f4b8588f5328dc68461f1706008ac873859 --- /dev/null +++ b/lc-continuity/mk4/continuity/config.sub @@ -0,0 +1,1324 @@ +#! /bin/sh +# Configuration validation subroutine script, version 1.1. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000 +# Free Software Foundation, Inc. + +version='2000-08-07' + +# 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., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, 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 . +# +# 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. + +# 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 + -V, --version print version number, then exit" + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case "$1" in + --version | --vers* | -V ) + echo "$version" ; exit 0 ;; + --help | --h* | -h ) + echo "$usage"; exit 0 ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + exec >&2 + echo "$me: invalid option $1" + echo "$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit 0;; + + * ) + 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*) + 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) + os= + basic_machine=$1 + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -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/'` + ;; + -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. + tahoe | i860 | ia64 | m32r | m68k | m68000 | m88k | ns32k | arc | arm \ + | arme[lb] | armv* | pyramid | mn10200 | mn10300 | tron | a29k \ + | 580 | i960 | h8300 \ + | x86 | ppcbe | mipsbe | mipsle | shbe | shle | armbe | armle \ + | hppa | hppa1.0 | hppa1.1 | hppa2.0 | hppa2.0w | hppa2.0n \ + | hppa64 \ + | alpha | alphaev[4-8] | alphaev56 | alphapca5[67] \ + | alphaev6[78] \ + | we32k | ns16k | clipper | i370 | sh | sh[34] \ + | powerpc | powerpcle \ + | 1750a | dsp16xx | pdp11 | mips16 | mips64 | mipsel | mips64el \ + | mips64orion | mips64orionel | mipstx39 | mipstx39el \ + | mips64vr4300 | mips64vr4300el | mips64vr4100 | mips64vr4100el \ + | mips64vr5000 | miprs64vr5000el | mcore \ + | sparc | sparclet | sparclite | sparc64 | sparcv9 | v850 | c4x \ + | thumb | d10v | d30v | fr30 | avr) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | z8k | v70 | h8500 | w65 | pj | pjl) + ;; + + # 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[234567]86) + 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. + # FIXME: clean up the formatting here. + vax-* | tahoe-* | i[234567]86-* | i860-* | ia64-* | m32r-* | m68k-* | m68000-* \ + | m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | arm-* | c[123]* \ + | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \ + | power-* | none-* | 580-* | cray2-* | h8300-* | h8500-* | i960-* \ + | xmp-* | ymp-* \ + | x86-* | ppcbe-* | mipsbe-* | mipsle-* | shbe-* | shle-* | armbe-* | armle-* \ + | hppa-* | hppa1.0-* | hppa1.1-* | hppa2.0-* | hppa2.0w-* \ + | hppa2.0n-* | hppa64-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphapca5[67]-* \ + | alphaev6[78]-* \ + | we32k-* | cydra-* | ns16k-* | pn-* | np1-* | xps100-* \ + | clipper-* | orion-* \ + | sparclite-* | pdp11-* | sh-* | powerpc-* | powerpcle-* \ + | sparc64-* | sparcv9-* | sparc86x-* | mips16-* | mips64-* | mipsel-* \ + | mips64el-* | mips64orion-* | mips64orionel-* \ + | mips64vr4100-* | mips64vr4100el-* | mips64vr4300-* | mips64vr4300el-* \ + | mipstx39-* | mipstx39el-* | mcore-* \ + | f301-* | armv*-* | s390-* | sv1-* | t3e-* \ + | m88110-* | m680[01234]0-* | m683?2-* | m68360-* | z8k-* | d10v-* \ + | thumb-* | v850-* | d30v-* | tic30-* | c30-* | fr30-* \ + | bs2000-* | tic54x-* | c54x-*) + ;; + # 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 + ;; + 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 + ;; + 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 + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + 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 | ymp) + basic_machine=ymp-cray + os=-unicos + ;; + cray2) + basic_machine=cray2-cray + os=-unicos + ;; + [ctj]90-cray) + basic_machine=c90-cray + os=-unicos + ;; + crds | unos) + basic_machine=m68k-crds + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + 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 + ;; + 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[34567]86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i[34567]86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i[34567]86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i[34567]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 + ;; + i386-go32 | go32) + basic_machine=i386-unknown + os=-go32 + ;; + i386-mingw32 | mingw32) + basic_machine=i386-unknown + os=-mingw32 + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mipsel*-linux*) + basic_machine=mipsel-unknown + os=-linux-gnu + ;; + mips*-linux*) + basic_machine=mips-unknown + os=-linux-gnu + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + mmix*) + basic_machine=mmix-knuth + os=-mmixware + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + msdos) + basic_machine=i386-unknown + os=-msdos + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + 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 + ;; + np1) + basic_machine=np1-gould + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + 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 + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pentium | p5 | k5 | k6 | nexen) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon) + basic_machine=i686-pc + ;; + pentiumii | pentium2) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexen-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=rs6000-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/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sparclite-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=t3e-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + 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 + ;; + xmp) + basic_machine=xmp-cray + os=-unicos + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + z8k-*-coff) + basic_machine=z8k-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 + ;; + mips) + if [ x$os = x-linux-gnu ]; then + basic_machine=mips-unknown + else + basic_machine=mips-mips + fi + ;; + romp) + basic_machine=romp-ibm + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh3 | sh4) + base_machine=sh-unknown + ;; + sparc | sparcv9) + 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 + ;; + c4x*) + basic_machine=c4x-none + os=-coff + ;; + *) + 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. + -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* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ + | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i[34567]86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto*) + os=-nto-qnx + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -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 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -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) + os=-mint + ;; + -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 + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + 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 + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-ibm) + os=-aix + ;; + *-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 + ;; + f301-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 + ;; + -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 + ;; + -ptx*) + vendor=sequent + ;; + -vxsim* | -vxworks*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -*MiNT) + vendor=atari + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "version='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/lc-continuity/mk4/continuity/configure.in b/lc-continuity/mk4/continuity/configure.in new file mode 100644 index 0000000000000000000000000000000000000000..1318d8285285c237c84a92680a89760643927952 --- /dev/null +++ b/lc-continuity/mk4/continuity/configure.in @@ -0,0 +1,254 @@ +walldnl Process this file with autoconf to produce a configure script. +AC_INIT(mecha/lst.c) + +AC_CANONICAL_SYSTEM +AC_PROG_CC +AC_SUBST(CC) +AC_PROG_CPP + +AC_ARG_ENABLE(64bit,dnl +[ --enable-64bit Attempt to build a 64bit target (sparc)], +do64=yes) + +AC_ARG_ENABLE(production,dnl +[ --enable-production Perform a production build, full opts, no debugging], +doprod=yes) + +AC_ARG_ENABLE(prof,dnl +[ --enable-prof Enable profiling], +doprof=yes) + +AC_ARG_ENABLE(gprof,dnl +[ --enable-gprof Enable g-profiling], +dogprof=yes) + +AC_ARG_ENABLE(oneshot,dnl +[ --enable-oneshot Enable one-shot build], +dooneshot=yes) + +echo "target_cpu: $target_cpu" +echo "target_os: $target_os" + +AC_CHECK_LIB(c_r,pthread_create) +AC_CHECK_LIB(resolv, inet_aton) +AC_CHECK_LIB(m,floor) +AC_CHECK_LIB(nsl, gethostname) +AC_CHECK_LIB(kstat,kstat_open) +AC_CHECK_LIB(socket, connect) +AC_CHECK_LIB(aio,aiowrite) +AC_CHECK_LIB(thread, pthread_create) +AC_CHECK_LIB(pthread, pthread_create) +AC_CHECK_LIB(dl,dlopen) +AC_CHECK_LIB(LiS,putpmsg) +AC_CHECK_LIB(mtmalloc,malloc) +AC_CHECK_LIB(c,prctl) + +AC_CHECK_PROG(MAKEDEPEND,makedepend,"yes","no") +if test "$MAKEDEPEND" = "no" ; then + echo "No makedepend found." + MAKEDEPEND="echo" +else + echo "makedepend found." + MAKEDEPEND="makedepend" +fi + +# Each platform needs to set a number of variables for the make. +# +# BUILD_CMD - The command that will be used to build executables. ld or cc, depending. +# PRE_BUILD - Any arguments that need to be called before the object list for BUILD_CMD. +# POST_BUILD - Any arguments that need to be called after the object list for BUILD_CMD. +# OPT_CFLAGS - Optional cflag lines, such as -g, etc. +# LDSHARED - The command to build a shared library, eg, gcc -shared, ld -G, etc. + +echo $target_os + +case "$target_os" in +#### +# OSX +#### +darwin*) + CC=cc + if test "$doprod" = "yes" ; then + echo "Setting GCC production flags." ; OPT_CFLAGS="$OPT_CFLAGS -O2 -DNDEBUG -DPRODUCTION -DDARWIN -pedantic -D_POSIX_C_SOURCE=199506L -std=c99" + else + echo "Setting GCC Development flags." ; OPT_CFLAGS="$OPT_CFLAGS -g -DDARWIN -pedantic -D_POSIX_C_SOURCE=199506L -std=c99" + fi + + LD_FLAGS="-rdynamic" + LDSHARED="cc -bundle -flat_namespace -undefined suppress -Wl,-all_load" + AR_CMD="ar cr" + BUILD_CMD=cc + PRE_CMD="-bundle -flat_namespace -undefined-suppress" + DEPFLAGS="-DDARWIN" +;; + +#### +# SUN SOLARIS +#### +solaris*) +if test "${CC}" != "gcc" ; then + # CC + case "$target_cpu" in + sparc) + if test "$do64" = "yes" ; then + echo "Setting 64-bit Ultra architecture flags." ; ARCH_CFLAGS="-xarch=v9a -DTA_64BIT" + BUILD_CMD="/usr/ccs/bin/ld" + PRE_BUILD="-zallextract /opt/SUNWspro/prod/lib/v9/crti.o /opt/SUNWspro/prod/lib/v9/crt1.o /opt/SUNWspro/prod/lib/v9/values-xa.o" + POST_BUILD="-Y "P,/opt/SUNWspro/prod/lib/v9a:/opt/SUNWspro/prod/lib/v9:/usr/ccs/lib/sparcv9:/usr/lib/sparcv9" -Qy -lc /opt/SUNWspro/prod/lib/v9/crtn.o" + MODTCL_TCLOPT="--enable-64bit-vis" + else + echo "Setting 32-bit Ultra architecture flags." ; ARCH_CFLAGS="-xarch=v8plusa" + PRE_BUILD="-zallextract /opt/SUNWspro/prod/lib/crti.o /opt/SUNWspro/prod/lib/crt1.o /opt/SUNWspro/prod/lib/values-xa.o" + POST_BUILD="-Y P,/opt/SUNWspro/prod/lib:/usr/ccs/lib:/usr/lib -Qy -lc /opt/SUNWspro/prod/lib/crtn.o" + BUILD_CMD=ld + fi + + if test "$doprod" = "yes" ; then + echo "Setting SUNWspro production flags." ; OPT_CFLAGS="-xtime -xO5 -xprefetch -DNDEBUG -DPRODUCTION -DSOLARIS -xc99=%all" + else + echo "Setting SUNWspro debug flags." ; OPT_CFLAGS="-xtime -g -DSOLARIS -xc99=%all" + fi + + AR_CMD="ar crs" + ;; + esac +else + # GCC + if test "$doprod" = "yes" ; then + echo "Setting GCC production flags." ; OPT_CFLAGS="-O2 -DSOLARIS -DNDEBUG -DPRODUCTION -Wall -std=c99 -D__STDC__=0 -D__EXTENSIONS__" + else + echo "Setting GCC Development flags." ; OPT_CFLAGS="-g -DSOLARIS -Wall -std=c99 -D__STDC__=0 -D__EXTENSIONS__" + fi + AR_CMD="ar crs" +# LD_FLAGS="-rdynamic" +fi + +DEPFLAGS="-DSOLARIS" + +if test "$doprof" = "yes" ; then + OPT_CFLAGS="$OPT_CFLAGS -p" +fi + +if test "$dogprof" = "yes" ; then + OPT_CFLAGS="$OPT_CFLAGS -xpg" +fi + +LDSHARED="ld -G" +;; + + +#### +# LINUX +#### +linux*) + if test "$doprod" = "yes" ; then + echo "Setting GCC production flags." ; OPT_CFLAGS="-O2 -W -Wall -Wimplicit -Wunused -Wchar-subscripts -Wshadow -Wwrite-strings -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wno-long-long -pedantic -DNDEBUG -DPRODUCTION -DLINUX -D_XOPEN_SOURCE=500 -D_POSIX_C_SOURCE=199506L -DLIS -rdynamic -pedantic -std=c99" + else +echo "Setting GCC Development flags." ; OPT_CFLAGS="-g -W -Wall -Wimplicit -Wunused -Wchar-subscripts -Wshadow -Wwrite-strings -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wno-long-long -pedantic -DLINUX -D_XOPEN_SOURCE=500 -D_POSIX_C_SOURCE=199506L -DLIS -rdynamic -std=c99" + fi + LDSHARED="gcc -shared" + BUILD_CMD="gcc" + LD_FLAGS="-rdynamic" + PRE_BUILD="-Wl,--whole-archive" + POST_BUILD="-Wl,--no-whole-archive" + AR_CMD="ar crs" + DEPFLAGS="-DLINUX -D_XOPEN_SOURCE=500 -D_POSIX_C_SOURCE=199506L -DLIS" +;; + +#### +# EVERYTHING ELSE +#### +*) + if test "$doprod" = "yes" ; then + echo "Setting GCC production flags." ; OPT_CFLAGS="-O2 -Wall -DNDEBUG -DPRODUCTION" + else + echo "Setting GCC Development flags." ; OPT_CFLAGS="-g -Wall" + fi + LDSHARED="ld -G" + AR_CMD="ar crs" + DEPFLAGS="" +;; +esac + +if test "$dooneshot" = "yes" ; then + echo "Configuring for One-Shot Build" + BUILD_CFLAGS="-DONESHOT" + BUILDMODE="oneshot" +else + echo "Configuring for Multi-Shot Build" + BUILD_CFLAGS="-DMULTISHOT" + BUILDMODE="multishot" +fi + +# Globals +RM="rm -rf" + +AC_SUBST(BUILDMODE) +AC_SUBST(BUILD_CFLAGS) +AC_SUBST(AR_CMD) +AC_SUBST(ARCH_CFLAGS) +AC_SUBST(OPT_CFLAGS) +AC_SUBST(LDSHARED) +AC_SUBST(LD_FLAGS) +AC_SUBST(CC) +AC_SUBST(BUILD_CMD) +AC_SUBST(PRE_BUILD) +AC_SUBST(POST_BUILD) +AC_SUBST(RM) +AC_SUBST(MODTCL_TCLOPT) +AC_SUBST(PWD) +AC_SUBST(DEPFLAGS) +AC_SUBST(MAKEDEPEND) + +dnl Checks for header files. +AC_HEADER_DIRENT +AC_HEADER_STDC +AC_CHECK_HEADERS(stropts.h libintl.h sys/dlpi.h kstat.h sys/lock.h stdint.h strings.h string.h malloc.h libgen.h) + +dnl Checks for typedefs, structures, and compiler characteristics. +#AC_C_CONST +#AC_TYPE_SIZE_T +#AC_HEADER_TIME +#AC_STRUCT_TM + +dnl Checks for library functions. +AC_TYPE_SIGNAL +AC_FUNC_VPRINTF +AC_CHECK_FUNCS(mmap rand_r prctl pthread_rwlock_init getloadavg on_exit) + + + dnl **************************** + dnl *** Checks for socklen_t *** + dnl **************************** + + AC_MSG_CHECKING([for socklen_t]) + ac_cv_socklen_t="" + AC_TRY_COMPILE([ +#include +#include + ],[ +socklen_t a=0; +getsockname(0,(struct sockaddr*)0, &a); + ], + ac_cv_socklen_t="socklen_t", + AC_TRY_COMPILE([ +#include +#include + ],[ +int a=0; +getsockname(0,(struct sockaddr*)0, &a); + ], + ac_cv_socklen_t="int", + ac_cv_socklen_t="size_t" + ) + ) + + AC_MSG_RESULT($ac_cv_socklen_t) + if test "$ac_cv_socklen_t" != "socklen_t"; then + AC_DEFINE_UNQUOTED(socklen_t, $ac_cv_socklen_t, + [Define the real type of socklen_t]) + fi + +AC_CONFIG_HEADER(include/config.h) + +AC_OUTPUT(Makefile mecha/Makefile cont/Makefile lib/env.mk) diff --git a/lc-continuity/mk4/continuity/cont/.cvsignore b/lc-continuity/mk4/continuity/cont/.cvsignore new file mode 100644 index 0000000000000000000000000000000000000000..f3c7a7c5da68804a1bdf391127ba34aed33c3cca --- /dev/null +++ b/lc-continuity/mk4/continuity/cont/.cvsignore @@ -0,0 +1 @@ +Makefile diff --git a/lc-continuity/mk4/continuity/cont/CVS/Entries b/lc-continuity/mk4/continuity/cont/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..88b79ef18cf10bc63ecae18f5ba79efa96db797a --- /dev/null +++ b/lc-continuity/mk4/continuity/cont/CVS/Entries @@ -0,0 +1,10 @@ +/.cvsignore/1.1/Thu Mar 11 01:11:48 2004//Tmk4_mod6_rc2 +/Makefile.in/1.23/Mon May 3 14:55:00 2004//Tmk4_mod6_rc2 +/cdog.c/1.6/Tue Mar 30 14:37:43 2004//Tmk4_mod6_rc2 +/continuity.c/1.42/Tue May 11 02:53:17 2004//Tmk4_mod6_rc2 +/dis.c/1.13/Wed Apr 21 21:47:03 2004//Tmk4_mod6_rc2 +/dl.c/1.31/Fri May 14 15:12:34 2004//Tmk4_mod6_rc2 +/mmc.c/1.6/Thu Mar 18 15:04:15 2004//Tmk4_mod6_rc2 +/tas.c/1.7/Fri May 14 06:20:32 2004//Tmk4_mod6_rc2 +/xfr.c/1.11/Thu Mar 18 15:04:15 2004//Tmk4_mod6_rc2 +D diff --git a/lc-continuity/mk4/continuity/cont/CVS/Repository b/lc-continuity/mk4/continuity/cont/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..07b567ec0aef4ef8b30452e92a8ce71691686218 --- /dev/null +++ b/lc-continuity/mk4/continuity/cont/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/continuity/cont diff --git a/lc-continuity/mk4/continuity/cont/CVS/Root b/lc-continuity/mk4/continuity/cont/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/continuity/cont/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/continuity/cont/CVS/Tag b/lc-continuity/mk4/continuity/cont/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/continuity/cont/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/continuity/cont/Makefile.in b/lc-continuity/mk4/continuity/cont/Makefile.in new file mode 100644 index 0000000000000000000000000000000000000000..7db23c3f13d664c36d77504c8ec7e5608f8ee195 --- /dev/null +++ b/lc-continuity/mk4/continuity/cont/Makefile.in @@ -0,0 +1,60 @@ +# $Header: /san01/cvs/ashpool/csrc/continuity/cont/Makefile.in,v 1.23 2004/05/03 14:55:00 aleigh Exp $ + +SRCS=tas.c xfr.c mmc.c dl.c dis.c continuity.c +OBJS=tas.o xfr.o mmc.o dl.o dis.o continuity.o + +MECHA_OBJS=../mecha/ast.o ../mecha/b64.o ../mecha/bsp.o ../mecha/bus.o ../mecha/crc.o ../mecha/dyn.o \ +../mecha/fle.o ../mecha/hsh.o ../mecha/log.o ../mecha/lst.o \ +../mecha/rnd.o ../mecha/str.o ../mecha/thr.o ../mecha/tls.o ../mecha/uid.o ../mecha/utl.o \ +../mecha/lst_void.o ../mecha/qry.o ../mecha/xml.o ../mecha/mem.o ../mecha/exp.o ../mecha/net.o ../mecha/pat.o \ +../mecha/dic.o ../mecha/sys.o ../mecha/cv.o ../pcre/pcreposix.o ../pcre/pcre.o ../pcre/get.o + +MECHA_SRCS=../mecha/ast.c ../mecha/b64.c ../mecha/bsp.c ../mecha/bus.c ../mecha/crc.c ../mecha/dyn.c \ +../mecha/fle.c ../mecha/hsh.c ../mecha/log.c ../mecha/lst.c \ +../mecha/rnd.c ../mecha/str.c ../mecha/thr.c ../mecha/tls.c ../mecha/uid.c ../mecha/utl.c \ +../mecha/lst_void.c ../mecha/qry.c ../mecha/xml.c ../mecha/mem.c ../mecha/exp.c \ +../mecha/net.c ../mecha/pat.c ../mecha/dic.c ../mecha/sys.c ../mecha/cv.c + +CFLAGS=-I../include @ARCH_CFLAGS@ @OPT_CFLAGS@ -D_REENTRANT -DTHR_POOL @BUILD_CFLAGS@ +LD_SHARECMD= @LDSHARED@ +CC=@CC@ +AR_CMD=@AR_CMD@ +BUILDMODE=@BUILDMODE@ +MAKEDEPEND=@MAKEDEPEND@ + +world: build.h $(BUILDMODE) ../bin/cdog + $(RM) build.h + +multishot: $(OBJS) $(MECHA_OBJS) + $(CC) $(CFLAGS) -o ../bin/continuity $(OBJS) $(MECHA_OBJS) @LDFLAGS@ @LIBS@ -L/usr/local/lib +oneshot: $(SRCS) $(MECHA_SRCS) + rm lst.h ; ln -s ../mecha/lst.h . + rm dyn.h ; ln -s ../mecha/dyn.h . + rm net.h ; ln -s ../mecha/net.h . + cat $(SRCS) $(MECHA_SRCS) > _continuity.c + $(CC) $(CFLAGS) _continuity.c -c + $(CC) $(CFLAGS) _continuity.o ../pcre/pcreposix.o ../pcre/pcre.o -o continuity @LDFLAGS@ @LIBS@ -L/usr/local/lib + +../bin/cdog: cdog.c + $(CC) $(CFLAGS) cdog.c -o ../bin/cdog + +clean: + rm -rf $(OBJS) *~ *.ln gmon.out mon.out _continuity.c ../bin/continuity ../bin/cdog + +count: + wc -l `find . -name '*.[ch]'` + +build.h: + @echo \#define CONT_UNAME \"`uname -a`\" > build.h + @echo \#define CONT_DATE \"`date`\" >> build.h + @echo \#define CONT_HOST \"`hostname`\" >> build.h + @echo \#define CONT_CFLAGS \" @CFLAGS@ \" >> build.h + @echo \#define CONT_LDSHARE \" @LDSHARED@ \" >> build.h + @echo \#define CONT_LIBS \" @LIBS@ \" >> build.h + @echo \#define CONT_PREBUILD \" @PRE_BUILD@ \" >> build.h + @echo \#define CONT_POSTBUILD \" @POST_BUILD@ \" >> build.h + +depend: build.h + $(MAKEDEPEND) @DEPFLAGS@ -I ../include $(SRCS) + $(RM) build.h + diff --git a/lc-continuity/mk4/continuity/cont/cdog.c b/lc-continuity/mk4/continuity/cont/cdog.c new file mode 100644 index 0000000000000000000000000000000000000000..0d6ab25e4a1267265fdba6f5209414e4da7bb354 --- /dev/null +++ b/lc-continuity/mk4/continuity/cont/cdog.c @@ -0,0 +1,90 @@ +/* + * $Header: /cvsroot/csrc/continuity/cont/cdog.c,v 1.4 2004/03/18 15:04:15 + * aleigh Exp $ + */ + +/* + * Copyright (c) 1994, 2004 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Disclosure, copying, distribution, or transmission of this code without + * express permission is prohibited. + */ + +#include +#include + +#include "csys.h" + +#define CBIN "./continuity" + +static void print_usage(void); + +static void print_usage(void) +{ + printf("For Continuity startup options, run cdog -h\n"); +} + +int main(int argc, char **argv) +{ + int status; + char **alist; + int acount; + + if (argc == 1) { + print_usage(); + exit(0); + } + + /* Prevent Continuity from daemonizing which will cause + us to lose track of it's PID */ + + if(fork()!=0) { + exit(0); + } + + setsid(); + + if(fork()!=0) { + exit(0); + } + + printf("Continuity Watchdog v1.0.2\n"); + + putenv((char *)"__CONT_NODAEMON=true"); + + signal(SIGHUP, SIG_IGN); + signal(SIGINT, SIG_IGN); + signal(SIGQUIT, SIG_IGN); + signal(SIGPIPE, SIG_IGN); + + acount = argc + 1; + alist = (char **) malloc(acount * sizeof(char *)); + bzero(alist, acount * sizeof(char *)); + bcopy(argv, alist, argc * sizeof(char *)); + alist[0] = (char *) CBIN; + + while (1) { + if (fork() != 0) { + wait(&status); + if (WIFEXITED(status)) { + printf("cdog: Continuity exited, status %d.\n", + WEXITSTATUS(status)); + if (WEXITSTATUS(status) == 5) { + printf("cdog: Continuity requested exit.\n"); + exit(0); + } + if (WEXITSTATUS(status) == 6) { + printf("cdog: Could not start server. Exiting.\n"); + exit(0); + } + } + continue; + } + if (execvp(CBIN, alist) == -1) + exit(6); + } +} diff --git a/lc-continuity/mk4/continuity/cont/continuity.c b/lc-continuity/mk4/continuity/cont/continuity.c new file mode 100644 index 0000000000000000000000000000000000000000..73cb233cb1729445a62db21746a13ebea658c8e2 --- /dev/null +++ b/lc-continuity/mk4/continuity/cont/continuity.c @@ -0,0 +1,382 @@ +/* + * $Header: /san01/cvs/ashpool/csrc/continuity/cont/continuity.c,v 1.42 2004/05/11 02:53:17 aleigh Exp $ + */ + +/* + * Copyright (c) 2001, 2004 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Use, disclosure, copying, distribution, or transmission of this code without + * express permission is prohibited. + */ + +#include "continuity.h" +#include "build.h" + +#if HAVE_PRCTL +#include +#endif + +/* Continuity's birthday is 12.05.2001 */ + +/* + * When the startup is finished, this conditional will receive a broadcast. + */ +static pthread_cond_t startup_conditional = PTHREAD_COND_INITIALIZER; +static int started = 0; + +static xmlTconfig *global_config = NULL; +static const xmlTtag *base_config_tag = NULL; +static hshTvoid_list *socket_stash; + +static void print_version(void); +static int test_build(void); +static void print_usage(void); +static void forever(void); + +static int test_build(void) { + cTval *v; + + CVNEWSTRCPY(v,"foo"); +} + +static void conFdaemonize(void) { + fclose(stdout); + fclose(stdin); + fclose(stderr); + + if(fork()!=0) { + exit(0); + } + + setsid(); + + if(fork()!=0) { + exit(0); + } +} + +const xmlTtag *conFget_config_basetag(void) +{ + assert(base_config_tag != NULL); + return base_config_tag; +} + +/* + * Do not go off the reservation. If you go off the reservation, I will not + * come after you. + */ +void intr_handler(int sigraised) +{ + exit(0); + /* logFmsgid(0, "CON", 1); */ + logFmsg(3, "intr_handler called: rcv'd sigraised %d", sigraised); + signal(SIGINT, intr_handler); + return; +} + +const char *conFget_build(void) +{ + return BUILD_STRING; +} + +static void forever(void) { + while(1) { + thrFsleep(99999); + } +} + +static void print_usage(void) +{ + printf(BUILD_STRING); + printf("\n"); + + printf("Copyright (c) 2001, 2004 Alex Leigh.\n"); + printf("Contains contributions by Eric Lindvall.\n\n"); + + printf("Usage: \tcontinuity -c module.cfg [-o logfile [-r n]] [-u username]\n"); + printf("\tcontinuity -v\n\n"); + printf("\t-c\tPath to the module configuration file.\n"); + printf("\t-o\tOutput messages to a file. Server will run in the background.\n"); + printf("\t-r\tRotate message files and do not use more than n MB total disk.\n"); + printf("\t-u\tUser to run as.\n"); + printf("\t-v\tPrint version information.\n"); +} + +int conFsocketstash_update(int sd, int idx) { + hshFvoid_int_update(socket_stash,idx,(void *)sd); + return 0; +} + +int conFsocketstash_find(int idx) { + int s; + + s=(int)hshFvoid_int_find(socket_stash,idx); + if(s==0) return -1; + return s; +} + +int main(int argc, char **argv) +{ + extern char *optarg; + int ret; + int c = 0, a = 0, t = 0, v = 0, o = 0, r=0, err = 0; + char *c_arg = NULL, *a_arg = NULL, *o_arg = NULL, *r_arg=NULL; + + signal(SIGINT, intr_handler); + signal(SIGPIPE, SIG_IGN); + + socket_stash=hshFvoid_int_init(NULL); + + logFinit(); + + while ((ret = getopt(argc, argv, "tvc:u:a:o:r:")) != EOF) { + switch (ret) { + case 'c': + if (c==1) { + err++; + } else { + c++; + } + c_arg = optarg; + break; + + case 'a': + if (a==1) { + err++; + } else { + a++; + } + a_arg = optarg; + break; + + case 'v': + if (v==1) { + err++; + } else { + v++; + } + break; + + case 't': + if (t==1) { + err++; + } else { + t++; + } + break; + + case 'o': + if (o==1) { + err++; + } else { + o++; + o_arg=optarg; + } + break; + case'r': + if(r==1) { + err++; + } else { + r++; + r_arg=optarg; + } + break; + + default: + err++; + } + } + + if (v==1) { + print_version(); + } + + if (t==1) { + exit(test_build()); + } + + /* no -c */ + if (c==0) { + err++; + } + + /* -r without -o */ + if(r==1&&o==0) { + err++; + } + + if (err != 0) { + print_usage(); + exit(5); + } + + if(r_arg!=NULL) { + logFset_rotatesize(atoi(r_arg)*1048576); + } + + if(o_arg!=NULL) { + if(getenv("__CONT_NODAEMON")==NULL) { + conFdaemonize(); + } + + if(logFset_outputfile(o_arg)==-1) { + perror(o_arg); + exit(1); + } + } + + thrFmod_init(); + + /* Bring the statistics interface online */ + tasFinit(); + tasFstat_counter_add("sys", 0, "startup", utlFtime()); + + logFmsg(0, BUILD_STRING); + logFmsg(0, + "Copyright (c) 2001, 2004 Alex Leigh."); + logFmsg(0, "Contains contributions by Eric Lindvall."); + logFmsg(0, "Use is subject to license terms."); + + global_config = xmlFload_file(c_arg); + if (global_config == NULL) { + logFmsg(2, "Could not load configuration file. [f: %s] [e: %d]", + c_arg, errno); + exit(0); + } + base_config_tag = xmlFbase_tag(global_config); + + assert(base_config_tag != NULL); + + base_config_tag = + xmlFfind_first_tag_children(base_config_tag, "configuration"); + + rndFinit(); + + /* Initialize TLS memory system. */ + tlsFinit(); + + /* Load the module.cfg */ + if (dlFload_config() != STATUS_OK) { + logFmsgid(2, "CON", 2); + exit(5); + } + + /* Initialize mmap memory system -- this creates a thread */ + mmcFinit(); + + started = 1; + + pthread_cond_broadcast(&startup_conditional); + + /* Never exit */ + forever(); + + return 0; +} + + +/* + * This function returns when the init functions have all been executed. + */ +void conFwait_for_init(void) +{ + +#ifdef LINUX + while (1) { + if (started == 1) + return; + thrFsleep(500); + } +#else + pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; + + if (started == 1) + return; + + pthread_cond_wait(&startup_conditional, &mut); +#endif +} + +static void print_version(void) +{ + + printf("%s\n", BUILD_STRING); + printf("Copyright (c) 2001, 2004 Alex Leigh.\n"); + printf + ("Contains contributions by Eric Lindvall.\nUse is subject to license terms.\n\n"); + printf("Built on: %s\n", CONT_DATE); + printf("Hostname: %s\n", CONT_HOST); + printf("%s\n\n", CONT_UNAME); + printf("CFLAGS: %s\n", CONT_CFLAGS); + printf("LDSHARECMD: %s\n", CONT_LDSHARE); + printf("LIBS: %s\n\n", CONT_LIBS); + printf("PRE_BUILD: %s\n", CONT_PREBUILD); + printf("POST_BUILD: %s\n", CONT_POSTBUILD); + + exit(0); +} + +int op_show_version(netTconn *conn) +{ + netFconn_writef(conn,"%s\r\n", BUILD_STRING); + netFconn_writef(conn,"Copyright (c) 2001, 2004 Alex Leigh\r\n"); + netFconn_writef(conn,"Contains contributions by Eric Lindvall\r\n"); + netFconn_writef(conn,"Built on: %s\r\n", CONT_DATE); + netFconn_writef(conn,"Hostname: %s\r\n", CONT_HOST); + netFconn_writef(conn,"%s\r\n\r\n", CONT_UNAME); + netFconn_writef(conn,"CFLAGS: %s\r\n", CONT_CFLAGS); + netFconn_writef(conn,"LDSHARECMD: %s\r\n", CONT_LDSHARE); + netFconn_writef(conn,"LIBS: %s\r\n\r\n", CONT_LIBS); + netFconn_writef(conn,"PRE_BUILD: %s\r\n", CONT_PREBUILD); + netFconn_writef(conn,"POST_BUILD: %s\r\n", CONT_POSTBUILD); + + return STATUS_OK; +} + +int set_userid(MECHA_UNUSED_ARGUMENT void *p, lstTset *opts) { + const char *u_arg = lstFset_get(opts,"user"); + int uid, gid; + + if(u_arg==NULL) return STATUS_ERROR; + + uid = utlFgetuid((const char *)u_arg); + gid = utlFgetgid (u_arg); + + if (gid != -1) { + if (setregid (gid, gid) != 0) { + logFmsg(2, "Unable to change GID to %d. Failing.", + gid); + exit(5); + } else { + logFmsg(0, "Changed GID to %d.", gid); + } + } else { + logFmsg(2, "No such user: %s.", u_arg); + exit(5); + } + + if (uid != -1) { + if (setreuid (uid, uid) != 0) { + logFmsg(2, "Unable to change UID to %s(%d). Failing.", + u_arg, uid); + exit(5); + } else { + logFmsg(0, "Changed UID to %s(%d).", u_arg, uid); + } + } else { + logFmsg(2, "No such user: %s.", u_arg); + exit(5); + } + +#if HAVE_PRCTL + /* if we have the ability to force coredumps -- let's do it */ + prctl (PR_SET_DUMPABLE, 1); +#endif + + return STATUS_PROCEED; +} + diff --git a/lc-continuity/mk4/continuity/cont/dis.c b/lc-continuity/mk4/continuity/cont/dis.c new file mode 100644 index 0000000000000000000000000000000000000000..5e6e0337f120fd9da372fc0ee5e972f6d32c553a --- /dev/null +++ b/lc-continuity/mk4/continuity/cont/dis.c @@ -0,0 +1,445 @@ +/* + * $Header: /datum01/src/continuity/src/dispatch.c,v 1.78.2.5 2002/09/15 + * 02:32:40 aleigh Exp $ + */ + +/* + * Copyright (c) 1994, 2004 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Disclosure, copying, distribution, or transmission of this code without + * express permission is prohibited. + */ + +#undef POLL_LISTENER + +/* + * The new role of the dispatcher in the v3 configuration is to monitor a + * network socket for new connections. When a connection is received, a pool + * thread is used to run a user-provided function to handle the request in + * whatever manner is appropriate. + */ + +#include "csys.h" +#include "mecha.h" + +struct disSsock { + int sd; + uint32_t cli_ipv4_addr; +}; +typedef struct disSsock disTsock; + +struct disSlistener { + int sd; + int ipv4_port; + unsigned int ipv4_ip; + const char *socketstash_id; + int thr_max; + int thr_runq; + int thr_block; + const char *handler_name; + int (*handler)(void *, lstTset *); + thrTtpool *req_pool; +}; + +#include "continuity.h" + +int disFwait_for_startup(disTlistener * listener) +{ + conFwait_for_init(); + + /* We have to create this here, rather than in disFsetup(), because on Linux setguid() + * does not set the user-id for all the threads of a process. + */ + + listener->req_pool = + thrFinit(listener->thr_max, listener->thr_runq, + listener->thr_block); + + return disFlisten_loop(listener); +} + +int ipv4_openport(MECHA_UNUSED_ARGUMENT void *p, lstTset * opts) +{ + const char *port; + const char *ip; + const char *id; + unsigned int port_int; + unsigned int ip_int; + int sd; + + port = lstFset_get(opts, "port"); + if (port == NULL) { + logFmsg(2,"port parameter unset!"); + exit(5); + } + + port_int=atoi(port); + + id = lstFset_get(opts,"id"); + if(id==NULL) { + logFmsg(2,"id parameter unset!"); + exit(5); + } + + ip = lstFset_get(opts, "ip"); + if (ip != NULL) { + struct in_addr saddr; + + if (inet_aton(ip, &saddr) == 0) { + logFmsg(2, "Invalid IP specified."); + return STATUS_ERROR; + } + + ip_int = ntohl(saddr.s_addr); + } else { + ip_int = 0; + } + + sd = netFipv4_listen_tcp(port_int,ip_int, 5); + + if(sd<0) { + logFmsg(2,"Unable to open socket. e: %d", errno); + exit(5); + } + + conFsocketstash_update(sd,atoi(id)); + + return STATUS_OK; +} + +int ipv4_dispatcher(MECHA_UNUSED_ARGUMENT void *p, lstTset * opts) +{ + const char *port; + const char *ip; + const char *threads = lstFset_get(opts, "threads"); + const char *queue = lstFset_get(opts, "queue"); + const char *id = lstFset_get(opts,"id"); + + disTlistener *listener; + pthread_t tid; + + listener = (disTlistener *) malloc(sizeof(disTlistener)); + bzero(listener, sizeof(disTlistener)); + + listener->socketstash_id=id; + + listener->handler_name = lstFset_get(opts, "handler"); + if (listener->handler_name == NULL) { + logFmsg(2, "Handler not specified."); + return STATUS_ERROR; + } + listener->handler = (cont_handler)dlFget_addr(listener->handler_name); + if (listener->handler == NULL) { + logFmsg(2, "Unable to map handler function."); + return STATUS_ERROR; + } + port = lstFset_get(opts, "port"); + if (port == NULL) { + logFmsg(3, "Port unspecified."); + return STATUS_ERROR; + } + listener->ipv4_port = atoi(port); + + if (threads == NULL) + listener->thr_max = 32; + else + listener->thr_max = atoi(threads); + + logFmsg(3, "pool threads: %d", listener->thr_max); + + if (queue == NULL) + listener->thr_runq = 512; + else + listener->thr_runq = atoi(queue); + + listener->thr_block = 0; + + ip = lstFset_get(opts, "ip"); + if (ip != NULL) { + struct in_addr saddr; + + if (inet_aton(ip, &saddr) == 0) { + logFmsg(2, "Invalid IP specified."); + return STATUS_ERROR; + } + + listener->ipv4_ip = ntohl(saddr.s_addr); + } else { + listener->ipv4_ip = 0; + } + + listener->sd = disFsetup(listener); + + if (listener->sd < 0) + return STATUS_ERROR; + + pthread_create(&tid, NULL, (void *(*)(void *)) disFwait_for_startup, + listener); + + return STATUS_OK; +} + +/* + * Create a dispatcher. + */ +int disFsetup(disTlistener * listener) +{ + int sock; + + logFmsgid(0, "CON", 10, listener->thr_max, listener->thr_runq, + listener->thr_block); + + if(listener->socketstash_id!=NULL) { + logFmsg(3,"Getting socket from stash."); + sock=conFsocketstash_find(atoi(listener->socketstash_id)); + logFmsg(3,"socket is %d", sock); + } else { + sock = netFipv4_listen_tcp(listener->ipv4_port, listener->ipv4_ip, 5); + } + + if (sock < 0) { + logFmsgid(2, "CON", 5, errno); + exit(5); + } + + fleFset_close_exec(sock); + + return sock; +} + +#ifndef POLL_LISTENER +int disFlisten_loop(disTlistener * listener) +{ + struct sockaddr_in ca; + + int calen = sizeof(ca); + int ns; + struct in_addr *ia; + pthread_attr_t tattr; + netTconn *conn; + + assert(listener->handler != NULL); + assert(listener->req_pool != NULL); + + listen(listener->sd, 1024); + + logFmsgid(0, "CON", 6, pthread_self(), listener->handler); + + pthread_attr_init(&tattr); + pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); + + while (1) { + conn = (netTconn *) malloc(sizeof(netTconn)); + + ns = accept(listener->sd, (struct sockaddr *) &ca, (socklen_t *) &calen); + + if (ns == -1) { + if (errno == EINTR) { + logFmsgid(0, "CON", 7); + intr_handler(0); + } + logFmsgid(1, "CON", 8, strerror(errno)); + continue; + } + + fleFset_close_exec(ns); + + netFset_reuse(ns); /* Set the socket to be reusable */ +/* netFset_nodelay(ns); */ + +#ifdef NOTDEF + /* Set the socket to nonblocking */ + if ((fd_flags = fcntl(ns, F_GETFL)) == -1) + return -1; + fd_flags |= O_NONBLOCK; + if (fcntl(ns, F_SETFL, fd_flags) == -1) + return -1; +#endif + + ia = &ca.sin_addr; + + conn->sd = ns; + conn->cli_ipv4_addr = ntohl(ia->s_addr); + conn->io_read = &netFconn_os_read; + conn->io_write = &netFconn_os_write; + conn->io_close = &netFconn_os_close; + conn->io_writev = &netFconn_os_writev; + conn->data_free = NULL; + + tasFstat_counter_add("net", 0, "conn_rcvd", 1); + + /* + * It's up to the work fucntion to free the connection structure + * whenever it's done with it + */ + + if (thrFadd_work(listener->req_pool, (mecha_handler)listener->handler, conn) == -1) { + logFmsgid(1, "CON", 9); + conn->io_close(conn); + } + } +} + +#else +/* + * this is the primary function that the dispatcher spins in while receiving + * connections. A connection is received and then placed into the poll list. + * If it becomes available for read, it is put on the work list where a + * thread will pick it up when one becomes available. This ensures that the + * request data has been received, which prevents read() from spinning on the + * socket later. + */ + +int disFlisten_loop(disTlistener * listener) +{ + struct sockaddr_in ca; + int calen = sizeof(ca); + int ns, fd_flags; + struct in_addr *ia; + pthread_attr_t tattr; + netTconn *conn; + int i, ret; + + struct pollfd *pfds; + int nfds; + disTsock *socks; + int maxsds = listener->thr_max + 1; + + assert(listener->handler != NULL); + assert(listener->req_pool != NULL); + + listen(listener->sd, 1024); + + logFmsgid(0, "CON", 6, pthread_self(), listener->handler); + + pthread_attr_init(&tattr); + pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); + + /* + * Create a pfd array large enough to hold an entry for every possible + * connection, which is equal to the number of threads. + */ + pfds = (struct pollfd *) malloc(sizeof(struct pollfd) * maxsds); + + socks = (disTsock *) malloc(sizeof(disTsock) * maxsds); + bzero(socks, sizeof(disTsock) * maxsds); + + if ((fd_flags = fcntl(listener->sd, F_GETFL)) == -1) + return -1; + fd_flags |= O_NONBLOCK; + if (fcntl(listener->sd, F_SETFL, fd_flags) == -1) + return -1; + + pfds[0].fd = listener->sd; + pfds[0].events = POLLIN | POLLPRI; + + while (1) { + /* Create poll list of socks currently in socks */ + + /* { utlTswatch *sw = utlFstart_swatch(); */ + nfds = 1; /* we start with the listener */ + for (i = 0; i < listener->thr_max; i++) { + if (socks[i].sd > 0) { + pfds[nfds].fd = socks[i].sd; + pfds[nfds].events = POLLIN | POLLPRI; + nfds++; + } + } + /* logFmsg(3,"poll build took %d us", utlFstop_swatch(sw));} */ + + + /* { utlTswatch *sw = utlFstart_swatch(); */ + ret = poll(pfds, nfds, 5000); + /* logFmsg(3,"poll() took %d us", utlFstop_swatch(sw));} */ + + + if (ret == -1) { + logFmsg(2, "poll() returned -1 (e: %d)", errno); + exit(1); + } + if (poll > 0) { + for (i = 1; i < nfds; i++) { + if ((pfds[i].revents & POLLIN) == POLLIN) { + int x; + + for (x = 0; x < listener->thr_max; x++) { + if (socks[x].sd == pfds[i].fd) { + conn = (netTconn *) malloc(sizeof(netTconn)); + + conn->cli_ipv4_addr = socks[x].cli_ipv4_addr; + conn->sd = socks[x].sd; + conn->io_read = &netFconn_os_read; + conn->io_write = &netFconn_os_write; + conn->io_close = &netFconn_os_close; + conn->io_writev = &netFconn_os_writev; + conn->data_free = NULL; + + + logFmsg(3, "%d", conn->sd); + + socks[x].sd = 0; + + tasFstat_counter_add("net", 0, "conn_rcvd", 1); + + if (thrFadd_work + (listener->req_pool, listener->handler, + conn) == -1) { + logFmsgid(1, "CON", 9); + close(conn->sd); + free(conn); + } + } + } + } + } + + /* if (pfds[0].revents & POLLIN == POLLIN) { */ + ns = accept(listener->sd, (struct sockaddr *) &ca, + (int *) &calen); + + if (ns == -1) { + if (errno == EINTR) { + logFmsgid(0, "CON", 7); + intr_handler(0); + } + /* logFmsgid(1, "CON", 8, strerror(errno)); */ + continue; + } + netFset_reuse(ns); /* Set the socket to be reusable */ + netFset_nodelay(ns); /* Disable the NAGLE algorithm on the socket */ + + { + unsigned int x = 50000; + if (setsockopt + (ns, SOL_SOCKET, SO_SNDBUF, &x, + sizeof(unsigned int)) == -1) { + logFmsg(3, + "setsockopt() SNDBUF failed: e: %d", + errno); + } + } + + /* Set the socket to nonblocking */ + if ((fd_flags = fcntl(ns, F_GETFL)) == -1) + return -1; + fd_flags |= O_NONBLOCK; + if (fcntl(ns, F_SETFL, fd_flags) == -1) + return -1; + + ia = &ca.sin_addr; + for (i = 0; i < listener->thr_max; i++) { + if (socks[i].sd == 0) { + socks[i].sd = ns; + socks[i].cli_ipv4_addr = ntohl(ia->s_addr); + break; + } + } + } + } +} + +#endif diff --git a/lc-continuity/mk4/continuity/cont/dl.c b/lc-continuity/mk4/continuity/cont/dl.c new file mode 100644 index 0000000000000000000000000000000000000000..35b401de914f11bf04fceac0f261a08db9703e35 --- /dev/null +++ b/lc-continuity/mk4/continuity/cont/dl.c @@ -0,0 +1,702 @@ +/* + * $Header: /datum01/src/continuity/src/dl.c,v 1.41.2.6 2002/09/11 18:02:28 + * aleigh Exp $ + */ + +/* + * Copyright (c) 1994, 2004 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Disclosure, copying, distribution, or transmission of of this code without + * express permission is prohibited. + */ + +/* + * MTS: The category list is MTS write unsafe. + */ + +#include "csys.h" +#include "mecha.h" + +struct dlSlib { + char *fn; // Filename without extension; ie ../lib/site + void *handle; // Handle to the library load + char *name; // Short name of the module. + xmlTconfig *profile; // XML profile (if provided) + struct dlSlib *next; +}; +typedef struct dlSlib dlTlib; + +struct dlSmap { + char symbol[64]; + void *addr; + lstTset *opts; + struct dlSmap *next; +}; + +struct dlSentry { + lstTset *opts; + int (*addr)(void *, lstTset *); + struct dlSentry *next; +}; + +struct dlScategory { + char *name; + unsigned int id; + struct dlSentry *entry; + struct dlScategory *next; +}; + +#include "continuity.h" + +static void dlFcreate_config(void); +static void dlFmap_append(dlTmap ** mapset, dlTmap * entry); +static void dlFentry_append(dlTcategory * category, dlTentry * entry); +static dlTcategory *dlFcategory_getbyid(unsigned int catid); +static dlTcategory *dlFcategory_get(const char *category); +static dlTcategory *dlFcategory_add(const char *category); +static void dlFresolve_categories(void); +static int dlFsatisfy_conditions(dlTlib *lib); + +#include + +#ifndef LINUX +/* #include */ +#endif + +unsigned int dlGcategory_seq = 0; +dlTcategory *dlGcategories = NULL; +dlTlib *dlGlibs = NULL; +dlTmap *dlGmap = NULL; + +int dlFop_show_dl_loads(netTconn *conn, int argc, char **argv) { + netFconn_writef(conn,"\r\nDL Loads\r\n--------\r\n"); + if(dlGlibs==NULL) { + netFconn_writef(conn,"No loads.\r\n"); + return STATUS_OK; + } + + for(dlTlib *p=dlGlibs;p!=NULL;p=p->next) { + netFconn_writef(conn,"%s\r\n", p->fn); + } + + return STATUS_OK; +} + +int dlFop_show_dl_symbols(netTconn *conn, int argc, char **argv) { + netFconn_writef(conn,"\r\nSymbols\r\n-------\r\n"); + + if(dlGmap==NULL) { + netFconn_writef(conn,"No dynamic symbols.\r\n"); + return STATUS_OK; + } + + for(dlTmap *p=dlGmap;p!=NULL;p=p->next) { + netFconn_writef(conn,"0x%06x %s()\r\n", p->addr, p->symbol); + } + return STATUS_OK; +} + +/* + * Append a new function reference to the map. This is reverse order out of + * legacy from mk2 and should probably be changed to just FILO the list, + * since the order is no longer relavant in mk3. + */ +static void dlFmap_append(dlTmap ** mapset, dlTmap * entry) +{ + dlTmap *p; + + if (*mapset == NULL) { + entry->next = NULL; + *mapset = entry; + return; + } + p = (dlTmap *) * mapset; + + while (1) { + if (p->next == NULL) { + entry->next = NULL; + p->next = entry; + return; + } else { + p = p->next; + } + } +} + +/* + * FIFO an entry into the categories list. The order is important here since + * this is the order they are going to get executed in the pipeline. + */ +static void dlFentry_append(dlTcategory * category, dlTentry * entry) +{ + dlTentry *p; + + if (category->entry == NULL) { + entry->next = NULL; + category->entry = entry; + return; + } + p = (dlTentry *) category->entry; + + while (1) { + if (p->next == NULL) { + entry->next = NULL; + p->next = entry; + return; + } else { + p = p->next; + } + } +} + +/* + * Return the category structure for the given cateogy name. Returns NULL if + * the category did not exist. + */ +static dlTcategory *dlFcategory_getbyid(unsigned int catid) +{ + dlTcategory *cat; + + cat = dlGcategories; + while (cat != NULL) { + if (catid == cat->id) { + return cat; + } + cat = cat->next; + } + return NULL; +} + +/* + * Return the category structure for the given cateogy name. Returns NULL if + * the category did not exist. + */ +static dlTcategory *dlFcategory_get(const char *category) +{ + dlTcategory *cat; + + cat = dlGcategories; + while (cat != NULL) { + if (strcmp(cat->name, category) == 0) { + return cat; + } + cat = cat->next; + } + return NULL; +} + +/* + * Return the catid for the given category name. Returns -1 if the name was + * not found. + */ +int dlFpipeline_getid(const char *pipeline) +{ + dlTcategory *cat; + + cat = dlGcategories; + while (cat != NULL) { + if (strcmp(cat->name, pipeline) == 0) { + return cat->id; + } + cat = cat->next; + } + return -1; +} + +/* + * o/~ What we see, and what we seem, are but a dream, within a dream o/~ + */ + +static dlTcategory *dlFcategory_add(const char *category) +{ + dlTcategory *cat; + + cat = (dlTcategory *) malloc(sizeof(dlTcategory)); + cat->name = strFcopy(category); + + /* + * Side-effect + */ + cat->id = dlGcategory_seq++; + cat->entry = NULL; + + cat->next = dlGcategories; + dlGcategories = cat; + + return cat; +} + +int dlFload_config(void) +{ + dlTcategory *category; + const xmlTtag *atag; + xmlTiterator *ait; + + dlFcreate_config(); + + atag = conFget_config_basetag(); + assert(atag != NULL); + if (atag == NULL) + return -1; + + atag = xmlFfind_first_tag_children(atag, "continuity_config"); + assert(atag != NULL); + + if (atag == NULL) + return -1; + + atag = xmlFfind_first_tag_children(atag, "modules"); + assert(atag != NULL); + + if (atag == NULL) + return -1; + + ait = xmlFiterator_init(atag); + assert(ait != NULL); + + while ((atag = xmlFiterator_next_name(ait, "module")) != NULL) { + const char *value = xmlFtag_get_value_str(atag); + dlFload_library(value); + } + + xmlFiterator_free(ait); + + /* Run the init class */ + + category = dlFcategory_get("init"); + + dlFresolve_categories(); + + dlFpipeline_exec(NULL, dlFpipeline_getid("__init"), NULL, NULL); + dlFpipeline_exec(NULL, dlFpipeline_getid("init"), NULL, NULL); + + return STATUS_OK; +} + +/* + * This function is used to execute one of the dynamic categories. By the + * time this function is called, all of the addresses in the category should + * have been mapped. + */ +int dlFpipeline_exec(void *payload, int catid, const char *limit_name, + const char *limit_value) +{ + dlTcategory *cat; + dlTentry *entry; + int (*func) (void *, lstTset *); + register int ret; + const char *limit; + register int done = 1; + int restart_count = 0; + + cat = dlFcategory_getbyid(catid); + + if (cat == NULL) { + return STATUS_ERROR; + } + + if (cat->entry == NULL) { + return STATUS_OK; + } + + while (1) { + if (limit_name != NULL && limit_value != NULL) { + for (entry = cat->entry; entry != NULL; entry = entry->next) { + limit = lstFset_get(entry->opts, limit_name); + if (limit != NULL) { + if (strcmp(limit_value, limit) != 0) + continue; + } + func = (int (*)(void *, lstTset *)) entry->addr; + + ret = (func) (payload, entry->opts); + if (ret == STATUS_EXIT) + return ret; + + if (ret == STATUS_RESTART) { + done = 0; + break; + } + } + } else { + for (entry = cat->entry; entry != NULL; entry = entry->next) { + func = (int (*)(void *, lstTset *)) entry->addr; + ret = (func) (payload, entry->opts); + if (ret == STATUS_EXIT) + return ret; + if (ret == STATUS_RESTART) { + done = 0; + break; + } + } + } + + if (done == 0) { + restart_count++; + if (restart_count > 32) + return STATUS_ERROR; + done = 1; + continue; + } + break; + } + return STATUS_OK; +} + +static void dlFresolve_categories(void) +{ + dlTcategory *c; + dlTentry *e; + const char *sym; + + for (c = dlGcategories; c != NULL; c = c->next) { + for (e = c->entry; e != NULL; e = e->next) { + sym = lstFset_get(e->opts, "fn"); + if (sym == NULL) + continue; + + if (strcmp(sym, "ipv4_dispatcher") == 0) { + e->addr = ipv4_dispatcher; + } else { + if(strcmp(sym,"set_userid")==0) { + e->addr=set_userid; + } else { + if(strcmp(sym,"ipv4_openport")==0) { + e->addr=ipv4_openport; + } else { + e->addr = (cont_handler)dlFget_addr(sym); + + if (e->addr == NULL) { + logFmsg(2, + "Failed to map function %s from loaded libraries.", + sym); + exit(5); + } + } + } + } + } + } +} + +static void dlFcreate_config(void) +{ + const xmlTtag *atag, *btag, *ctag; + xmlTiterator *ait, *bit, *cit; + dlTentry *entry; + dlTcategory *cat; + + /* + * Create the special __init pipeline that will hold + * the automatic init handlers. + */ + dlFcategory_add("__init"); + + atag = conFget_config_basetag(); + if (atag == NULL) + return; + + atag = xmlFfind_first_tag_children(atag, "continuity_config"); + if (atag == NULL) + return; + + atag = xmlFfind_first_tag_children(atag, "pipelines"); + if (atag == NULL) + return; + + ait = xmlFiterator_init(atag); + assert(ait != NULL); + + while ((atag = xmlFiterator_next_name(ait, "pipeline")) != NULL) { + const char *name = xmlFtag_get_attrib_value(atag, "name"); + assert(name != NULL); + cat = dlFcategory_get(name); + if (cat == NULL) + cat = dlFcategory_add(name); + + bit = xmlFiterate_children(atag); + if (bit != NULL) { + while ((btag = xmlFiterator_next_name(bit, "handler")) != NULL) { + const char *func = xmlFtag_get_attrib_value(btag, "func"); + assert(func != NULL); + + entry = (dlTentry *) malloc(sizeof(dlTentry)); + bzero(entry, sizeof(dlTentry)); + entry->opts = lstFset_init(); + lstFset_add(entry->opts, "fn", func); + + cit = xmlFiterate_children(btag); + if (cit != NULL) { + while ((ctag = + xmlFiterator_next_name(cit, "arg")) != NULL) { + const char *arg_name = + xmlFtag_get_attrib_value(ctag, "name"); + const char *arg_value = xmlFtag_get_value_str(ctag); + if (arg_name != NULL && arg_value != NULL) { + lstFset_add(entry->opts, arg_name, arg_value); + } + } + xmlFiterator_free(cit); + } + dlFentry_append(cat, entry); + } + xmlFiterator_free(bit); + } + } + xmlFiterator_free(ait); +} + +/* Check to see if the conditions of the XML profile + * are met and that this module should be loaded. The specific + * requirements that are checked are that the modules listed + * in the tag have already been loaded into the + * server. */ +static int dlFsatisfy_conditions(dlTlib *lib) +{ + xmlTtag *tag, *req; + xmlTiterator *it; + + /* + * If there is no XML profile associated with the module + * there's nothing we can do but hope. + */ + + if(lib->profile==NULL) { + return -1; + } + + tag=xmlFbase_tag(lib->profile); + + /* If we have a profile but it's empty that's the same + as not having any requirements, so we pass this + config */ + + if(tag==NULL) { + return 0; + } + + tag=xmlFtag_get_children(tag); + + /* Ditto */ + if(tag==NULL) { + return 0; + } + + req=xmlFfind_first_tag_children(tag,"requires"); + + /* Ditto */ + if(req==NULL) { + return 0; + } + + it=xmlFiterator_init(req); + + assert(it!=NULL); + + while((tag=xmlFiterator_next_name(it,"require"))!=NULL) { + char *required=xmlFtag_get_value_str(tag); + int found=0; + + if(required==NULL) continue; + +// logFmsg(3,"Module requires %s; searching...", xmlFtag_get_value_str(tag)); + + for(dlTlib *lp=dlGlibs;lp!=NULL;lp=lp->next) { + /* Not all modules have profiles, so not + * all modules have names. */ + if(lp->name==NULL) continue; + + if(strcmp(lp->name,required)==0) { + found=1; + break; + } + } + + if(found==0) { + logFmsg(2,"Unable to load module: requires %s", required); + return -1; + } + } + + xmlFiterator_free(it); + + return 0; +} + +/* Load the requested library. This is called directly in reponse + * to tags stored in the XML configuration. + */ +int dlFload_library(const char *shlib) +{ + void *handle; + dlTlib *lib; + char xmlpath[1024]; + char sopath[1024]; + dlTcategory *cat = dlFcategory_get("__init"); + + assert(shlib != NULL); + assert(cat!=NULL); + + snprintf(xmlpath,1024,"%s.xml", shlib); + snprintf(sopath,1024,"%s.so",shlib); + + lib = (dlTlib *) malloc(sizeof(dlTlib)); + + memFclear (lib, sizeof (dlTlib)); + + if(fleFexist(xmlpath)==0) { + logFmsg(0,"XML profile %s not found.", xmlpath); + } else { + char *xmlfile; + size_t xmllen; +// logFmsg(3,"XML profile found for %s", shlib); + + xmlfile=fleFload_file(xmlpath,&xmllen); + if(xmlfile==NULL) { + logFmsg(1,"Unable to load XML profile. %s", xmlpath); + exit(5); + } + lib->profile=xmlFparse(xmlfile); + if(lib->profile==NULL) { + logFmsg(1,"Unable to parse XML profile. %s", xmlpath); + } else { + xmlTtag *base, *tag; + + base=xmlFbase_tag(lib->profile); + if(base!=NULL) { + tag=xmlFfind_first_child(base,"module_name"); + if(tag!=NULL) { + const char *n = xmlFtag_get_value_str(tag); + if(n!=NULL) { + lib->name=n; +// logFmsg(3,"Module was named %s", n); + } + } + + tag=xmlFfind_first_child(base,"init_func"); + if(tag!=NULL) { + const char *f = xmlFtag_get_value_str(tag); + + if(f!=NULL) { + dlTentry *e; + + e=(dlTentry *)malloc(sizeof(dlTentry)); + memFclear(e,sizeof(dlTentry)); + e->opts=lstFset_init(); + lstFset_add(e->opts,"fn",f); + dlFentry_append(cat,e); + } + } + } + +// logFmsg(3,"XML profile loaded."); + if(dlFsatisfy_conditions(lib)!=0) { + logFmsg(2,"Could not load module %s. Failing.", shlib); + exit(5); + } + } + } + +#ifndef OPENBSD + handle = dlopen(sopath, RTLD_LAZY | RTLD_GLOBAL); +#else + handle = dlopen(sopath, RTLD_LAZY); +#endif + + if (handle == NULL) { + logFmsg(3, "Unable to dlopen() shlib %s: %s", + sopath, dlerror()); + exit(1); + } else { + logFmsg(0, "Loaded %s", sopath); + } + + + lib->fn = strFcopy(shlib); + lib->handle = handle; + + lib->next = dlGlibs; + dlGlibs = lib; + + return STATUS_OK; +} + +void *dlFget_addr(const char *name) +{ + void *sym; + dlTmap *map; + dlTlib *l; + +#if defined(SOLARIS)||defined(DARWIN) + void *ghandle; +#endif + +#if defined(SOLARIS)||defined(DARWIN) +#ifdef SOLARIS + sym = dlsym(RTLD_DEFAULT, name); +#else /* darwin */ + ghandle = dlopen(NULL, 0); + sym = dlsym(ghandle, name); +#endif +#else + sym = dlsym(NULL, name); +#endif + + if (sym == NULL) { + char buf[64]; + + snprintf(buf, sizeof(buf), "_%s", name); + +#if defined(SOLARIS)||defined(DARWIN) +#ifdef SOLARIS + sym = dlsym(RTLD_DEFAULT, buf); + +#else /* darwin */ + sym = dlsym(ghandle, buf); +#endif +#else + sym = dlsym(NULL, buf); +#endif + } + /**** Try the loaded libraries ****/ + + for (l = dlGlibs; l != NULL; l = l->next) { + sym = dlsym(l->handle, name); + + /* + * Also required for OPENBSD but we dropped support for that anyways + */ +#ifdef DARWIN + if (sym == NULL) { + char buf[64]; + + snprintf(buf, sizeof(buf), "_%s", name); + sym = dlsym(l->handle, buf); + } +#endif + if (sym != NULL) + break; + } + + if (sym == NULL) { + logFmsg(1, "Failed to map symbol %s.", name); + return NULL; + } + /* + * We've found the symbol but it wasn't in the map cache, so we're going + * to add it. + */ + + map = (dlTmap *) malloc(sizeof(dlTmap)); + map->addr = sym; + strcpy(map->symbol, name); + map->opts = NULL; + + dlFmap_append(&dlGmap, map); + + return sym; +} diff --git a/lc-continuity/mk4/continuity/cont/mmc.c b/lc-continuity/mk4/continuity/cont/mmc.c new file mode 100644 index 0000000000000000000000000000000000000000..7bb8315e1cd702b59068e2d2b33cdde46a160797 --- /dev/null +++ b/lc-continuity/mk4/continuity/cont/mmc.c @@ -0,0 +1,452 @@ +/* $Header: /san01/cvs/ashpool/csrc/continuity/cont/mmc.c,v 1.6 2004/03/18 15:04:15 aleigh Exp $ */ +/* + * Copyright (c) 1994, 2004 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Disclosure, copying, distribution, or transmission of this code without + * express permission is prohibited. + */ + + +#include "continuity.h" +#include "mecha.h" + +#ifdef HAVE_MMAP +#include +#endif /* HAVE_MMAP */ + +/* Defines. */ +#ifndef DEFAULT_EXPIRE_AGE +#define DEFAULT_EXPIRE_AGE 600 +#endif +#ifndef DESIRED_FREE_COUNT +#define DESIRED_FREE_COUNT 100 +#endif +#ifndef DESIRED_MAX_MAPPED_FILES +#define DESIRED_MAX_MAPPED_FILES 2000 +#endif +#ifndef INITIAL_HASH_SIZE +#define INITIAL_HASH_SIZE (1 << 10) +#endif + +#define max(a,b) ((a)>(b)?(a):(b)) +#define min(a,b) ((a)<(b)?(a):(b)) + + +/* The Map struct. */ +typedef struct MapStruct { + ino_t ino; + dev_t dev; + off_t size; + time_t ctime; + int refcount; + time_t reftime; + void *addr; + unsigned int hash; + int hash_idx; + struct MapStruct *next; +} Map; + +static Map *maps = (Map *) 0; +static Map *free_maps = (Map *) 0; +static int alloc_count = 0, map_count = 0, free_count = 0; +static Map **hash_table = (Map **) 0; +static int hash_size; +static unsigned int hash_mask; +static time_t expire_age = DEFAULT_EXPIRE_AGE; + +static void really_unmap(Map ** mm); +static int check_hash_size(void); +static int add_hash(Map * m); +static Map *find_hash(ino_t ino, dev_t dev, off_t size, time_t stat_ctime); +static unsigned int hash(ino_t ino, dev_t dev, off_t size, + time_t stat_ctime); + +int mmcFinit(void) +{ + pthread_t ignored; + + pthread_create(&ignored, NULL, (void *(*)(void *)) mmcFcleanup_thr, + NULL); + + return STATUS_OK; +} + +void *mmcFmap(const char *filename, struct stat *sbP, struct timeval *nowP) +{ + time_t now; + struct stat sb; + Map *m; + int fd; + + /* Stat the file, if necessary. */ + if (sbP != (struct stat *) 0) + sb = *sbP; + else { + if (stat(filename, &sb) != 0) { + logFmsgid(1, "CON", 12, filename, errno); + return NULL; + } + } + + /* Get the current time, if necessary. */ + if (nowP != (struct timeval *) 0) + now = nowP->tv_sec; + else + now = time((time_t *) 0); + + /* See if we have it mapped already, via the hash table. */ + if (check_hash_size() < 0) { + logFmsgid(1, "CON", 13, "mmc: check_hash_size() failed."); + return NULL; + } + m = find_hash(sb.st_ino, sb.st_dev, sb.st_size, sb.st_ctime); + if (m != (Map *) 0) { + /* Yep. Just return the existing map */ + ++m->refcount; + m->reftime = now; + return m->addr; + } + /* Open the file. */ + fd = open(filename, O_RDONLY); + if (fd < 0) { + logFmsgid(1, "CON", 14, filename, errno); + return NULL; + } + + /* don't keep this fd open on fork() */ + fleFset_close_exec(fd); + + /* Find a free Map entry or make a new one. */ + if (free_maps != (Map *) 0) { + m = free_maps; + free_maps = m->next; + --free_count; + } else { + m = (Map *) malloc(sizeof(Map)); + if (m == (Map *) 0) { + (void) close(fd); + logFmsgid(1, "CON", 15, "mmc map creation"); + return NULL; + } + ++alloc_count; + } + + /* Fill in the Map entry. */ + m->ino = sb.st_ino; + m->dev = sb.st_dev; + m->size = sb.st_size; + m->ctime = sb.st_ctime; + m->refcount = 1; + m->reftime = now; + + /* + * Avoid doing anything for zero-length files; some systems don't like * + * to mmap them, other systems dislike mallocing zero bytes. + */ + if (m->size == 0) + m->addr = (void *) 1; /* arbitrary non-NULL address */ + else { +#ifdef HAVE_MMAP + /* Map the file into memory. */ + m->addr = mmap(0, m->size, PROT_READ, MAP_SHARED, fd, 0); + if (m->addr == MAP_FAILED) { + logFmsgid(1, "CON", 16, errno, "mmc"); + (void) close(fd); + free((void *) m); + --alloc_count; + return NULL; + } +#else /* HAVE_MMAP */ + /* Read the file into memory. */ + m->addr = (void *) malloc(m->size); + if (m->addr == NULL) { + logFmsgid(1, "CON", 15, "mmc: file store"); + (void) close(fd); + free((void *) m); + --alloc_count; + return NULL; + } + if (read(fd, m->addr, m->size) != m->size) { + logFmsgid(1, "CON", 17, errno, "mmcFmap"); + (void) close(fd); + free((void *) m); + --alloc_count; + return NULL; + } +#endif /* HAVE_MMAP */ + } + (void) close(fd); + + /* Put the Map into the hash table. */ + if (add_hash(m) < 0) { + logFmsgid(1, "CON", 13, "mmc: add_hash() failure."); + free((void *) m); + --alloc_count; + return (void *) 0; + } + /* Put the Map on the active list. */ + m->next = maps; + maps = m; + ++map_count; + + /* And return the address. */ + return m->addr; +} + + +void mmc_unmap(void *addr, struct stat *sbP, struct timeval *nowP) +{ + Map *m = (Map *) 0; + + /* Find the Map entry for this address. First try a hash. */ + if (sbP != (struct stat *) 0) { + m = find_hash(sbP->st_ino, sbP->st_dev, sbP->st_size, + sbP->st_ctime); + if (m != (Map *) 0 && m->addr != addr) + m = (Map *) 0; + } + /* If that didn't work, try a full search. */ + if (m == (Map *) 0) + for (m = maps; m != (Map *) 0; m = m->next) + if (m->addr == addr) + break; + if (m == (Map *) 0) + logFmsgid(1, "CON", 13, "mmcFunmap: Unable to find entry."); + else if (m->refcount <= 0) + logFmsgid(1, "CON", 13, "mmcFunmap: Reference was <=0"); + else { + --m->refcount; + if (nowP != (struct timeval *) 0) + m->reftime = nowP->tv_sec; + else + m->reftime = time((time_t *) 0); + } +} + + +void mmcFcleanup(void) +{ + time_t now; + Map **mm; + Map *m; + + /* Get the current time, if necessary. */ + now = time((time_t *) 0); + + /* Really unmap any unreferenced entries older than the age limit. */ + for (mm = &maps; *mm != (Map *) 0;) { + m = *mm; + if (m->refcount == 0 && now - m->reftime >= expire_age) + really_unmap(mm); + else + mm = &(*mm)->next; + } + + /* If there are still too many (or too few) maps, adjust the age limit. */ + if (map_count > DESIRED_MAX_MAPPED_FILES) + expire_age = max((expire_age * 2) / 3, DEFAULT_EXPIRE_AGE / 10); + else if (map_count < DESIRED_MAX_MAPPED_FILES / 2) + expire_age = min((expire_age * 5) / 4, DEFAULT_EXPIRE_AGE * 3); + + /* Really free excess blocks on the free list. */ + while (free_count > DESIRED_FREE_COUNT) { + m = free_maps; + free_maps = m->next; + --free_count; + free((void *) m); + --alloc_count; + } +} + +void mmcFcleanup_thr(void) +{ + while (1) { + mmcFcleanup(); + thrFsleep(60000); + } +} + +static void really_unmap(Map ** mm) +{ + Map *m; + + m = *mm; + if (m->size != 0) { +#ifdef HAVE_MMAP + if (munmap(m->addr, m->size) < 0) + logFmsgid(1, "CON", 18, errno, "mmc"); +#else /* HAVE_MMAP */ + free((void *) m->addr); +#endif /* HAVE_MMAP */ + } + /* And move the Map to the free list. */ + *mm = m->next; + --map_count; + m->next = free_maps; + free_maps = m; + ++free_count; + /* + * This will sometimes break hash chains, but that's harmless; the * + * unmapping code that searches the hash table knows to keep searching. + */ + hash_table[m->hash_idx] = (Map *) 0; +} + + +void mmc_destroy(void) +{ + Map *m; + + while (maps != (Map *) 0) + really_unmap(&maps); + while (free_maps != (Map *) 0) { + m = free_maps; + free_maps = m->next; + --free_count; + free((void *) m); + --alloc_count; + } +} + +/* Make sure the hash table is big enough. */ +static int check_hash_size(void) +{ + int i; + Map *m; + + /* Are we just starting out? */ + if (hash_table == (Map **) 0) { + hash_size = INITIAL_HASH_SIZE; + hash_mask = hash_size - 1; + } + /* Is it at least three times bigger than the number of entries? */ + else if (hash_size >= map_count * 3) + return 0; + else { + /* No, got to expand. */ + free((void *) hash_table); + /* Double the hash size until it's big enough. */ + do { + hash_size = hash_size << 1; + } + while (hash_size < map_count * 6); + hash_mask = hash_size - 1; + } + /* Make the new table. */ + hash_table = (Map **) malloc(hash_size * sizeof(Map *)); + if (hash_table == (Map **) 0) + return -1; + /* Clear it. */ + for (i = 0; i < hash_size; ++i) + hash_table[i] = (Map *) 0; + /* And rehash all entries. */ + for (m = maps; m != (Map *) 0; m = m->next) + if (add_hash(m) < 0) + return -1; + return 0; +} + + +static int add_hash(Map * m) +{ + unsigned int h, he, i; + + h = hash(m->ino, m->dev, m->size, m->ctime); + he = (h + hash_size - 1) & hash_mask; + for (i = h;; i = (i + 1) & hash_mask) { + if (hash_table[i] == (Map *) 0) { + hash_table[i] = m; + m->hash = h; + m->hash_idx = i; + return 0; + } + if (i == he) + break; + } + return -1; +} + + +static Map *find_hash(ino_t ino, dev_t dev, off_t size, time_t stat_ctime) +{ + unsigned int h, he, i; + Map *m; + + h = hash(ino, dev, size, stat_ctime); + he = (h + hash_size - 1) & hash_mask; + for (i = h;; i = (i + 1) & hash_mask) { + m = hash_table[i]; + if (m == (Map *) 0) + break; + if (m->hash == h && m->ino == ino && m->dev == dev && + m->size == size && m->ctime == stat_ctime) + return m; + if (i == he) + break; + } + return (Map *) 0; +} + + +static unsigned int hash(ino_t ino, dev_t dev, off_t size, + time_t stat_ctime) +{ + unsigned int h = 177573; + + h ^= ino; + h += h << 5; + h ^= dev; + h += h << 5; + h ^= size; + h += h << 5; + h ^= stat_ctime; + + return h & hash_mask; +} + + +/* + * Stolen from VI + */ + +int mmcFopen(char *filename, char **buf, int *len) +{ + int fd; + void *map; + struct stat sbuf; + + if ((fd = open(filename, O_RDONLY)) == -1) + return (-errno); + + fleFset_close_exec(fd); + + if (fstat(fd, &sbuf) == -1) { + close(fd); + return (-1); + } + if ((map = + mmap(0, sbuf.st_size, PROT_READ, MAP_PRIVATE, fd, + 0)) == MAP_FAILED) { + close(fd); + return 0; + } + close(fd); + + *buf = map; + *len = sbuf.st_size; + + return 0; +} + +/* Stolen from VI */ + +int mmcFclose(char *buf, int len) +{ + if (munmap(buf, len) == -1) + return (-1); + return (0); +} diff --git a/lc-continuity/mk4/continuity/cont/tas.c b/lc-continuity/mk4/continuity/cont/tas.c new file mode 100644 index 0000000000000000000000000000000000000000..b51ee4d4450cb2f9c27e3f5e85f834904538604e --- /dev/null +++ b/lc-continuity/mk4/continuity/cont/tas.c @@ -0,0 +1,265 @@ +/* $Header: /san01/cvs/ashpool/csrc/continuity/cont/tas.c,v 1.7 2004/05/14 06:20:32 eric Exp $ */ + +/* Copyright (c) 1994, 2004 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH + * The copyright notice above does not evidence any + * actual or intended publication of such source code. + * + * Disclosure, copying, distribution, or transmission of + * this code without express permission is prohibited. + */ + +/* + * Runtime Statistics Alex Leigh, 1995, 2000 $Id: stat.c,v 1.1 2000/04/08 + * 17:35:55 aleigh Exp $ + */ + +#include "csys.h" + +#define TA_STAT_STRLEN 32 + +#define TA_STAT_INT 1 +#define TA_STAT_UINT 2 +#define TA_STAT_CHAR 3 + +struct tasSstat { + unsigned int tas_ctime; + struct tasSstat *tas_next; + + char tas_module[TA_STAT_STRLEN]; + int tas_instance; + char tas_name[TA_STAT_STRLEN]; + int tas_type; + char tas_class[TA_STAT_STRLEN]; + unsigned char tas_flags; + void *tas_data; + size_t tas_data_size; + unsigned int tas_ndata; +}; + +struct tasSctl { + struct tasSstat *chain; +}; + +#include "continuity.h" +#include "mecha.h" + +tasTctl *tasGctl; +pthread_mutex_t tasMctl = PTHREAD_MUTEX_INITIALIZER; + +int tasFinit(void) +{ + tasGctl = (tasTctl *) malloc(sizeof(tasTctl)); + bzero(tasGctl, sizeof(tasTctl)); + return 0; +} + +tasTstat *tasFget_chain(void) +{ + return tasGctl->chain; +} + +tasTstat *tasFcreate(const char *module, int instance, const char *name, + const char *class, unsigned char type, + unsigned long ndata, unsigned char flag) +{ + tasTstat *tas; + int size; + + tas = (tasTstat *) malloc(sizeof(tasTstat)); + bzero(tas, sizeof(tasTstat)); + + strncpy(tas->tas_name, name, TA_STAT_STRLEN); + strncpy(tas->tas_module, module, TA_STAT_STRLEN); + strncpy(tas->tas_class, class, TA_STAT_STRLEN); + + tas->tas_instance = instance; + tas->tas_type = type; + tas->tas_flags = flag; + tas->tas_ndata = ndata; + + switch (type) { + case TA_STAT_INT: + size = ndata * sizeof(int32_t); + tas->tas_data = (int32_t *) malloc(size); + bzero(tas->tas_data, size); + break; + + case TA_STAT_UINT: + size = ndata * sizeof(uint32_t); + tas->tas_data = (uint32_t *) malloc(size); + bzero(tas->tas_data, size); + break; + + case TA_STAT_CHAR: + tas->tas_data = (char *) malloc(ndata); + bzero(tas->tas_data, ndata); + break; + } + + if (tas->tas_data == NULL) { + free(tas); + return NULL; + } + return tas; + +} + + +tasTstat *tasFstat_lookup(tasTctl * ctl, const char *module, + int instance, const char *name) +{ + tasTstat *p; + int match = 1; + + if (ctl->chain == NULL) + return NULL; + + p = ctl->chain; + + while (1) { + match = 1; + + if (module != NULL) + if (strcmp(p->tas_module, module) != 0) + match = 0; + + if (instance != -1) + if (p->tas_instance != instance) + match = 0; + + if (strcmp(p->tas_name, name) != 0) + match = 0; + + if (match == 1) + return p; + + if (p->tas_next == NULL) + break; + p = p->tas_next; + } + return NULL; +} + +tasTstat *tasFlookup(char *module, int instance, char *name) +{ + return tasFstat_lookup(tasGctl, module, instance, name); +} + + +void tasFstat_free(tasTstat * statp) +{ + + if (statp->tas_data != NULL) + free(statp->tas_data); + free(statp); + + return; +} + +void tasFstat_install(tasTstat * statp) +{ + pthread_mutex_lock(&tasMctl); + statp->tas_next = tasGctl->chain; + tasGctl->chain = statp; + pthread_mutex_unlock(&tasMctl); +} + +void tasFstat_delete(tasTstat * statp) +{ + tasTstat *p; + + pthread_mutex_lock(&tasMctl); + + if (tasGctl->chain == NULL) { + pthread_mutex_unlock(&tasMctl); + tasFstat_free(statp); + return; + } + if (tasGctl->chain == statp) { + tasGctl->chain = statp->tas_next; + pthread_mutex_unlock(&tasMctl); + tasFstat_free(statp); + return; + } + p = tasGctl->chain; + while (1) { + if (p->tas_next == statp) { + p->tas_next = statp->tas_next; + pthread_mutex_unlock(&tasMctl); + tasFstat_free(statp); + return; + } + if (p->tas_next == NULL) + break; + p = p->tas_next; + } + + pthread_mutex_unlock(&tasMctl); + tasFstat_free(statp); + return; +} + +int tasFstat_counter_add(const char *module, int instance, + const char *name, unsigned int value) +{ + tasTstat *p; + unsigned int *ip; + + p = tasFstat_lookup(tasGctl, module, instance, name); + if (p == NULL) { + p = tasFcreate(module, instance, name, "cnt", TA_STAT_UINT, 1, + (unsigned char) NULL); + ip = p->tas_data; + *ip = value; + tasFstat_install(p); + return value; + } + ip = (unsigned int *) p->tas_data; + *ip += value; + + return *ip; +} + +int tasFstat_counter_sub(const char *module, int instance, const char *name, + unsigned int value) +{ + tasTstat *p; + unsigned int *ip; + + p = tasFstat_lookup(tasGctl, module, instance, name); + if (p == NULL) { + p = tasFcreate(module, instance, name, "cnt", TA_STAT_UINT, 1, + (unsigned char) NULL); + ip = p->tas_data; + *ip = value; + tasFstat_install(p); + return value; + } + ip = (unsigned int *) p->tas_data; + *ip -= value; + + return *ip; +} + +int tasFstat_set(const char *module, int instance, const char *name, + unsigned int value) +{ + tasTstat *p; + unsigned int *ip; + + p = tasFstat_lookup(tasGctl, module, instance, name); + if (p == NULL) { + p = tasFcreate(module, instance, name, "cnt", TA_STAT_UINT, 1, + (unsigned char) NULL); + ip = p->tas_data; + *ip = value; + tasFstat_install(p); + return value; + } + ip = (unsigned int *) p->tas_data; + *ip = value; + + return *ip; +} diff --git a/lc-continuity/mk4/continuity/cont/xfr.c b/lc-continuity/mk4/continuity/cont/xfr.c new file mode 100644 index 0000000000000000000000000000000000000000..49f29648c228498cd911afa35950f03c0fa741b5 --- /dev/null +++ b/lc-continuity/mk4/continuity/cont/xfr.c @@ -0,0 +1,134 @@ +/* + * $Header: /datum01/src/continuity/src/xfer.c,v 1.19.2.3 2002/09/16 15:15:31 + * aleigh Exp $ + */ + +/* + * Copyright (c) 1994, 2004 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Disclosure, copying, distribution, or transmission of this code without + * express permission is prohibited. + */ + +#include "continuity.h" +#include "mecha.h" + +#define CHUNK_SZ 10240 + +int xfrFfile(netTconn * conn, const char *path) +{ + struct stat s; + int ret; + + ret = stat(path, &s); + + if (ret == -1) + return -1; + + ret = xfrFmmap(conn, path, &s); + return ret; + +} + +int xfrFis_extant(char *path) +{ + int ret; + + struct stat s; + + ret = stat(path, &s); + + if (ret == 0) + return 1; + + return 0; +} + +/* + * -> mmap contains the mapping -> len the length + */ +int xfrFmmap(netTconn * conn, const char *fname, + struct stat *sb + ) +{ + char *map; +#ifdef DARWIN + size_t written = 0, ret; + size_t towrite = sb->st_size; +#else + off_t written = 0, ret; +#endif + + map = (char *) mmcFmap(fname, (struct stat *) sb, NULL); + + if (map == NULL) + return STATUS_ERROR; + + while (1) { +#ifdef DARWIN + if ((towrite - written) > CHUNK_SZ) { +#else + if ((sb->st_size - written) > CHUNK_SZ) { +#endif + ret = netFconn_write(conn, map + written, CHUNK_SZ); + } else { +#ifdef DARWIN + ret = netFconn_write(conn, map + written, (towrite - written)); +#else + ret = + netFconn_write(conn, map + written, + (sb->st_size - written)); +#endif + } + + if (ret == -1) { + return STATUS_ERROR; + } else { + written += ret; +#ifdef DARWIN + if (written >= towrite) +#else + if (written >= sb->st_size) +#endif + break; + } + } + return written; +} + +int xfrFmemory(netTconn * conn, char *p, size_t len) +{ + size_t written = 0; + char *wp; + ssize_t ret; + + wp = p; + + while (1) { + if (len - written < CHUNK_SZ) { + ret = netFconn_write(conn, wp, len - written); + + if (ret == -1) { + return written; + } + written += ret; + wp += ret; + } else { + ret = netFconn_write(conn, wp, CHUNK_SZ); + + if (ret == -1) { + return written; + } + written += ret; + wp += ret; + } + if (written == len) + break; + } + + return written; +} diff --git a/lc-continuity/mk4/continuity/include/.cvsignore b/lc-continuity/mk4/continuity/include/.cvsignore new file mode 100644 index 0000000000000000000000000000000000000000..424c745c1253f9495e9b01b6bbe5e946e0f5bce6 --- /dev/null +++ b/lc-continuity/mk4/continuity/include/.cvsignore @@ -0,0 +1 @@ +*.h diff --git a/lc-continuity/mk4/continuity/include/CVS/Entries b/lc-continuity/mk4/continuity/include/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..73ea853576b3035d2b0930a02bf20084802de080 --- /dev/null +++ b/lc-continuity/mk4/continuity/include/CVS/Entries @@ -0,0 +1,8 @@ +/.cvsignore/1.1/Thu Mar 11 01:11:48 2004//Tmk4_mod6_rc2 +/config.h.in/1.10/Thu Jun 3 14:40:29 2004//Tmk4_mod6_rc2 +/continuity.h/1.75/Wed Jun 30 15:02:17 2004//Tmk4_mod6_rc2 +/csys.h/1.23/Thu May 20 20:09:46 2004//Tmk4_mod6_rc2 +/cwin32.h/1.3/Thu Dec 11 17:23:06 2003//Tmk4_mod6_rc2 +/mecha.h/1.134/Fri May 14 18:33:19 2004//Tmk4_mod6_rc2 +/mecha_dep.h/1.6/Tue Mar 16 02:30:46 2004//Tmk4_mod6_rc2 +D diff --git a/lc-continuity/mk4/continuity/include/CVS/Repository b/lc-continuity/mk4/continuity/include/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..e5bd4c080a794e6a25f201b47d48d24bb770ccb9 --- /dev/null +++ b/lc-continuity/mk4/continuity/include/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/continuity/include diff --git a/lc-continuity/mk4/continuity/include/CVS/Root b/lc-continuity/mk4/continuity/include/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/continuity/include/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/continuity/include/CVS/Tag b/lc-continuity/mk4/continuity/include/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/continuity/include/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/continuity/include/config.h.in b/lc-continuity/mk4/continuity/include/config.h.in new file mode 100644 index 0000000000000000000000000000000000000000..677c64d416eeb94d7ffb4ae148d032628a51ce73 --- /dev/null +++ b/lc-continuity/mk4/continuity/include/config.h.in @@ -0,0 +1,151 @@ +/* include/config.h.in. Generated from configure.in by autoheader. */ + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_DIRENT_H + +/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ +#undef HAVE_DOPRNT + +/* Define to 1 if you have the `getloadavg' function. */ +#undef HAVE_GETLOADAVG + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_KSTAT_H + +/* Define to 1 if you have the `aio' library (-laio). */ +#undef HAVE_LIBAIO + +/* Define to 1 if you have the `c' library (-lc). */ +#undef HAVE_LIBC + +/* Define to 1 if you have the `c_r' library (-lc_r). */ +#undef HAVE_LIBC_R + +/* Define to 1 if you have the `dl' library (-ldl). */ +#undef HAVE_LIBDL + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIBGEN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIBINTL_H + +/* Define to 1 if you have the `kstat' library (-lkstat). */ +#undef HAVE_LIBKSTAT + +/* Define to 1 if you have the `LiS' library (-lLiS). */ +#undef HAVE_LIBLIS + +/* Define to 1 if you have the `m' library (-lm). */ +#undef HAVE_LIBM + +/* Define to 1 if you have the `mtmalloc' library (-lmtmalloc). */ +#undef HAVE_LIBMTMALLOC + +/* Define to 1 if you have the `nsl' library (-lnsl). */ +#undef HAVE_LIBNSL + +/* Define to 1 if you have the `pthread' library (-lpthread). */ +#undef HAVE_LIBPTHREAD + +/* Define to 1 if you have the `resolv' library (-lresolv). */ +#undef HAVE_LIBRESOLV + +/* Define to 1 if you have the `socket' library (-lsocket). */ +#undef HAVE_LIBSOCKET + +/* Define to 1 if you have the `thread' library (-lthread). */ +#undef HAVE_LIBTHREAD + +/* Define to 1 if you have the header file. */ +#undef HAVE_MALLOC_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the `mmap' function. */ +#undef HAVE_MMAP + +/* Define to 1 if you have the header file, and it defines `DIR'. */ +#undef HAVE_NDIR_H + +/* Define to 1 if you have the `on_exit' function. */ +#undef HAVE_ON_EXIT + +/* Define to 1 if you have the `prctl' function. */ +#undef HAVE_PRCTL + +/* Define to 1 if you have the `pthread_rwlock_init' function. */ +#undef HAVE_PTHREAD_RWLOCK_INIT + +/* Define to 1 if you have the `rand_r' function. */ +#undef HAVE_RAND_R + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STROPTS_H + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_SYS_DIR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_DLPI_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_LOCK_H + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_SYS_NDIR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the `vprintf' function. */ +#undef HAVE_VPRINTF + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define as the return type of signal handlers (`int' or `void'). */ +#undef RETSIGTYPE + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define the real type of socklen_t */ +#undef socklen_t diff --git a/lc-continuity/mk4/continuity/include/continuity.h b/lc-continuity/mk4/continuity/include/continuity.h new file mode 100644 index 0000000000000000000000000000000000000000..e4b4bf45871bf720e9fcf611a05ed82bbf45cc4d --- /dev/null +++ b/lc-continuity/mk4/continuity/include/continuity.h @@ -0,0 +1,140 @@ +/* Copyright (c) 2001, 2004 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH + * The copyright notice above does not evidence any + * actual or intended publication of such source code. + * + * Use, disclosure, copying, distribution, or transmission of + * this code without express permission is prohibited. + */ + +#ifndef CONTINUITY_H +#define CONTINUITY_H + +/* #define CONT_PROFILE */ + +#include "csys.h" +#include "mecha.h" + +#define BUILD_REV "mk4 mod6 rc3" +#define BUILD_LEV_LEN 12 +//#define BUILD_LEV_LEN 8 + +#ifdef PRODUCTION +#define PROD_NOTICE "Production" +#else +#define PROD_NOTICE "Development" +#endif + +#ifdef ONESHOT +#define BUILDMODE "One-Shot." +#else +#define BUILDMODE "Multi-Shot." +#endif + +#ifdef TA_64BIT +#define BUILD_STRING "Continuity Enterprise Edition - " BUILD_REV " - 64bit " PROD_NOTICE ", " BUILDMODE +#else +#define BUILD_STRING "Continuity Enterprise Edition - " BUILD_REV " - 32bit " PROD_NOTICE ", " BUILDMODE +#endif + +#define TA_LOG_OK 0 +#define TA_LOG_WARN 1 +#define TA_LOG_ERR 2 +#define TA_LOG_DIAG 3 +#define TA_LOG_AUX 4 + +#define STATUS_OK 1 +#define STATUS_ERROR 2 +#define STATUS_PROCEED 3 +#define STATUS_EXIT 4 +#define STATUS_RESTART 5 + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int(*cont_handler)(void *, lstTset *); + +/* dis.c */ +typedef struct disSlistener disTlistener; + +int disFwait_for_startup(disTlistener * listener); +int disFsetup(disTlistener * listener); +int disFlisten_loop(disTlistener * listener); + +int ipv4_dispatcher(void *p, lstTset *opts); + int ipv4_openport(MECHA_UNUSED_ARGUMENT void *p, lstTset * opts); + + + /* continuity.c */ + const xmlTtag *conFget_config_basetag(void); + void conFwait_for_init (void); + const char *conFget_build (void); + void intr_handler (int sigraised); + int set_userid(void *p, lstTset *opts); + int conFsocketstash_update(int sd, int idx); + int conFsocketstash_find(int idx); + +/* tas.c */ +#define TA_STAT_STRLEN 32 +#define TA_STAT_INT 1 +#define TA_STAT_UINT 2 +#define TA_STAT_CHAR 3 +typedef struct tasSstat tasTstat; +typedef struct tasSctl tasTctl; +int tasFinit (void); +tasTstat *tasFget_chain (void); +tasTstat *tasFcreate (const char *module, int instance, const char *name, + const char *class, unsigned char type, + unsigned long ndata, unsigned char flag); +tasTstat *tasFstat_lookup (tasTctl * ctl, const char *module, + int instance, const char *name); +tasTstat *tasFlookup (char *module, int instance, char *name); +void tasFstat_free (tasTstat * statp); +void tasFstat_install (tasTstat * statp); +void tasFstat_delete (tasTstat * statp); +int tasFstat_counter_add (const char *module, int instance, const char *name, + unsigned int value); +int tasFstat_counter_sub (const char *module, int instance, const char *name, + unsigned int value); +int tasFstat_set (const char *module, int instance, const char *name, unsigned int value); + +/* xfr.c */ +int xfrFfile(netTconn *conn, const char *path); +int xfrFis_extant(char *path); +int xfrFmmap(netTconn *conn, const char *fname, + struct stat *sb +) ; +int xfrFmemory(netTconn *conn, char *p, size_t len); + +/* mmc.c */ +int mmcFclose(char *buf, int len); +int mmcFopen(char *filename, char **buf, int *len); +void* mmcFmap(const char* filename, struct stat* sbP, struct timeval* nowP ); +int mmcFinit(void); +void mmcFcleanup(void); +void mmcFcleanup_thr(void); +void mmc_unmap( void* addr, struct stat* sbP, struct timeval* nowP ); +void mmc_destroy( void ); + +/* dl.c */ +typedef struct dlSmap dlTmap; +typedef struct dlScategory dlTcategory; +typedef struct dlSentry dlTentry; + +void *dlFget_addr(const char *name); +int dlFpipeline_getid(const char *pipeline); +int dlFpipeline_exec(void *payload, int pipeline, const char *limit_name, const char *limit_value); +/* undoc */ +int dlFload_library (const char *shlib); +int dlFload_config(void); +int dlFop_show_dl_loads(netTconn *conn, int argc, char **argv); +int dlFop_show_dl_symbols(netTconn *conn, int argc, char **argv); +/* end undoc */ + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/lc-continuity/mk4/continuity/include/csys.h b/lc-continuity/mk4/continuity/include/csys.h new file mode 100644 index 0000000000000000000000000000000000000000..c1c5a6f79085b5793656352539224bb68fbd319f --- /dev/null +++ b/lc-continuity/mk4/continuity/include/csys.h @@ -0,0 +1,141 @@ +/* Copyright (c) 2001, 2004 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH + * The copyright notice above does not evidence any + * actual or intended publication of such source code. + * + * Use, disclosure, copying, distribution, or transmission of + * this code without express permission is prohibited. + */ + +#ifndef CSYS_H +#define CSYS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef WIN32 +#include "cwin32.h" +#else + +/* It is important that this comes first, because on Solaris + it's required to make 64-bit work properly. */ +#include + +#include "config.h" + +/* If we don't have pthread_rwlock_init() then we probably don't have + * pthread_rwlock() support. This is true on old OSX systems that we + * basically don't support, but also Solaris 2.6; rwlocks weren't implemented + * until Solaris 7 + */ + +#ifndef HAVE_PTHREAD_RWLOCK_INIT +#define pthread_rwlock_t pthread_mutex_t +#define PTHREAD_RWLOCK_INITIALIZER PTHREAD_MUTEX_INITIALIZER +#define pthread_rwlock_init pthread_mutex_init +#define pthread_rwlock_rdlock pthread_mutex_lock +#define pthread_rwlock_wrlock pthread_mutex_lock +#define pthread_rwlock_unlock pthread_mutex_unlock +#define pthread_rwlock_destory pthread_mutex_destroy +#endif + +#include +#include +#include + +/* Colliding namespace on OSX with Tcl */ +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_SYS_LOCK_H +#include +#endif + +#include + +#ifdef HAVE_STRING_H +#include +#endif + +#ifdef HAVE_STRINGS_H +#include +#endif + +#include +#include +#include +#include + +#ifdef HAVE_STDINT_H +#ifndef __USE_MISC +#define __USE_MISC +#endif +#include /* LINUX */ +#endif + +#ifdef LINUX +#include /* TCP_NODELAY */ +#include + +/* There is something wonky with this on my platform; + it's not included in unistd.h unless __USE_BSD or something + bizarre is defined, so I am just putting it here to get the + compiler to shut up. */ +extern int gethostname (char *__name, size_t __len); + +#endif + +#ifdef FREEBSD +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef SOLARIS +#include // Required on 2.6 for MAXDNAME +#include +#include +#include +#endif + +#ifdef DARWIN +#include +#endif + +#if defined(SOLARIS) +#define _Bool char +#define bool _Bool +#define true 1 +#define false 0 +#define __bool_true_false_are_defined 1 +#endif + +#if defined(LINUX) || defined(DARWIN) +#include +#endif + + +#endif /* WIN32 */ + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/lc-continuity/mk4/continuity/include/cwin32.h b/lc-continuity/mk4/continuity/include/cwin32.h new file mode 100644 index 0000000000000000000000000000000000000000..b1dd7c279a5c38c36582d3e6942ca2971f5e647f --- /dev/null +++ b/lc-continuity/mk4/continuity/include/cwin32.h @@ -0,0 +1,41 @@ +/* Copyright (c) 1994,2003 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH + * The copyright notice above does not evidence any + * actual or intended publication of such source code. + * + * Use, disclosure, copying, distribution, or transmission of + * this code without express permission is prohibited. + */ + +#ifndef CWIN_H +#define CWIN_H + +#include +#include +#include +#include +#include +#include + +typedef unsigned int uint32_t; +typedef int int32_t; +typedef unsigned int time_t; +typedef unsigned short uint16_t; +typedef short int16_t; +typedef int ssize_t; +typedef unsigned char uint8_t; +typedef char int8_t; + +#define assert +#define vsnprintf _vsnprintf +#define snprintf _snprintf + +struct timezone { + int tz_minuteswest; + int tz_dsttime; +}; + +int gettimeofday(struct timeval * time_Info, struct timezone * timezone_Info); + +#endif diff --git a/lc-continuity/mk4/continuity/include/mecha.h b/lc-continuity/mk4/continuity/include/mecha.h new file mode 100644 index 0000000000000000000000000000000000000000..5f5e8d8a09d6f1a21fada0bb0c47a8d3dd15f083 --- /dev/null +++ b/lc-continuity/mk4/continuity/include/mecha.h @@ -0,0 +1,586 @@ +/* $Id: mecha.h,v 1.134 2004/05/14 18:33:19 aleigh Exp $ */ + +/* Copyright (c) 2001, 2004 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH + * The copyright notice above does not evidence any + * actual or intended publication of such source code. + * + * Use, disclosure, copying, distribution, or transmission of + * this code without express permission is prohibited. + */ + +#ifndef MECHA_H +#define MECHA_H + +#include "csys.h" +#include "mecha_dep.h" /* Deprecated Interfaces */ + +#ifdef __GNUC__ +#define MECHA_UNUSED_ARGUMENT __attribute__((unused)) +#else +#define MECHA_UNUSED_ARGUMENT +#endif + +#ifdef __GNUC__ +#define MECHA_UNUSED __attribute__((unused)) +#else +#define MECHA_UNUSED +#endif + +#if !defined(TRUE) +#define TRUE 1 +#endif + +#if !defined(FALSE) +#define FALSE 0 +#endif + +typedef unsigned char BOOL; + +typedef void(*mecha_handler)(void *); + +void mecha_init(void); + +/* ast.c - Astronomical Functions */ +struct astSsunriset +{ + double length; /* 0-degree length of the day in hours */ + double rise; /* 0-degree rise time UT */ + double set; /* 0-degree set time UT */ + double zenith; /* Zenith time UT*/ + double status; /* Sun status */ + double civil_length; /* 6-degree length of day in hours*/ + double civil_start; /* 6-degree rise time UT */ + double civil_end; /* 6-degree set time UT */ + double civil_status; /* 6-degree sun status */ + double nautical_length; /* 12-degree length of day in hours */ + double nautical_start; /* 12-degree rise time UT */ + double nautical_end; /* 12-degree set time UT */ + double nautical_status; /* 12-degree sun status */ + double astro_length; /* 18-degree length of day in hours */ + double astro_start; /* 18-degree rise time UT */ + double astro_end; /* 18-degree set time UT */ + double astro_status; /* 18-degree sun status */ +}; +typedef struct astSsunriset astTsunriset; +void astFsunriset (astTsunriset * srs, int month, int day, int year, double lon, double lat); + +/* b64.c - Base64 Coder */ +int b64Fencode (unsigned char *bufin, unsigned int nbytes, char *bufcoded); +int b64Fdecode (const char *bufcoded, unsigned char *bufplain, int outbufsize); + +/* bsp.c - BSP Tree */ +typedef struct bspSnode bspTnode; + +int bspFadd (bspTnode * list, void *p, int high_key, int low_key); +void *bspFsearch (bspTnode * node, unsigned int x); +void bspFdestroy (bspTnode * node, void (*destructor) (void *)); +bspTnode *bspFinit (void); +void bspFbalance (bspTnode * node, unsigned int depth); + +/* undoc */ +unsigned int bspFcount (bspTnode * node); +void bspFsplit (bspTnode * node); +/* end undoc */ + +/* bus.c - Data bus */ +typedef struct busSbus busTbus; +busTbus *busFinit (void (*destructor) (void *)); +void busFfree (busTbus * bus); +int busFpush (busTbus * bus, void *data, size_t data_len); +int busFpull (busTbus * bus, void **data); + +/* crc.c - Cyclical Redundancy Check */ +uint32_t crcFcrc32 (const unsigned char *buf, unsigned len); + +/* dyn.c - Dynamic String BUffers */ +typedef struct dynSstring dynTstring; +dynTstring *dynFinit (void); +void dynFfree (dynTstring * ds); +size_t dynFappend (dynTstring * ds, const char *str, size_t len); +size_t dynFappend_string (dynTstring * ds, const dynTstring * src); +size_t dynFsappend (dynTstring * ds, const char *str); +size_t dynFappend_print (dynTstring * ds, const char *fmt, ...); +const char *dynFgetstr (const dynTstring * ds); +size_t dynFgetlen(const dynTstring *ds); +void dynFreset(dynTstring *ds); + +/* fle.c - File Operations */ +char *fleFload_file(const char *filename, size_t *len); +size_t fleFget_size(const char *filename); +int fleFset_close_exec (int fd); +void fleFpath_clean (char *pathname); +int fleFlock (const char *filename); +int fleFunlock (const char *filename); +int fleFsync_mem_to_file (char *filename, const char *memory, size_t len); +int fleFpath_simplify (const char *path, char *outpath, int len); +int fleFpath_combine (const char *path, int path_len, const char *relative, char *output, int output_len); +void fleFrotate(int count, const char *fn); +int fleFexist(const char *filename); + + + +/* hsh.c - Hashing & Hash Lists */ +typedef struct hshSiterator hshTiterator; +typedef struct hshSvoid_list hshTvoid_list; + +void hshFvoid_int_update(hshTvoid_list * list, const int key, void *data); +void hshFvoid_update(hshTvoid_list * list, const char *name, void *data); + +unsigned short int hshFraw_hash (const char *str, size_t len, + unsigned int buckets); +unsigned short int hshFraw_hashcode (const char *str, size_t len); +unsigned short int hshFhash (const char *str); +hshTvoid_list *hshFvoid_init (void (*destructor) (void *)); +hshTvoid_list *hshFvoid_int_init (void (*destructor) (void *)); +hshTvoid_list *hshFvoid_raw_init (void (*destructor) (void *), + void (*name_destructor) (void *), + int (name_comparator) (const void *s1, + const void *s2, + size_t len), + unsigned int buckets); +void hshFvoid_int_replace (hshTvoid_list * list, int key, void *data); +int hshFvoid_int_add (hshTvoid_list * list, int key, void *data); +void hshFvoid_replace (hshTvoid_list * list, const char *name, void *data); +int hshFvoid_add (hshTvoid_list * list, const char *name, void *data); +int hshFvoid_raw_add (hshTvoid_list * list, char *name, size_t name_len, + void *data, int replace); +void *hshFvoid_raw_find (hshTvoid_list * list, const char *name, + size_t name_len); +void *hshFvoid_find (hshTvoid_list * list, const char *name); +void *hshFvoid_int_find (hshTvoid_list * list, int key); + +int hshFvoid_contains (hshTvoid_list *list, const char *key); +int hshFvoid_int_contains (hshTvoid_list *list, int key); + +void hshFvoid_del (hshTvoid_list * list, const char *name); +void hshFvoid_int_del (hshTvoid_list * list, int key); +void hshFvoid_raw_del (hshTvoid_list * list, const char *name, + size_t name_len); +void *hshFvoid_remove (hshTvoid_list * list, const char *name); +void *hshFvoid_int_remove (hshTvoid_list * list, int key); +void * hshFvoid_raw_remove (hshTvoid_list * list, const char *name, size_t name_len); +void hshFvoid_destroy (hshTvoid_list *list); +void hshFvoid_free(hshTvoid_list *list); +hshTiterator *hshFiterator_init (hshTvoid_list * list); +int hshFiterator_next (hshTiterator * iterator); +void *hshFiterator_current_key (hshTiterator * iterator); +void *hshFiterator_current_value (hshTiterator * iterator); +void hshFiterator_free (hshTiterator * iterator); +void hshFiterator_reset (hshTiterator * iterator); +int hshFvoid_size (hshTvoid_list *list); +uint32_t hshFraw_hash32(const void *buf, size_t len, uint32_t buckets); +uint32_t hshFhash32(const char *str); +uint32_t hshFraw_hashcode32(const void *buf, size_t len); +void hshFvalue_destructor_set(hshTvoid_list *list, void (*destructor)(void *)); +/* nodoc */ +dynTstring *hshFdiag_output (hshTvoid_list *list); +/* end nodoc */ + +/* log.c - Message Logging */ +#define CONT_LOG_OK 0 +#define CONT_LOG_WARN 1 +#define CONT_LOG_ERROR 2 +#define CONT_LOG_DEBUG 3 + +#define logFmsg(...) logF_msg(__func__,__VA_ARGS__) + +void logF_msg (const char *func, int level, const char *m, ...); +void logFmsgid (int level, const char *module, int msg_id, ...); +void logFoutputfh_set(FILE *fh, int close_flag); +FILE *logFoutputfh_get(void); +int logFset_outputfile(const char *filename); +void logFset_rotatesize(size_t size); +void logFinit(void); + +/* lst.c - Linear Lists */ +typedef struct lstSset lstTset; +typedef struct lstSfield lstTfield; +lstTset *lstFset_init(void); +void lstFset_update (lstTset * set, const char *key, const char *value); +void lstFset_bupdate (lstTset * set, const char *key, size_t key_len, const char *value, size_t value_len); +/* undoc */ +lstTset *lstFset_create (const char *name); +size_t lstFset_get_vsize_cmp (lstTset * set, const char *key, + int (*cmp) (const char *s1, const char *s2)); +size_t lstFset_get_nsize_cmp (lstTset * set, const char *key, + int (*cmp) (const char *s1, const char *s2)); +/* end undoc */ +void lstFset_free (lstTset * set); +int lstFset_add (lstTset * set, const char *key, const char *value); +int lstFset_badd (lstTset * set, const char *key, size_t key_len, const char *value, size_t value_len); +int lstFset_nadd (lstTset * set, const char *key, int value); +/* return based on physical location */ +const char *lstFset_get_index (lstTset * set, int idx); +int lstFset_unique (lstTset * set, const char *key); +int lstFset_inique (lstTset * set, const char *key); +int lstFset_find (lstTset * set, const char *key); +int lstFset_ifind (lstTset * set, const char *key); +const char *lstFset_get (const lstTset * set, const char *key); +ssize_t lstFset_get_vsize (lstTset * set, const char *key); +ssize_t lstFset_get_nsize (lstTset * set, const char *key); +const char *lstFset_iget (lstTset * set, const char *key); +void lstFset_trunc (lstTset * set, int size); +void lstFset_delete (lstTset * set, int idx); +void lstFset_add_value (lstTset * set, int idx, const char *value); +void lstFset_delete_key (lstTset * set, const char *key); +void lstFset_idelete_key (lstTset * set, const char *key); +int lstFset_size (const lstTset * set); +void lstFset_merge (lstTset * high, const lstTset * low); +int lstFnth_find (const lstTset * list, int nth); +char *lstFset_pack (const lstTset * set, size_t * len); + +lstTset *lstFset_unpack (const char *pack); + +const char *lstFfield_value (const lstTfield *field); +int lstFfield_value_len (const lstTfield *field); + +const lstTfield *lstFset_get_field (lstTset *set, const char *key, int key_len); + +/* begin undoc */ +void lstFset_dump (char *pack); +int lstFpack (char *dest, char *src, int len, int class); +const char *lstFset_get_key_index (lstTset * set, int idx); +void lstFset_list_free (lstTset * sets); +lstTset *lstFset_list_find (lstTset ** sets, const char *name); +int lstFset_unique_cmp (lstTset * set, const char *key, + int (*cmp) (const char *s1, const char *s2)); +int lstFset_find_cmp (const lstTset * set, const char *key, + int (*cmp) (const char *s1, const char *s2)); +const char *lstFset_get_cmp (const lstTset * set, const char *key, + int (*cmp) (const char *s1, const char *s2)); +/* end undoc */ + +/* lst_void.c - Void Linear List */ +/* begin undoc */ +/* DEPRECATED INTERFACE DO NOT USE */ +typedef struct lstSlist lstTlist; +typedef struct lstSlist_elem lstTlist_elem; +void lstFlist_init(lstTlist * list, void (*destroy) (void *)); +void lstFlist_destroy(lstTlist * list); +lstTlist * lstFlist_create (void (*destroy) (void *)); +void lstFlist_free (lstTlist *list); +int lstFlist_add_next(lstTlist * list, lstTlist_elem * elem, void *data); +int lstFlist_add_prev(lstTlist * list, lstTlist_elem * elem, void *data); +int lstFlist_remove(lstTlist * list, lstTlist_elem * elem, void **data); +lstTlist_elem * lstFlist_next (lstTlist_elem *elem); +lstTlist_elem * lstFlist_prev (lstTlist_elem *elem); +void * lstFlist_data (lstTlist_elem *elem); +int lstFlist_is_head (lstTlist *list, lstTlist_elem *elem); +int lstFlist_is_head (lstTlist *list, lstTlist_elem *elem); +lstTlist_elem * lstFlist_head (lstTlist *list); +lstTlist_elem * lstFlist_tail (lstTlist *list); +int lstFlist_size (lstTlist *list); +int lstFlist_is_tail (lstTlist *list, lstTlist_elem *elem) ; +/* end undoc */ + +/* mem.c - Memory Operations */ +#ifndef WIN32 +#define memFclear bzero +#define memFcopy bcopy +#else +#define memFclear(a,b) memset(a,0,b) +#define memFcopy memcpy +#endif +#define memFfree free +#define memFalloc malloc +#define memFrealloc realloc +void *memFdup(const void *p, size_t len); + +/* rnd.c - Random Number Generator */ +void rndFinit (void); +void rndFrandom_bytes (unsigned char *buf, int len); +unsigned int rndFnumber (void); + +/* str.c - String Functions */ +lstTset *strFattrib_parser(const char *str); +void strFstrip_crlf (char *s, const size_t len); +void strFtoupper (char *s); +void strFtolower (char *s); +char *strFdup_size (const char *s, size_t * len); +char *strFcopy_size (const char *s, size_t * len); +char *strFcopy (const char *s); +void strFrealloc (char **strP, int *maxsizeP, int size); +const char *strFcasestr (const char *haystack, const char *needle); +int strFis_whitespace(char c); +int strFis_blank(char *s); +dynTstring *strFcollapse_whitespace (char *str); +unsigned int strFsplit (char *str, char **list, unsigned int list_size,const char delim, const char quotechar); +char *strFncopy(const char *s, size_t len); +const char *strFskip_whitespace(const char *p); +const char *strFskip_token(const char *p); + +/* tls.c - Thread Local Storage */ +int tlsFregister (void *(*clean_fn) (void *)); +char *tlsFadd_makeid (void *data, int class); +void *tlsFget (char *name, int class); +void tlsFdel (char *name, int class); +void tlsFclean (void); +/* undoc */ +void tlsFdestroy (void *p); +void tlsFinit (void); +void tlsFadd (void *data, char *name, int class); +/* end undoc */ + +/* utl.c - Utility Functions */ +typedef struct utlSswatch utlTswatch; +int utlFfd_printf (int fd, const char *fmt, ...); +unsigned int utlFtime (void); +volatile const struct tm *utlFlocaltime (void); +volatile const char *utlFcommonlog_time (void); +volatile const char *utlFlocal_time (void); +utlTswatch *utlFstart_swatch (void); +unsigned int utlFstop_swatch (utlTswatch * sw); +int utlFtv_sub (struct timeval *r, const struct timeval *x, const struct timeval *y); +int utlFip_to_str (unsigned int ip, char *buf, size_t buflen); +unsigned int utlFstr_to_ip (const char *ip); +int utlFisnum (const char c); +int utlFstr_has_alphas (const char *p); +void utlFtv_add (struct timeval *res, struct timeval *t1, struct timeval *t2); +long utlFtv_to_ms (struct timeval *tv); +int utlFurl_encode (dynTstring * dyn, const char *string); +int utlFurl_decode (dynTstring * dyn, const char *string); +int utlFhexdigit (char c); +uint32_t utlFgethostid (void); +size_t utlFhttp_time_print (time_t when, char *buf, size_t buflen); +time_t utlFhttp_time_parse (char *str); +int utlFgetuid (const char *username); +int utlFgetgid (const char *username); +int utlFget_pwname(const char *username, struct passwd *pw); +int utlFget_homedir(const char *username,char *dir,size_t dir_len); +void utlFhours_to_hourmin(double in_time, int *hours, int *mins); +double utlFhourmin_to_hours(int hours, int mins); +int utlFip_match(unsigned int ipa, unsigned int ipb, unsigned int netmask); +const char *utlFshort_to_str(unsigned short n); +int utlFip_validate(const char *addr); +unsigned int utlFatoui(const char *s); +void utlFhexdump(void *data, size_t size); + +/* undoc */ +int utlFclock_get (uint32_t * clock_high, uint32_t * clock_low, + uint16_t * ret_clock_seq); +/* end undoc */ + +/* uid.c - Unique ID Generator */ +int uidFgenerate_str (char *id, size_t len); + +/* thr.c - Threads (Pooling, Triggers) */ +typedef struct thrStpool thrTtpool; +typedef struct thrStrigger thrTtrigger; +thrTtpool *thrFinit (int num_threads, + int max_queue_size, int blocking_mode); +int thrFadd_work (thrTtpool * tpool, void (*routine) (void *), void *arg); +int thrFdestroy (thrTtpool * tpool, int finish); +int thrFsleep (int ms); +thrTtrigger *thrFgettrigger (void); +void thrFcheck_triggers (thrTtpool * tp); +int thrFtrigger_set (unsigned int delta, int fd); +int thrFtrigger_clear (void); +void thrFmod_init (void); +void thrFstat_thr (void *tp); + +/* qry.c - HTTP query parser */ +lstTset *qryFlst_parse(const char *query); +int qryFqualify(void); + +/* cfg.c - "XML"ish configuration parser */ +typedef struct xmlSiterator xmlTiterator; +typedef struct xmlSconfig xmlTconfig; +typedef struct xmlStag xmlTtag; + +xmlTtag *xmlFbase_tag(const xmlTconfig *config); +xmlTconfig *xmlFparse(const char *str); +xmlTconfig *xmlFload_file(const char *filename); + +const xmlTtag *xmlFfind_first_tag(const xmlTtag *tag, const char *name); +const xmlTtag *xmlFfind_first_tag_children(const xmlTtag *tag, const char *name); +const xmlTtag *xmlFfind_first_child(const xmlTtag *tag, const char *name); + +xmlTiterator *xmlFiterator_init(const xmlTtag *tag); +void xmlFiterator_free(xmlTiterator *iterator); +const xmlTtag *xmlFiterator_next(xmlTiterator *iterator); +const xmlTtag *xmlFiterator_next_name(xmlTiterator *iterator, const char *name); +xmlTiterator *xmlFiterate_children(const xmlTtag *tag); +void xmlFiterator_reset(xmlTiterator *iterator); +const xmlTtag *xmlFiterator_tag(xmlTiterator *it); + +const char *xmlFtag_get_name(const xmlTtag *tag, size_t *name_len); +const char *xmlFtag_get_value(const xmlTtag *tag, size_t *value_len); +const lstTset *xmlFtag_get_attribs(const xmlTtag *tag); +const char *xmlFtag_get_attrib_value(const xmlTtag *tag, const char *name); +const xmlTtag *xmlFtag_get_children(const xmlTtag *tag); +const char *xmlFtag_get_value_str(const xmlTtag *tag); +const char *xmlFtag_get_name_str(const xmlTtag *tag); +lstTset *xmlFcreate_list(const xmlTtag *tag, const char *tagname, const char *attribname); +const char *xmlFfirst_child_value(const xmlTtag *tag, const char *name, size_t *value_len); +const char *xmlFfirst_child_value_str (const xmlTtag *tag, const char *name); + +/* net.c */ +struct netSconn { + int sd; /* OS socket descriptor*/ + uint32_t cli_ipv4_addr; /* ipv4 address of the remote endpoint*/ + int (*io_close)(struct netSconn *conn); + ssize_t (*io_writev)(struct netSconn *conn, const struct iovec *iov, int iovcnt); + ssize_t (*io_read)(struct netSconn *conn, void *buf, size_t len); + ssize_t (*io_write)(struct netSconn *conn, const void *buf, size_t len); + void (*data_free)(void *data); + void *data; +}; +typedef struct netSconn netTconn; +typedef struct netSreader netTreader; + +int netFconn_close(netTconn *conn); +ssize_t netFconn_os_read(netTconn *conn, void *buf, size_t len); +ssize_t netFconn_os_write(netTconn *conn, const void *buf, size_t len); +int netFconn_os_close(netTconn *conn); +ssize_t netFconn_os_writev(netTconn *conn, const struct iovec *iov, int iovcnt); +ssize_t netFconn_write(netTconn *conn, const char *buf, ssize_t len); +netTreader *netFreader_init(void); +void netFreader_free(netTreader * reader); +int netFset_reuse(int sd); +int netFset_nodelay(int sd); +int netFipv4_listen_tcp(int port, unsigned int ip, int maxconnect); +ssize_t netFconn_read_line(netTconn * conn, netTreader * reader, char *buf, ssize_t len); +int netFisready(int fd); +int netFtcp_connect(char *addr, unsigned int port); +ssize_t netFconn_read(netTconn * conn, netTreader * reader, char *buf, ssize_t len); +ssize_t netFconn_write_two(netTconn * conn, const char *buf1, size_t buf1_len, const char *buf2, + size_t buf2_len); +int netFudp_send(int sd, const void *msg, size_t msg_len, unsigned int port, unsigned int ip); +int netFudp_recv(int sd, char *msg, size_t msg_len, struct sockaddr_in * sa, + size_t * sa_len); +int netFudp_open(uint16_t * port, int defport, char *service); +int netFudp_bcast_connect(void); +int netFconn_writef(netTconn * conn, const char *fmt,...); +int _netFconn_writef(netTconn * conn, const char *fmt, va_list * ap); +void netFconn_free(netTconn *conn); +netTconn *netFconn_make(int sd); + +int netFipv4_mcast_create(unsigned int port, char *group); + + /* pat.c - patterns */ +typedef struct patSstack patTstack; + +patTstack *patFstack_init(void (*destructor) (void *)); +void patFstack_free(patTstack *stack); +size_t patFstack_size(patTstack *stack); +void patFstack_append(patTstack *stack, const char *regexp, void *target); +void *patFstack_search(patTstack *stack, const char *needle) ; + +/* exp.c - Expressions */ +typedef void expTregexp; +int expFmatch(const char *pattern, const char *subject); +int expFmatch_len(const char *pattern, const char *subject, size_t subject_length); + +expTregexp *expFregexp_compile(const char *pattern); +void expFregexp_free(expTregexp *re); +int expFregexp_replace (const expTregexp * regexp, const char *subject, size_t subject_length, + const char *replace, size_t replace_length, char *output, size_t output_length); + +int expFregexp_match(const expTregexp *re, const char *subject); +int expFregexp_match_len(const expTregexp *regexp, const char *subject, size_t subject_length); +int expFapply(const char *pattern, const char *subject, lstTset * output); + +/* dic.c - Dictionary */ +typedef struct dicSdictionary dicTdictionary; + +dicTdictionary *dicFinit(void (*destructor) (void *), + int (*comparator) (const void *s1, + const void *s2, + size_t len)); +void dicFfree(dicTdictionary *d); +int dicFupdate(dicTdictionary *d, int idx, void *value, size_t value_len); +void *dicFfind(dicTdictionary *d, int idx); +int docFfind_index(dicTdictionary *d, void *value, size_t value_len, int *idx); +char *dicFchar_find(dicTdictionary *d, int idx); +int dicFchar_update(dicTdictionary *d, int idx, char *str, size_t str_len); +dicTdictionary *dicFchar_init(void); +int dicFchar_find_index(dicTdictionary *d, char *value, size_t value_len, int *idx); +void dicFuserdata_destructor_set(dicTdictionary *d, void (*destructor)(void *)); +void *dicFuserdata_find(dicTdictionary *d, int idx); +void dicFuserdata_update(dicTdictionary *d, int idx, void *data); + +/* sic.c - System functions */ +int sysFfs_info(lstTset * set); +int sysFget_load(double *one_min, double *five_min, double *fifteen_min); +unsigned int sysFboot_time(void); +int sysFmem_usage(uint32_t *pages_total, uint32_t *pages_free, + uint32_t *phys_mem, uint32_t *availr_mem, + uint32_t *free_mem); +int sysFcpu_usage(uint32_t *idle_time, uint32_t *user_time, + uint32_t *kernel_time, uint32_t *wait_time); +int sysFnet_usage(uint32_t *obytes, uint32_t *ibytes, + uint32_t *opkts, uint32_t *ipkts); + +/* cv - CeeValues */ + +#define CV_EMPTY 0 +#define CV_STRING 1 +#define CV_OBJECT 2 +#define CV_FLOAT 3 +#define CV_INTEGER 4 + +typedef struct cSval cTval; +typedef struct cSarray cTarray; +typedef struct cSassoc cTassoc; + +int cFval_type_get(cTval *v); +cTval *cFval_init(void); +void cFval_empty(cTval *v) ; +void cFval_free(cTval *v); +void cFval_assign_string(cTval *v, char *str, size_t len); +void cFval_assign_object(cTval *v, void *obj, size_t size); +void cFval_assign_object_tors(cTval *v, + void (*obj_destructor)(void *, size_t), + void *(*obj_duplicator)(void *, size_t), + int (*obj_comparator)(void *, void *, size_t)); +void cFval_assign_float(cTval *v, double value); +cTval *cFval_copy(cTval *v); +void cFval_assign_string_copy(cTval *v, const char *str, size_t len); +long long cFval_get_integer(cTval *v); +double cFval_get_float(cTval *v); +const char *cFval_get_string(cTval *v, size_t *size); +ssize_t cFval_get_string_copy(cTval *v, char *buf, size_t buf_size); +void cFval_used(cTval *v); + +#define CVNEW(v) x=cFval_init() + +#define CFREE(v) cFval_free(v) + +#define CUSE(v) cFval_use(v) + +#define CVNULL(v) cFval_empty(v) + +#define CVNEWSTRN(v,s,l) \ + v=cFval_init(); \ + cFval_assign_string(v,s,l) + +#define CVNEWSTR(v,s) CVNEWSTRN(v,s) + +#define CVNEWSTRCPYN(v,s,l) \ + v=cFval_init(); \ + cFval_assign_string_copy(v,s,l) + +#define CVNEWSTRCPY(v,s) CVNEWSTRCPYN(v,s,strlen(s)) + + +#define CNEWFLOAT(v,f) \ + v=cFval_init(); \ + cFval_assign_float(v,f) + +#define CNEWOBJ(v,o) \ + v=cFval_init(); \ + cFval_assign_object(o) + +#define CNEWINT(v,i) \ + v=cFval_init(); \ + cFval_assign_integer(i) + +cTarray *cFarray_new(void); +void cFarray_push(cTarray *array, cTval *val); +cTval *cFarray_pop(cTarray *array); +void *cFarray_foreach(cTarray *array, void *(*callback)(cTval *v)); +void cFarray_free(cTarray *array); + +#endif diff --git a/lc-continuity/mk4/continuity/include/mecha_dep.h b/lc-continuity/mk4/continuity/include/mecha_dep.h new file mode 100644 index 0000000000000000000000000000000000000000..78e37f393d47e2d48aa5442815e09a445276f8ef --- /dev/null +++ b/lc-continuity/mk4/continuity/include/mecha_dep.h @@ -0,0 +1,47 @@ +/* Copyright (c) 2001, 2004 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH + * The copyright notice above does not evidence any + * actual or intended publication of such source code. + * + * Use, disclosure, copying, distribution, or transmission of + * this code without express permission is prohibited. + */ + +/* + * the interfaces in this file are deprecated and should not be used + * for new development. They are provided as a trasitional API for + * backwards compatibility with mk3. + */ + +#ifndef MECHA_DEP_H +#define MECHA_DEP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _HSH_DEP_C +#define hshTlist void +#define hshTentry void +#define hshTnode void +#endif +hshTnode *hshFlist_node_find (hshTlist * list, char *name); +hshTentry *hshFlist_find_entry (hshTlist * list, char *nname, char *ename); +hshTlist *hshFlist_create (void); +hshTentry *hshFlist_entry_insert (hshTlist * list, char *l, char *n, char *v); +hshTentry *hshFnode_find_entry (hshTnode * node, char *str); +char *hshFnode_find_value (hshTnode * node, char *str); +void hshFnode_free (hshTnode * node); +hshTnode *hshFnode_create (char *name); +void hshFnode_entry_add (hshTnode * n, hshTentry * e); +hshTnode *hshFnode_entry_alloc (void); +hshTentry *hshFnode_entry_insert (hshTnode * node, char *n, char *v); +void hshFlist_node_add (hshTlist * list, hshTnode * node); +void hshFentry_free (hshTentry * entry); +void hashFlist_dump (hshTlist * list, unsigned int len); + +#ifdef __cplusplus +}; +#endif +#endif diff --git a/lc-continuity/mk4/continuity/install-sh b/lc-continuity/mk4/continuity/install-sh new file mode 100644 index 0000000000000000000000000000000000000000..e9de23842dcd44d2953129c866b1ad25f7e1f1d9 --- /dev/null +++ b/lc-continuity/mk4/continuity/install-sh @@ -0,0 +1,251 @@ +#!/bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5 (mit/util/scripts/install.sh). +# +# Copyright 1991 by the Massachusetts Institute of Technology +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation, and that the name of M.I.T. not be used in advertising or +# publicity pertaining to distribution of the software without specific, +# written prior permission. M.I.T. makes no representations about the +# suitability of this software for any purpose. It is provided "as is" +# without express or implied warranty. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +transformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +else + true +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d $dst ]; then + instcmd=: + chmodcmd="" + else + instcmd=mkdir + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f $src -o -d $src ] + then + true + else + echo "install: $src does not exist" + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "install: no destination specified" + exit 1 + else + true + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d $dst ] + then + dst="$dst"/`basename $src` + else + true + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' +' +IFS="${IFS-${defaultIFS}}" + +oIFS="${IFS}" +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS="${oIFS}" + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp="${pathcomp}${1}" + shift + + if [ ! -d "${pathcomp}" ] ; + then + $mkdirprog "${pathcomp}" + else + true + fi + + pathcomp="${pathcomp}/" +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd $dst && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename $dst` + else + dstfile=`basename $dst $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename $dst` + else + true + fi + +# Make a temp file name in the proper directory. + + dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + + $doit $instcmd $src $dsttmp && + + trap "rm -f ${dsttmp}" 0 && + +# and set any options; do chmod last to preserve setuid bits + +# If any of these fail, we abort the whole thing. If we want to +# ignore errors from any of these, just make sure not to ignore +# errors from the above "$doit $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && + +# Now rename the file to the real destination. + + $doit $rmcmd -f $dstdir/$dstfile && + $doit $mvcmd $dsttmp $dstdir/$dstfile + +fi && + + +exit 0 diff --git a/lc-continuity/mk4/continuity/lib/.cvsignore b/lc-continuity/mk4/continuity/lib/.cvsignore new file mode 100644 index 0000000000000000000000000000000000000000..9b493d31e89da3c1600670d727ce9fa607f56c47 --- /dev/null +++ b/lc-continuity/mk4/continuity/lib/.cvsignore @@ -0,0 +1 @@ +env.mk diff --git a/lc-continuity/mk4/continuity/lib/CVS/Entries b/lc-continuity/mk4/continuity/lib/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..fb47aaf6f69514aef5afd275e2ebe6699afd61bd --- /dev/null +++ b/lc-continuity/mk4/continuity/lib/CVS/Entries @@ -0,0 +1,4 @@ +/.cvsignore/1.1/Thu Mar 11 01:11:48 2004//Tmk4_mod6_rc2 +/build.mk/1.10/Fri May 14 19:12:09 2004//Tmk4_mod6_rc2 +/env.mk.in/1.5/Fri May 14 19:12:09 2004//Tmk4_mod6_rc2 +D diff --git a/lc-continuity/mk4/continuity/lib/CVS/Repository b/lc-continuity/mk4/continuity/lib/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..bb2f3ecbc036609042c2fd55b01be4a5d3a1b28d --- /dev/null +++ b/lc-continuity/mk4/continuity/lib/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/continuity/lib diff --git a/lc-continuity/mk4/continuity/lib/CVS/Root b/lc-continuity/mk4/continuity/lib/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/continuity/lib/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/continuity/lib/CVS/Tag b/lc-continuity/mk4/continuity/lib/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/continuity/lib/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/continuity/lib/build.mk b/lc-continuity/mk4/continuity/lib/build.mk new file mode 100644 index 0000000000000000000000000000000000000000..1189ac3041c4409322bbcd6f14cdf9123ce65243 --- /dev/null +++ b/lc-continuity/mk4/continuity/lib/build.mk @@ -0,0 +1,173 @@ + +################################################################################ +## +## check to make SOURCES and TARGET is properly set +## +################################################################################ + +ifndef SOURCES +$(error SOURCES variable must be defined to be the sources you want to include in the build.) +endif + +ifndef TARGET +$(error TARGET must be defined to be the name of the module to build.) +endif + + +################################################################################ +## +## make sure CONTINUITY is properly configured +## +################################################################################ + +ifndef CONTINUITY +$(error CONTINUITY must be defined to point to the root of the continuity build.) +endif + +ifeq ($shell(test -d $(CONTINUITY)/continuity/lib && echo found),found) +CONTINUITY := $(CONTINUITY)/continuity +endif + +include $(CONTINUITY)/lib/env.mk + +################################################################################ +## +## Targets +## +################################################################################ + +ifndef TARGETTYPE +TARGETTYPE = module +endif + +ifneq (,$(findstring module,$(TARGETTYPE))) +SHARED_TARGET = mod$(TARGET).so +ALL_TARGETS += $(SHARED_TARGET) +endif + +ifneq (,$(findstring shared,$(TARGETTYPE))) +SHARED_TARGET = lib$(TARGET).so +ALL_TARGETS += $(SHARED_TARGET) +endif + +ifneq (,$(findstring static,$(TARGETTYPE))) +STATIC_TARGET = lib$(TARGET).a +ALL_TARGETS += $(STATIC_TARGET) +endif + +ifneq (,$(findstring executable,$(TARGETTYPE))) +EXECUTABLE_TARGET = $(TARGET) +ALL_TARGETS += $(EXECUTABLE_TARGET) +endif + +################################################################################ +## +## Dependancy mapping +## +################################################################################ + +DEPDIR = .deps +df = $(*D)/$(DEPDIR)/$(*F) + +DEPENDFLAGS = -MD -MP -MF $(df).d + +MAKE_DEP_DIR = [ -d "$(*D)$(DEPDIR)" ] || mkdir -p "$(*D)/$(DEPDIR)" + +DEP_FILES = $(foreach dep,$(SOURCES),$(dir $(dep))$(DEPDIR)/$(notdir $(dep:%.c=%.d))) + +################################################################################ +## +## Cleare defaults we don't want +## +################################################################################ + +.SUFFIXES: +.SUFFIXES: .o .c .h + +.a: +%.a: + + +################################################################################ +## +## setup variables +## +################################################################################ + +OBJECTS = $(SOURCES:%.c=%.o) + +CFLAGS += -I$(CONTINUITY)/include -fPIC +CFLAGS += $(INCLUDES) $(LOCAL_CFLAGS) $(OPT_CFLAGS) + +LIBS += $(LOCAL_LIBS) + +# +# i decided this isn't really needed +# -eric 3.11.2004 +# +# EXPANDED_STATIC_LIBS = $(STATIC_LIBS:%=-Wl,--whole-archive % -Wl,--no-whole-archive) + +EXPANDED_STATIC_LIBS = $(STATIC_LIBS) $(WHOLE_STATIC_LIBS:%=-Wl,--whole-archive % -Wl,--no-whole-archive) + + +MAKEFILES = $(CONTINUITY)/lib/env.mk $(CONTINUITY)/lib/build.mk Makefile + + +################################################################################ +## +## define targets +## +################################################################################ + +all: $(ALL_TARGETS) install + +$(EXECUTABLE_TARGET): $(OBJECTS) $(STATIC_LIBS) $(MAKEFILES) $(WHOLE_STATIC_LIBS) + $(CC) $(LD_FLAGS) $(OBJECTS) $(EXPANDED_STATIC_LIBS) $(LIBS) -o $@ + +$(SHARED_TARGET): $(OBJECTS) $(STATIC_LIBS) $(MAKEFILES) $(WHOLE_STATIC_LIBS) + $(LD_SHARECMD) $(LD_FLAGS) $(PRE_BUILD) $(OBJECTS) $(EXPANDED_STATIC_LIBS) $(LIBS) $(POST_BUILD) -o $@ + +$(STATIC_TARGET): $(OBJECTS) $(MAKEFILES) + $(RM) $@ + $(AR) crs $@ $(OBJECTS) + +%.o: %.c $(MAKEFILES) + @$(MAKE_DEP_DIR) + $(CC) $(DEPENDFLAGS) $(CFLAGS) -c $< -o $@ + +ifneq ($(SHARED_TARGET),) +$(CONTINUITY)/lib/$(SHARED_TARGET): $(SHARED_TARGET) + @echo "$< -> $@" + @$(RM) $@ + @cp $< $@ +endif + +ifneq ($(STATIC_TARGET),) +$(CONTINUITY)/lib/$(STATIC_TARGET): $(STATIC_TARGET) + @echo "$< -> $@" + @$(RM) $@ + @cp $< $@ +endif + +ifneq ($(EXECUTABLE_TARGET),) +$(CONTINUITY)/bin/$(EXECUTABLE_TARGET): $(EXECUTABLE_TARGET) + @echo "$< -> $@" + @$(RM) $@ + @cp $< $@ +endif + +install: $(CONTINUITY)/lib/$(SHARED_TARGET) + +#install: $(ALL_TARGETS) +# @for file in $(ALL_TARGETS); do \ +# echo "$$file -> $(CONTINUITY)/lib/$$file"; \ +# $(RM) $(CONTINUITY)/lib/$$file; \ +# cp $$file $(CONTINUITY)/lib/$$file; \ +# done + +clean: + $(RM) $(OBJECTS) $(DEP_FILES) + +#ifneq ($(MAKECMDGOALS),clean) +#-include $(DEP_FILES) +#endif diff --git a/lc-continuity/mk4/continuity/lib/env.mk.in b/lc-continuity/mk4/continuity/lib/env.mk.in new file mode 100644 index 0000000000000000000000000000000000000000..00ee1027267e622be9da874540544a568616c516 --- /dev/null +++ b/lc-continuity/mk4/continuity/lib/env.mk.in @@ -0,0 +1,25 @@ +# $Id: env.mk.in,v 1.5 2004/05/14 19:12:09 eric Exp $ + +CC=@CC@ +CFLAGS=@ARCH_CFLAGS@ @OPT_CFLAGS@ -D_REENTRANT -DTHR_POOL +CONT_FLAGS=@ARCH_CFLAGS@ @OPT_CFLAGS@ -D_REENTRANT -DTHR_POOL + +LD_SHARECMD=@LDSHARED@ +LIBS=@LIBS@ +LD_FLAGS=@LD_FLAGS@ + +MAKEDEPEND=@MAKEDEPEND@ +DEPFLAGS=@DEPFLAGS@ + +AR_CMD=@AR_CMD@ + +CCVER=WS6U1 +COMPOBJ=$(CONTINUITY_HOME)/lib/$(CCVER) +COMPOBJS32=$(COMPOBJ)/crti.o $(COMPOBJ)/crt1.o $(COMPOBJ)/crtn.o + +BUILD_CMD=@BUILD_CMD@ +PRE_BUILD=@PRE_BUILD@ +POST_BUILD=@POST_BUILD@ + +MODTCL_TCLOPT=@MODTCL_TCLOPT@ + diff --git a/lc-continuity/mk4/continuity/mecha/CVS/Entries b/lc-continuity/mk4/continuity/mecha/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..0a0a000eb82c386ba516384491e26c8b58110035 --- /dev/null +++ b/lc-continuity/mk4/continuity/mecha/CVS/Entries @@ -0,0 +1,34 @@ +/Makefile.in/1.20/Fri May 14 18:30:26 2004//Tmk4_mod6_rc2 +/ast.c/1.8/Fri Apr 30 13:41:56 2004//Tmk4_mod6_rc2 +/b64.c/1.9/Fri Apr 30 13:41:56 2004//Tmk4_mod6_rc2 +/bsp.c/1.18/Fri Apr 30 13:41:56 2004//Tmk4_mod6_rc2 +/bus.c/1.10/Fri Apr 30 13:41:56 2004//Tmk4_mod6_rc2 +/crc.c/1.8/Fri Apr 30 13:41:56 2004//Tmk4_mod6_rc2 +/cv.c/1.4/Fri May 14 06:20:32 2004//Tmk4_mod6_rc2 +/dic.c/1.1/Fri Apr 30 13:41:56 2004//Tmk4_mod6_rc2 +/dyn.c/1.18/Fri Apr 30 13:41:56 2004//Tmk4_mod6_rc2 +/dyn.h/1.5/Wed Mar 17 19:26:08 2004//Tmk4_mod6_rc2 +/exp.c/1.9/Fri Apr 30 13:41:56 2004//Tmk4_mod6_rc2 +/fle.c/1.18/Tue May 11 20:39:12 2004//Tmk4_mod6_rc2 +/hsh.c/1.24/Thu May 27 14:31:42 2004//Tmk4_mod6_rc2 +/hsh_dep.c/1.9/Thu Mar 18 15:04:15 2004//Tmk4_mod6_rc2 +/log.c/1.8/Fri Apr 30 13:41:56 2004//Tmk4_mod6_rc2 +/lst.c/1.31/Fri Apr 30 13:41:56 2004//Tmk4_mod6_rc2 +/lst.h/1.6/Wed Mar 17 19:26:08 2004//Tmk4_mod6_rc2 +/lst_void.c/1.12/Fri Apr 30 13:41:56 2004//Tmk4_mod6_rc2 +/mecha.c/1.2/Fri May 14 18:32:51 2004//Tmk4_mod6_rc2 +/mem.c/1.9/Fri Apr 30 13:41:56 2004//Tmk4_mod6_rc2 +/net.c/1.14/Thu May 27 13:32:22 2004//Tmk4_mod6_rc2 +/net.h/1.2/Wed Mar 17 19:26:08 2004//Tmk4_mod6_rc2 +/pat.c/1.6/Fri Apr 30 13:41:56 2004//Tmk4_mod6_rc2 +/qry.c/1.9/Fri Apr 30 13:41:56 2004//Tmk4_mod6_rc2 +/rnd.c/1.8/Fri Apr 30 13:41:56 2004//Tmk4_mod6_rc2 +/str.c/1.21/Fri Apr 30 13:41:56 2004//Tmk4_mod6_rc2 +/sys.c/1.2/Thu May 20 19:39:25 2004//Tmk4_mod6_rc2 +/thr.c/1.24/Thu May 27 13:55:00 2004//Tmk4_mod6_rc2 +/tls.c/1.9/Fri Apr 30 13:41:56 2004//Tmk4_mod6_rc2 +/uid.c/1.9/Fri Apr 30 13:41:56 2004//Tmk4_mod6_rc2 +/utl.c/1.31/Thu May 13 14:11:25 2004//Tmk4_mod6_rc2 +/w32.c/1.5/Fri Apr 30 13:41:56 2004//Tmk4_mod6_rc2 +/xml.c/1.21/Fri Apr 30 13:41:56 2004//Tmk4_mod6_rc2 +D diff --git a/lc-continuity/mk4/continuity/mecha/CVS/Repository b/lc-continuity/mk4/continuity/mecha/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..99e351e3a83805f8bdd02ad78c8aca79cbb6314e --- /dev/null +++ b/lc-continuity/mk4/continuity/mecha/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/continuity/mecha diff --git a/lc-continuity/mk4/continuity/mecha/CVS/Root b/lc-continuity/mk4/continuity/mecha/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/continuity/mecha/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/continuity/mecha/CVS/Tag b/lc-continuity/mk4/continuity/mecha/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/continuity/mecha/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/continuity/mecha/Makefile.in b/lc-continuity/mk4/continuity/mecha/Makefile.in new file mode 100644 index 0000000000000000000000000000000000000000..d2e14ea42532993039ac82bb27b559a5b5449b2c --- /dev/null +++ b/lc-continuity/mk4/continuity/mecha/Makefile.in @@ -0,0 +1,31 @@ +# $Header: /san01/cvs/ashpool/csrc/continuity/mecha/Attic/Makefile.in,v 1.20 2004/05/14 18:30:26 aleigh Exp $ + +SRCS=ast.c b64.c bsp.c bus.c crc.c dyn.c fle.c hsh.c hsh_dep.c log.c lst.c \ +rnd.c str.c thr.c tls.c uid.c utl.c lst_void.c qry.c xml.c w32.c mem.c \ +exp.c net.c pat.c dic.c sys.c cv.c mecha.c +OBJS=ast.o b64.o bsp.o bus.o crc.o dyn.o fle.o hsh.o hsh_dep.o log.o lst.o \ +rnd.o str.o thr.o tls.o uid.o utl.o lst_void.o qry.o xml.o w32.o mem.o \ +exp.o net.o pat.o dic.o sys.o cv.o mecha.o +PCRE_OBJS=../pcre/pcreposix.o ../pcre/pcre.o ../pcre/get.o + +CFLAGS=-I../include @ARCH_CFLAGS@ @OPT_CFLAGS@ -D_REENTRANT -DTHR_POOL @BUILD_CFLAGS@ +LD_SHARECMD= @LDSHARED@ +CC=@CC@ +AR_CMD=@AR_CMD@ +BUILDMODE=@BUILDMODE@ +MAKEDEPEND=@MAKEDEPEND@ + +world: $(OBJS) $(PCRE_OBJS) + $(AR_CMD) mechanism.a $(OBJS) $(PCRE_OBJS) + ranlib mechanism.a + cp mechanism.a ../lib + +clean: + rm -rf ../lib/mechanism.a $(OBJS) + +count: + wc -l `find . -name '*.[ch]'` + +depend: + $(MAKEDEPEND) @DEPFLAGS@ -I ../include $(SRCS) + diff --git a/lc-continuity/mk4/continuity/mecha/ast.c b/lc-continuity/mk4/continuity/mecha/ast.c new file mode 100644 index 0000000000000000000000000000000000000000..27d9e47aa7a23a6b075bbe37b972e73c6f250594 --- /dev/null +++ b/lc-continuity/mk4/continuity/mecha/ast.c @@ -0,0 +1,431 @@ +/* + * $Header: /san01/cvs/ashpool/csrc/continuity/mecha/Attic/ast.c,v 1.8 2004/04/30 13:41:56 aleigh Exp $ + */ + +/* + * Copyright (c) 1994, 2004 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Disclosure, copying, distribution, or transmission of of this code without + * express permission is prohibited. + */ + +/* + * Original Algorithm: Written as DAYLEN.C, 1989-08-16 Modified to + * SUNRISET.C, 1992-12-01 (c) Paul Schlyter, 1989, 1992 Released to the + * public domain by Paul Schlyter, December 1992 + */ + +#include "mecha.h" + +/* A macro to compute the number of days elapsed since 2000 Jan 0.0 */ +/* (which is equal to 1999 Dec 31, 0h UT) */ + +#define days_since_2000_Jan_0(y,m,d) \ + (367L*(y)-((7*((y)+(((m)+9)/12)))/4)+((275*(m))/9)+(d)-730530L) + +/* Some conversion factors between radians and degrees */ +#ifndef PI +#define PI 3.1415926535897932384 +#endif +#define RADEG ( 180.0 / PI ) +#define DEGRAD ( PI / 180.0 ) + +/* The trigonometric functions in degrees */ +#define sind(x) sin((x)*DEGRAD) +#define cosd(x) cos((x)*DEGRAD) +#define tand(x) tan((x)*DEGRAD) +#define atand(x) (RADEG*atan(x)) +#define asind(x) (RADEG*asin(x)) +#define acosd(x) (RADEG*acos(x)) +#define atan2d(y,x) (RADEG*atan2(y,x)) + +/* Following are some macros around the "workhorse" function __daylen__ */ +/* They mainly fill in the desired values for the reference altitude */ +/* below the horizon, and also selects whether this altitude should */ +/* refer to the Sun's center or its upper limb. */ +/* This macro computes the length of the day, from sunrise to sunset. */ +/* Sunrise/set is considered to occur when the Sun's upper limb is */ +/* 35 arc minutes below the horizon (this accounts for the refraction */ +/* of the Earth's atmosphere). */ +#define day_length(year,month,day,lon,lat) \ + __daylen__( year, month, day, lon, lat, -35.0/60.0, 1 ) + +/* This macro computes the length of the day, including civil twilight. */ +/* Civil twilight starts/ends when the Sun's center is 6 degrees below */ +/* the horizon. */ + +#define day_civil_twilight_length(year,month,day,lon,lat) \ + __daylen__( year, month, day, lon, lat, -6.0, 0 ) +/* This macro computes the length of the day, incl. nautical twilight. */ +/* Nautical twilight starts/ends when the Sun's center is 12 degrees */ +/* below the horizon. */ + +#define day_nautical_twilight_length(year,month,day,lon,lat) \ + __daylen__( year, month, day, lon, lat, -12.0, 0 ) +/* This macro computes the length of the day, incl. astronomical twilight. */ +/* Astronomical twilight starts/ends when the Sun's center is 18 degrees */ +/* below the horizon. */ + +#define day_astronomical_twilight_length(year,month,day,lon,lat) \ + __daylen__( year, month, day, lon, lat, -18.0, 0 ) +/* This macro computes times for sunrise/sunset. */ +/* Sunrise/set is considered to occur when the Sun's upper limb is */ +/* 35 arc minutes below the horizon (this accounts for the refraction */ +/* of the Earth's atmosphere). */ + +#define sun_rise_set(year,month,day,lon,lat,rise,set) \ + __sunriset__( year, month, day, lon, lat, -35.0/60.0, 1, rise, set ) +/* This macro computes the start and end times of civil twilight. */ +/* Civil twilight starts/ends when the Sun's center is 6 degrees below */ +/* the horizon. */ + +#define civil_twilight(year,month,day,lon,lat,start,end) \ + __sunriset__( year, month, day, lon, lat, -6.0, 0, start, end ) +/* This macro computes the start and end times of nautical twilight. */ +/* Nautical twilight starts/ends when the Sun's center is 12 degrees */ +/* below the horizon. */ + +#define nautical_twilight(year,month,day,lon,lat,start,end) \ + __sunriset__( year, month, day, lon, lat, -12.0, 0, start, end ) +/* This macro computes the start and end times of astronomical twilight. */ +/* Astronomical twilight starts/ends when the Sun's center is 18 degrees */ +/* below the horizon. */ + +#define astronomical_twilight(year,month,day,lon,lat,start,end) \ + __sunriset__( year, month, day, lon, lat, -18.0, 0, start, end ) +/* Function prototypes */ + +static double __daylen__(int year, int month, int day, double lon, + double lat, double altit, int upper_limb); + +static int __sunriset__(int year, int month, int day, double lon, + double lat, double altit, int upper_limb, + double *rise, double *set); + +static void sunpos(double d, double *lon, double *r); + +static void sun_RA_dec(double d, double *RA, double *dec, double *r); + +static double revolution(double x); + +static double rev180(double x); + +static double GMST0(double d); + +void astFsunriset(astTsunriset * srs, int month, int day, int year, + double lon, double lat) +{ + srs->length = day_length(year, month, day, lon, lat); + srs->civil_length = + day_civil_twilight_length(year, month, day, lon, lat); + srs->nautical_length = + day_nautical_twilight_length(year, month, day, lon, lat); + srs->astro_length = + day_astronomical_twilight_length(year, month, day, lon, lat); + + srs->status = + sun_rise_set(year, month, day, lon, lat, &srs->rise, &srs->set); + srs->civil_status = + civil_twilight(year, month, day, lon, lat, &srs->civil_start, + &srs->civil_end); + srs->nautical_status = + nautical_twilight(year, month, day, lon, lat, &srs->nautical_start, + &srs->nautical_end); + srs->astro_status = + astronomical_twilight(year, month, day, lon, lat, + &srs->astro_start, &srs->astro_end); + + srs->zenith = (srs->rise + srs->set) / 2.0; +} + + +/* The "workhorse" function for sun rise/set times */ + +static int __sunriset__(int year, int month, int day, double lon, + double lat, double altit, int upper_limb, + double *trise, double *tset) +/***************************************************************************/ +/* Note: year,month,date = calendar date, 1801-2099 only. */ +/* Eastern longitude positive, Western longitude negative */ +/* Northern latitude positive, Southern latitude negative */ +/* The longitude value IS critical in this function! */ +/* altit = the altitude which the Sun should cross */ +/* Set to -35/60 degrees for rise/set, -6 degrees */ +/* for civil, -12 degrees for nautical and -18 */ +/* degrees for astronomical twilight. */ +/* upper_limb: non-zero -> upper limb, zero -> center */ +/* Set to non-zero (e.g. 1) when computing rise/set */ +/* times, and to zero when computing start/end of */ +/* twilight. */ +/* *rise = where to store the rise time */ +/* *set = where to store the set time */ +/* Both times are relative to the specified altitude, */ +/* and thus this function can be used to compute */ +/* various twilight times, as well as rise/set times */ +/* Return value: 0 = sun rises/sets this day, times stored at */ +/* *trise and *tset. */ +/* +1 = sun above the specified "horizon" 24 hours. */ +/* *trise set to time when the sun is at south, */ +/* minus 12 hours while *tset is set to the south */ +/* time plus 12 hours. "Day" length = 24 hours */ +/* -1 = sun is below the specified "horizon" 24 hours */ +/* "Day" length = 0 hours, *trise and *tset are */ +/* both set to the time when the sun is at south. */ +/* */ +/**********************************************************************/ +{ + double d, /* Days since 2000 Jan 0.0 (negative before) */ + sr, /* Solar distance, astronomical units */ + sRA, /* Sun's Right Ascension */ + sdec, /* Sun's declination */ + sradius, /* Sun's apparent radius */ + t, /* Diurnal arc */ + tsouth, /* Time when Sun is at south */ + sidtime; /* Local sidereal time */ + + int rc = 0; /* Return cde from function - usually 0 */ + + /* Compute d of 12h local mean solar time */ + d = days_since_2000_Jan_0(year, month, day) + 0.5 - lon / 360.0; + + /* Compute local sidereal time of this moment */ + sidtime = revolution(GMST0(d) + 180.0 + lon); + + /* Compute Sun's RA + Decl at this moment */ + sun_RA_dec(d, &sRA, &sdec, &sr); + + /* Compute time when Sun is at south - in hours UT */ + tsouth = 12.0 - rev180(sidtime - sRA) / 15.0; + + /* Compute the Sun's apparent radius, degrees */ + sradius = 0.2666 / sr; + + /* Do correction to upper limb, if necessary */ + if (upper_limb) + altit -= sradius; + + /* Compute the diurnal arc that the Sun traverses to reach */ + /* the specified altitude altit: */ + { + double cost; + cost = (sind(altit) - sind(lat) * sind(sdec)) / + (cosd(lat) * cosd(sdec)); + if (cost >= 1.0) + rc = -1, t = 0.0; /* Sun always below altit */ + else if (cost <= -1.0) + rc = +1, t = 12.0; /* Sun always above altit */ + else + t = acosd(cost) / 15.0; /* The diurnal arc, hours */ + } + + /* Store rise and set times - in hours UT */ + *trise = tsouth - t; + *tset = tsouth + t; + + return rc; +} /* __sunriset__ */ + + + +/* The "workhorse" function */ + + +static double __daylen__(int year, int month, int day, double lon, + double lat, double altit, int upper_limb) +/**********************************************************************/ +/* Note: year,month,date = calendar date, 1801-2099 only. */ +/* Eastern longitude positive, Western longitude negative */ +/* Northern latitude positive, Southern latitude negative */ +/* The longitude value is not critical. Set it to the correct */ +/* longitude if you're picky, otherwise set to to, say, 0.0 */ +/* The latitude however IS critical - be sure to get it correct */ +/* altit = the altitude which the Sun should cross */ +/* Set to -35/60 degrees for rise/set, -6 degrees */ +/* for civil, -12 degrees for nautical and -18 */ +/* degrees for astronomical twilight. */ +/* upper_limb: non-zero -> upper limb, zero -> center */ +/* Set to non-zero (e.g. 1) when computing day length */ +/* and to zero when computing day+twilight length. */ +/**********************************************************************/ +{ + double d, /* Days since 2000 Jan 0.0 (negative before) */ + obl_ecl, /* Obliquity (inclination) of Earth's axis */ + sr, /* Solar distance, astronomical units */ + slon, /* True solar longitude */ + sin_sdecl, /* Sine of Sun's declination */ + cos_sdecl, /* Cosine of Sun's declination */ + sradius, /* Sun's apparent radius */ + t; /* Diurnal arc */ + + /* Compute d of 12h local mean solar time */ + d = days_since_2000_Jan_0(year, month, day) + 0.5 - lon / 360.0; + + /* Compute obliquity of ecliptic (inclination of Earth's axis) */ + obl_ecl = 23.4393 - 3.563E-7 * d; + + /* Compute Sun's position */ + sunpos(d, &slon, &sr); + + /* Compute sine and cosine of Sun's declination */ + sin_sdecl = sind(obl_ecl) * sind(slon); + cos_sdecl = sqrt(1.0 - sin_sdecl * sin_sdecl); + + /* Compute the Sun's apparent radius, degrees */ + sradius = 0.2666 / sr; + + /* Do correction to upper limb, if necessary */ + if (upper_limb) + altit -= sradius; + + /* Compute the diurnal arc that the Sun traverses to reach */ + /* the specified altitude altit: */ + { + double cost; + cost = (sind(altit) - sind(lat) * sin_sdecl) / + (cosd(lat) * cos_sdecl); + if (cost >= 1.0) + t = 0.0; /* Sun always below altit */ + else if (cost <= -1.0) + t = 24.0; /* Sun always above altit */ + else + t = (2.0 / 15.0) * acosd(cost); /* The diurnal arc, hours */ + } + return t; +} /* __daylen__ */ + + +/* This function computes the Sun's position at any instant */ + +static void sunpos(double d, double *lon, double *r) +/******************************************************/ +/* Computes the Sun's ecliptic longitude and distance */ +/* at an instant given in d, number of days since */ +/* 2000 Jan 0.0. The Sun's ecliptic latitude is not */ +/* computed, since it's always very near 0. */ +/******************************************************/ +{ + double M, /* Mean anomaly of the Sun */ + w, /* Mean longitude of perihelion */ + /* Note: Sun's mean longitude = M + w */ + e, /* Eccentricity of Earth's orbit */ + E, /* Eccentric anomaly */ + x, y, /* x, y coordinates in orbit */ + v; /* True anomaly */ + + /* Compute mean elements */ + M = revolution(356.0470 + 0.9856002585 * d); + w = 282.9404 + 4.70935E-5 * d; + e = 0.016709 - 1.151E-9 * d; + + /* Compute true longitude and radius vector */ + E = M + e * RADEG * sind(M) * (1.0 + e * cosd(M)); + x = cosd(E) - e; + y = sqrt(1.0 - e * e) * sind(E); + *r = sqrt(x * x + y * y); /* Solar distance */ + v = atan2d(y, x); /* True anomaly */ + *lon = v + w; /* True solar longitude */ + if (*lon >= 360.0) + *lon -= 360.0; /* Make it 0..360 degrees */ +} + +static void sun_RA_dec(double d, double *RA, double *dec, double *r) +{ + double lon, obl_ecl, x, y, z; + + /* Compute Sun's ecliptical coordinates */ + sunpos(d, &lon, r); + + /* Compute ecliptic rectangular coordinates (z=0) */ + x = *r * cosd(lon); + y = *r * sind(lon); + + /* Compute obliquity of ecliptic (inclination of Earth's axis) */ + obl_ecl = 23.4393 - 3.563E-7 * d; + + /* Convert to equatorial rectangular coordinates - x is unchanged */ + z = y * sind(obl_ecl); + y = y * cosd(obl_ecl); + + /* Convert to spherical coordinates */ + *RA = atan2d(y, x); + *dec = atan2d(z, sqrt(x * x + y * y)); + +} /* sun_RA_dec */ + + +/******************************************************************/ +/* This function reduces any angle to within the first revolution */ +/* by subtracting or adding even multiples of 360.0 until the */ +/* result is >= 0.0 and < 360.0 */ +/******************************************************************/ + +#define INV360 ( 1.0 / 360.0 ) + +static double revolution(double x) +/*****************************************/ +/* Reduce angle to within 0..360 degrees */ +/*****************************************/ +{ + return (x - 360.0 * floor(x * INV360)); +} /* revolution */ + +static double rev180(double x) +/*********************************************/ +/* Reduce angle to within +180..+180 degrees */ +/*********************************************/ +{ + return (x - 360.0 * floor(x * INV360 + 0.5)); +} /* revolution */ + + +/*******************************************************************/ +/* This function computes GMST0, the Greenwich Mean Sidereal Time */ +/* at 0h UT (i.e. the sidereal time at the Greenwhich meridian at */ +/* 0h UT). GMST is then the sidereal time at Greenwich at any */ +/* time of the day. I've generalized GMST0 as well, and define it */ +/* as: GMST0 = GMST - UT -- this allows GMST0 to be computed at */ +/* other times than 0h UT as well. While this sounds somewhat */ +/* contradictory, it is very practical: instead of computing */ +/* GMST like: */ +/* */ +/* GMST = (GMST0) + UT * (366.2422/365.2422) */ +/* */ +/* where (GMST0) is the GMST last time UT was 0 hours, one simply */ +/* computes: */ +/* */ +/* GMST = GMST0 + UT */ +/* */ +/* where GMST0 is the GMST "at 0h UT" but at the current moment! */ +/* Defined in this way, GMST0 will increase with about 4 min a */ +/* day. It also happens that GMST0 (in degrees, 1 hr = 15 degr) */ +/* is equal to the Sun's mean longitude plus/minus 180 degrees! */ +/* (if we neglect aberration, which amounts to 20 seconds of arc */ +/* or 1.33 seconds of time) */ +/* */ +/*******************************************************************/ + +static double GMST0(double d) +{ + double sidtim0; + /* Sidtime at 0h UT = L (Sun's mean longitude) + 180.0 degr */ + /* L = M + w, as defined in sunpos(). Since I'm too lazy to */ + /* add these numbers, I'll let the C compiler do it for me. */ + /* Any decent C compiler will add the constants at compile */ + /* time, imposing no runtime or code overhead. */ + sidtim0 = revolution((180.0 + 356.0470 + 282.9404) + + (0.9856002585 + 4.70935E-5) * d); + return sidtim0; +} /* GMST0 */ + +#ifdef NOTDEF +int main() +{ + astTsunriset srs; + + astFsunriset(&srs, 4, 23, 1979, 49, -123); +} +#endif diff --git a/lc-continuity/mk4/continuity/mecha/b64.c b/lc-continuity/mk4/continuity/mecha/b64.c new file mode 100644 index 0000000000000000000000000000000000000000..fa0692e8d13f5d3dc8355b21bd7363a49df80a16 --- /dev/null +++ b/lc-continuity/mk4/continuity/mecha/b64.c @@ -0,0 +1,216 @@ +/* + * $Header: /san01/cvs/ashpool/csrc/continuity/mecha/Attic/b64.c,v 1.9 2004/04/30 13:41:56 aleigh Exp $ + */ + +/* + * Copyright (c) 1994, 2004 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Disclosure, copying, distribution, or transmission of this code without + * express permission is prohibited. + */ + +#include "mecha.h" + +/* + * MODULE HTUU.c + * + * UENCODE AND UUDECODE + * + * ACKNOWLEDGEMENT: This code is taken from rpem distribution, and was + * originally written by Mark Riordan. + * + * AUTHORS: MR Mark Riordan riordanmr@clvax1.cl.msu.edu AL Ari + * Luotonen luotonen@dxcern.cern.ch + * + * HISTORY: Added as part of the WWW library and edited to conform with the WWW + * project coding standards by: AL 5 Aug 1993 Originally written by: + * MR 12 Aug 1990 Original header text: + * ------------------------------------------------------------- File + * containing routines to convert a buffer of bytes to/from RFC 1113 + * printable encoding format. + * + * This technique is similar to the familiar Unix uuencode format in that it + * maps 6 binary bits to one ASCII character (or more aptly, 3 binary bytes + * to 4 ASCII characters). However, RFC 1113 does not use the same mapping + * to printable characters as uuencode. + * + * Mark Riordan 12 August 1990 and 17 Feb 1991. This code is hereby placed in + * the public domain. + * ------------------------------------------------------------- + * + * BUGS: + * + */ + + +/* + * htuu.c -- + * + * Uuencoding and decoding routines. + * + * + */ + + +static char six2pr[64] = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', + 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' +}; + +static unsigned char pr2six[256]; + + +/*--- function HTUU_encode ----------------------------------------------- + * + * Encode a single line of binary data to a standard format that + * uses only printing ASCII characters (but takes up 33% more bytes). + * + * Entry bufin points to a buffer of bytes. If nbytes is not + * a multiple of three, then the byte just beyond + * the last byte in the buffer must be 0. + * nbytes is the number of bytes in that buffer. + * This cannot be more than 48. + * bufcoded points to an output buffer. Be sure that this + * can hold at least 1 + (4*nbytes)/3 characters. + * + * Exit bufcoded contains the coded line. The first 4*nbytes/3 bytes + * contain printing ASCII characters representing + * those binary bytes. This may include one or + * two '=' characters used as padding at the end. + * The last byte is a zero byte. + * Returns the number of ASCII characters in "bufcoded". + */ +int b64Fencode(unsigned char *bufin, unsigned int nbytes, char *bufcoded) +{ + /* ENC is the basic 1 character encoding function to make a char printing */ +#define ENC(c) six2pr[c] + + register char *outptr = bufcoded; + unsigned int i; + + assert(bufin != NULL); + assert(bufcoded != NULL); + + for (i = 0; i < nbytes; i += 3) { + /* c1 */ + *(outptr++) = ENC(*bufin >> 2); + /* c2 */ + *(outptr++) = ENC(((*bufin << 4) & 060) | ((bufin[1] >> 4) & 017)); + /* c3 */ + *(outptr++) = + ENC(((bufin[1] << 2) & 074) | ((bufin[2] >> 6) & 03)); + /* c4 */ + *(outptr++) = ENC(bufin[2] & 077); + + bufin += 3; + } + + /* + * If nbytes was not a multiple of 3, then we have encoded too many + * characters. Adjust appropriately. + */ + if (i == nbytes + 1) { + /* There were only 2 bytes in that last group */ + outptr[-1] = '='; + } else if (i == nbytes + 2) { + /* There was only 1 byte in that last group */ + outptr[-1] = '='; + outptr[-2] = '='; + } + *outptr = '\0'; + return (outptr - bufcoded); +} + + +/*--- function HTUU_decode ------------------------------------------------ + * + * Decode an ASCII-encoded buffer back to its original binary form. + * + * Entry bufcoded points to a uuencoded string. It is + * terminated by any character not in + * the printable character table six2pr, but + * leading whitespace is stripped. + * bufplain points to the output buffer; must be big + * enough to hold the decoded string (generally + * shorter than the encoded string) plus + * as many as two extra bytes used during + * the decoding process. + * outbufsize is the maximum number of bytes that + * can fit in bufplain. + * + * Exit Returns the number of binary bytes decoded. + * bufplain contains these bytes. + */ +int b64Fdecode(const char *bufcoded, unsigned char *bufplain, + int outbufsize) +{ + /* single character decode */ +#define DEC(c) pr2six[(int)c] +#define MAXVAL 63 + + static int first = 1; + + int nbytesdecoded, j; + register const char *bufin = bufcoded; + register unsigned char *bufout = bufplain; + register int nprbytes; + + assert(bufcoded != NULL); + assert(bufplain != NULL); + /* + * If this is the first call, initialize the mapping table. This code + * should work even on non-ASCII machines. + */ + if (first) { + first = 0; + for (j = 0; j < 256; j++) + pr2six[j] = MAXVAL + 1; + + for (j = 0; j < 64; j++) + pr2six[(int) six2pr[j]] = (unsigned char) j; + } + /* Strip leading whitespace. */ + + while (*bufcoded == ' ' || *bufcoded == '\t') + bufcoded++; + + /* + * Figure out how many characters are in the input buffer. If this would + * decode into more bytes than would fit into the output buffer, adjust + * the number of input bytes downwards. + */ + bufin = bufcoded; + while (pr2six[(int) *(bufin++)] <= MAXVAL); + nprbytes = bufin - bufcoded - 1; + nbytesdecoded = ((nprbytes + 3) / 4) * 3; + if (nbytesdecoded > outbufsize) { + nprbytes = (outbufsize * 4) / 3; + } + bufin = bufcoded; + + while (nprbytes > 0) { + *(bufout++) = + (unsigned char) (DEC(*bufin) << 2 | DEC(bufin[1]) >> 4); + *(bufout++) = + (unsigned char) (DEC(bufin[1]) << 4 | DEC(bufin[2]) >> 2); + *(bufout++) = (unsigned char) (DEC(bufin[2]) << 6 | DEC(bufin[3])); + bufin += 4; + nprbytes -= 4; + } + + if (nprbytes & 03) { + if (pr2six[(int) bufin[-2]] > MAXVAL) { + nbytesdecoded -= 2; + } else { + nbytesdecoded -= 1; + } + } + return (nbytesdecoded); +} diff --git a/lc-continuity/mk4/continuity/mecha/bsp.c b/lc-continuity/mk4/continuity/mecha/bsp.c new file mode 100644 index 0000000000000000000000000000000000000000..afc975459e608a5d6279a86ff4a24be7e966416c --- /dev/null +++ b/lc-continuity/mk4/continuity/mecha/bsp.c @@ -0,0 +1,294 @@ +/* + * $Header: /san01/cvs/ashpool/csrc/continuity/mecha/Attic/bsp.c,v 1.18 2004/04/30 13:41:56 aleigh Exp $ + */ + +/* + * Copyright (c) 1994, 2004 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Use, disclosure, copying, distribution, or transmission of this code without + * express permission is prohibited. + */ + +#include "mecha.h" + +#undef BSP_DEBUG +#undef BSP_DEBUG_LOTS + +struct bspSentry { + unsigned int l_key; /* the lowest value of this key range */ + unsigned int h_key; /* the highest value of this key range */ + void *p; + int is_copy; /* 1 if p is a copy and shouldn't be + * destructed */ + struct bspSentry *next; +}; +typedef struct bspSentry bspTentry; + +struct bspSnode { + unsigned int split; /* the key value on which the nodes are split */ + struct bspSnode *high; /* The next list, high */ + struct bspSnode *low; /* The next list, low */ + bspTentry *ents; +}; + +static void bspFadd_entry(bspTnode * node, bspTentry * ent); +static void bspF_balance(bspTnode * node, unsigned int count, + unsigned int depth); +static bspTentry *bspFdup_entry(bspTentry * ent); + +void bspFdestroy(bspTnode * node, void (*destructor) (void *)) +{ + bspTentry *e, *ne; + + assert(node != NULL); + + /* Destroy any member entries */ + + for (e = node->ents; e != NULL; e = ne) { + ne = e->next; + if (e->p != NULL) { + if (destructor != NULL && e->is_copy == 0) + destructor(e->p); + } + free(e); + } + + if (node->high != NULL) + bspFdestroy(node->high, destructor); + if (node->low != NULL) + bspFdestroy(node->low, destructor); + + free(node); +} + +static void bspFadd_entry(bspTnode * node, bspTentry * ent) +{ + assert(node != NULL); + assert(ent != NULL); + ent->next = node->ents; + node->ents = ent; +} + +static bspTentry *bspFdup_entry(bspTentry * ent) +{ + bspTentry *e; + + assert(ent != NULL); + + e = (bspTentry *) malloc(sizeof(bspTentry)); + assert(e != NULL); + + memFcopy(ent, e, sizeof(bspTentry)); + + e->next = NULL; + return e; +} + +/* + * Allocate and return an empty bspTnode + */ +bspTnode *bspFinit(void) +{ + bspTnode *p; + + p = (bspTnode *) malloc(sizeof(bspTnode)); + assert(p != NULL); + memFclear(p, sizeof(bspTnode)); + + return p; +} + +/* + * The the given node and split it into two nodes based on the median value. + */ +void bspFsplit(bspTnode * node) +{ + unsigned int max = 0, min = 0, size = 0; + bspTentry *ent, *tmpent, *next; + + assert(node != NULL); + + /* Determine the min/max range of the low keys */ + for (ent = node->ents; ent != NULL; ent = ent->next) { +#ifdef BSP_DEBUG_LOTS + logFmsg(3,"bspFsplit: entry: %u low key: %u min/max: %u/%u", size, ent->l_key, min, max); +#endif + if (ent->l_key < min || min == 0) + min = ent->l_key; + if (ent->l_key > max || max == 0) + max = ent->l_key; + size++; + } + + /* Calculate the splitpoint */ + node->split = min + ((max - min) / 2); + +#ifdef BSP_DEBUG + logFmsg(3,"bspFsplit: Split point calculated: %u from %u / %u. I have %u elements.", node->split, min, max, size); +#endif + + node->high = bspFinit(); + node->low = bspFinit(); + + ent = node->ents; + while (1) { + int e; + + /* + * e0, Load the range low e1, Load the range high e2, Split the range + * into two ranges and load high and low + */ + + if (ent->l_key < node->split) + e = 0; + else + e = 1; + + if (ent->l_key < node->split && ent->h_key > node->split) + e = 2; + + next = ent->next; + + if (e == 0) { + bspFadd_entry(node->low, ent); + } + if (e == 1) { + bspFadd_entry(node->high, ent); + } + if (e == 2) { + tmpent = bspFdup_entry(ent); + tmpent->h_key = (node->split - 1); + tmpent->is_copy = 1; + bspFadd_entry(node->low, tmpent); + + ent->l_key = node->split; + bspFadd_entry(node->high, ent); + } + if (next == NULL) + break; + ent = next; + } + + /* This is intentional */ + node->ents = NULL; +} + +/* + * Count the number of entries in the given node. + */ +unsigned int bspFcount(bspTnode * node) +{ + bspTentry *ent; + unsigned int size = 0; + + assert(node != NULL); + + if (node->ents == NULL) + return 0; + + for (ent = node->ents; ent != NULL; ent = ent->next) { + size++; + } + + return size; +} + +/* + * Balance an entire tree, up to the given depth. Size indicates the number + * of entries that a given node must have before it is split. Let depth be 0 + * for the first invocation. + */ + +void bspFbalance(bspTnode * node, unsigned int count) +{ + assert(node != NULL); + bspF_balance(node, count, 0); +} + +static void bspF_balance(bspTnode * node, unsigned int size, + unsigned int depth) +{ + unsigned int count; + + assert(node != NULL); + assert(depth<20); + + depth++; + + count=bspFcount(node); +#ifdef BSP_DEBUG + logFmsg(3,"bspF_balance: Will split if %u > %u", count, size); +#endif + + if (count > size) { + /* Split this node */ + bspFsplit(node); + bspF_balance(node->high, size, depth); + bspF_balance(node->low, size, depth); + } +} + +int bspFadd(bspTnode * list, void *p, int high_key, int low_key) +{ + bspTentry *ep; + + assert(list != NULL); + assert(p != NULL); + + ep = (bspTentry *) malloc(sizeof(bspTentry)); + + assert(ep != NULL); + + ep->l_key = low_key; + ep->h_key = high_key; + ep->p = p; + ep->next = list->ents; + list->ents = ep; + + return 0; +} + +/* + * Searches for key in the BSP range *list. Returns NULL if the value is not + * found in any of the ranges. + */ + +void *bspFsearch(bspTnode * node, unsigned int x) +{ + bspTentry *e; + bspTnode *n; + + assert(node != NULL); + + n = node; + + while (1) { + if (n->ents == NULL) { + /* Transverse */ + if (x >= n->split) { + if (n->high == NULL) + return NULL; + n = n->high; + } else { + if (n->low == NULL) + return NULL; + n = n->low; + } + } else { + if (n->ents == NULL) + return NULL; + e = n->ents; + while (1) { + if (e->l_key <= x && e->h_key >= x) + return e->p; + if (e->next == NULL) + return NULL; + e = e->next; + } + } + } +} diff --git a/lc-continuity/mk4/continuity/mecha/bus.c b/lc-continuity/mk4/continuity/mecha/bus.c new file mode 100644 index 0000000000000000000000000000000000000000..418894748bbe06447c4fc7f7b911a4e869b49b01 --- /dev/null +++ b/lc-continuity/mk4/continuity/mecha/bus.c @@ -0,0 +1,135 @@ +/* + * $Header: /san01/cvs/ashpool/csrc/continuity/mecha/Attic/bus.c,v 1.10 2004/04/30 13:41:56 aleigh Exp $ + */ + +/* + * Copyright (c) 1994, 2004 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Use, disclosure, copying, distribution, or transmission of this code without + * express permission is prohibited. + */ + +#include "mecha.h" + +struct busSelem { + long msg_type; + /* unsigned int time; */ + void *data; + size_t data_len; + struct busSelem *next; +}; +typedef struct busSelem busTelem; + +struct busSbus { + pthread_rwlock_t lock; + struct busSelem *msgs; + struct busSelem *last_msg; + void (*destructor) (void *); +}; + +busTbus *busFinit(void (*destructor) (void *)) +{ + busTbus *bus; + + bus = (busTbus *) malloc(sizeof(busTbus)); + assert(bus != NULL); + + memFclear(bus, sizeof(busTbus)); + + bus->msgs = NULL; + bus->last_msg = NULL; + bus->destructor = destructor; + + if (pthread_rwlock_init(&bus->lock, NULL) == -1) { + return NULL; + } + return bus; +} + +void busFfree(busTbus * bus) +{ + busTelem *e, *np; + + assert(bus != NULL); + + pthread_rwlock_wrlock(&bus->lock); + + e = bus->msgs; + + while (1) { + bus->destructor(e->data); + np = e->next; + free(e); + if (np == NULL) + break; + e = np; + } + + free(bus); +} + +int busFpush(busTbus * bus, void *data, size_t data_len) +{ + busTelem *elem; + + assert(bus != NULL); + assert(data != NULL); + + elem = (busTelem *) malloc(sizeof(busTelem)); + + assert(elem != NULL); + + elem->data = data; + elem->data_len = data_len; + elem->next = NULL; + + if (pthread_rwlock_wrlock(&bus->lock) == -1) + return -1; + + if (bus->last_msg == NULL) { + bus->msgs = bus->last_msg = elem; + } else { + bus->last_msg->next = elem; + bus->last_msg = elem; + } + + pthread_rwlock_unlock(&bus->lock); + + return 0; +} + +int busFpull(busTbus * bus, void **data) +{ + busTelem *e; + size_t len; + + assert(bus != NULL); + assert(data != NULL); + + if (pthread_rwlock_wrlock(&bus->lock) == -1) + return -1; + + if (bus->msgs == NULL) { + pthread_rwlock_unlock(&bus->lock); + return 0; + } + e = bus->msgs; + if (bus->last_msg == e) { + bus->last_msg = bus->msgs = NULL; + } else { + bus->msgs = e->next; + } + + pthread_rwlock_unlock(&bus->lock); + + *data = e->data; + len = e->data_len; + + free(e); + + return len; +} diff --git a/lc-continuity/mk4/continuity/mecha/crc.c b/lc-continuity/mk4/continuity/mecha/crc.c new file mode 100644 index 0000000000000000000000000000000000000000..ee1d2b563e3a9d8fee07d461659221aa52a2f648 --- /dev/null +++ b/lc-continuity/mk4/continuity/mecha/crc.c @@ -0,0 +1,94 @@ +/* + * $Header: /san01/cvs/ashpool/csrc/continuity/mecha/Attic/crc.c,v 1.8 2004/04/30 13:41:56 aleigh Exp $ + */ + +/* + * Copyright (c) 1994, 2004 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Disclosure, copying, distribution, or transmission of this code without + * express permission is prohibited. + */ + +#include "mecha.h" + +static uint32_t crc_table[256] = { + 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, + 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, + 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, + 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, + 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, + 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, + 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, + 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, + 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, + 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, + 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, + 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, + 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, + 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, + 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, + 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, + 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, + 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, + 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, + 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, + 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, + 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, + 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, + 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, + 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, + 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, + 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, + 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, + 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, + 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, + 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, + 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, + 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, + 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, + 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, + 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, + 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, + 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, + 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, + 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, + 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, + 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, + 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, + 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, + 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, + 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, + 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, + 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, + 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, + 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, + 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, + 0x2d02ef8dL +}; + +#define DO1(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8); +#define DO2(buf) DO1(buf); DO1(buf); +#define DO4(buf) DO2(buf); DO2(buf); +#define DO8(buf) DO4(buf); DO4(buf); + +uint32_t crcFcrc32(const unsigned char *buf, unsigned len) +{ + uint32_t crc = 0xffffffffL; + + assert(buf != NULL); + + while (len >= 8) { + DO8(buf); + len -= 8; + } + if (len) + do { + DO1(buf); + } + while (--len); + return crc ^ 0xffffffffL; +} diff --git a/lc-continuity/mk4/continuity/mecha/cv.c b/lc-continuity/mk4/continuity/mecha/cv.c new file mode 100644 index 0000000000000000000000000000000000000000..44faf29e6aab877e6276ef83c4014eb466c76301 --- /dev/null +++ b/lc-continuity/mk4/continuity/mecha/cv.c @@ -0,0 +1,381 @@ +/* + * Copyright (c) 1994, 2004 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Use, disclosure, copying, distribution, or transmission of this code without + * express permission is prohibited. + */ + +#include "mecha.h" + +struct cSval { + int type; + + char *str_ptr; + size_t str_len; + + double dbl; + long long integer; + + float flt; + + void (*obj_destruct)(void *, size_t); + void *(*obj_copy)(void *, size_t); + int (*obj_compare)(void *, void *, size_t); + void *obj_ptr; + size_t obj_size; + + size_t refcount; +}; + +int cFval_type_get(cTval *v) +{ + assert(v!=NULL); + return v->type; +} + +void cFval_used(cTval *v) { + assert(v!=NULL); + v->refcount++; +} + +cTval *cFval_init(void) +{ + cTval *v = (cTval *)malloc(sizeof(cTval)); + + assert(v!=NULL); + + v->type=CV_EMPTY; + v->refcount=0; + return v; +} + +void cFval_empty(cTval *v) +{ + assert(v!=NULL); + + switch(v->type) { + case CV_EMPTY: + return; + + case CV_STRING: + if(v->str_ptr!=NULL) { + free(v->str_ptr); + } + break; + + case CV_OBJECT: + if(v->obj_ptr!=NULL && v->obj_destruct!=NULL) { + v->obj_destruct(v->obj_ptr, v->obj_size); + } + v->obj_destruct=NULL; + break; + + /* CV_FLOAT: Do nothing */ + /* CV_INTEGER: Do nothing */ + } + + v->type=CV_EMPTY; +} + +void cFval_free(cTval *v) +{ + assert(v!=NULL); + + if(v->refcount>1) { + v->refcount--; + return; + } + + cFval_empty(v); + + free(v); +} + +void cFval_assign_string(cTval *v, char *str, size_t len) +{ + assert(v!=NULL); + + cFval_empty(v); + + if(str==NULL) { + v->type=CV_EMPTY; + return; + } + + v->type=CV_STRING; + v->str_ptr=str; + v->str_len=len; +} + +void cFval_assign_string_copy(cTval *v, const char *str, size_t len) +{ + assert(v!=NULL); + + cFval_empty(v); + + v->type=CV_STRING; + v->str_ptr=strFncopy(str, len); + v->str_len=len; +} + +void cFval_assign_object(cTval *v, void *obj, size_t size) +{ + assert(v!=NULL); + + cFval_empty(v); + + v->type=CV_OBJECT; + v->obj_ptr=obj; + v->obj_size=size; +} + +void cFval_assign_object_tors(cTval *v, + void (*obj_destructor)(void *, size_t), + void *(*obj_duplicator)(void *, size_t), + int (*obj_comparator)(void *, void *, size_t)) +{ + assert(v!=NULL); + + v->obj_destruct=obj_destructor; + v->obj_copy=obj_duplicator; + v->obj_compare=obj_comparator; +} + +void cFval_assign_float(cTval *v, double value) +{ + assert(v!=NULL); + + cFval_empty(v); + + v->type=CV_FLOAT; + v->dbl=value; +} + +void cFval_assign_integer(cTval *v, long long value) +{ + assert(v!=NULL); + + cFval_empty(v); + + v->type=CV_INTEGER; + v->integer=value; +} + +long long cFval_get_integer(cTval *v) +{ + assert(v!=NULL); + + /* todo: support object converter -aleigh */ + switch(v->type) { + case CV_INTEGER: + return v->integer; + case CV_FLOAT: + return (long long) v->dbl; + case CV_STRING: + return atoll(v->str_ptr); + default: + return 0; + } +} + +double cFval_get_float(cTval *v) +{ + assert(v!=NULL); + + switch(v->type) { + case CV_INTEGER: + return (double) v->integer; + case CV_FLOAT: + return v->dbl; + case CV_STRING: + return (double)atoll(v->str_ptr); + + default: + return 0; + } + + /* todo: Support object converter -aleigh */ +} + +/* Get a const char pointer to the string stored in the cval. + * No conversion to other types is supported because that would + * require the function to return orphaned memory. + */ +const char *cFval_get_string(cTval *v, size_t *size) +{ + assert(v!=NULL); + + if(v->type==CV_STRING) { + *size=v->str_len; + return v->str_ptr; + } + + return NULL; +} + +ssize_t cFval_get_string_copy(cTval *v, char *buf, size_t buf_size) +{ + assert(v!=NULL); + + switch(v->type) { + case CV_INTEGER: + return snprintf(buf,buf_size,"%Ld",v->integer); + case CV_FLOAT: + return snprintf(buf,buf_size,"%e",v->dbl); + case CV_STRING: + if(buf_sizestr_len) { + memFcopy(v->str_ptr,buf,buf_size-1); + buf[buf_size]=0; + return buf_size; + } else { + memFcopy(v->str_ptr,buf,v->str_len); + return v->str_len; + } + default: + return -1; + } +} + +cTval *cFval_copy(cTval *v) +{ + cTval *new=cFval_init(); + + assert(v!=NULL); + assert(new!=NULL); + + switch(v->type) { + case CV_STRING: + new->type=CV_STRING; + new->str_ptr=strFncopy(v->str_ptr,v->str_len); + new->str_len=v->str_len; + break; + case CV_OBJECT: + new->type=CV_OBJECT; + + if(v->obj_copy==NULL) { + new->obj_ptr=v->obj_ptr; + } else { + new->obj_ptr=v->obj_copy(v->obj_ptr,v->obj_size); + } + + new->obj_size=v->obj_size; + new->obj_destruct=v->obj_destruct; + new->obj_copy=v->obj_copy; + new->obj_compare=v->obj_compare; + break; + case CV_FLOAT: + new->type=CV_FLOAT; + new->dbl=v->dbl; + break; + } + return new; +} + +struct cSarray +{ + cTval **vals; + size_t size; + size_t count; +}; + +cTarray *cFarray_new(void) +{ + cTarray *array; + + array=(cTarray *)malloc(sizeof(cTarray)); + assert(array!=NULL); + + array->count=array->size=0; + + return array; +} + +void cFarray_push(cTarray *array, cTval *val) +{ + assert(array!=NULL); + assert(val!=NULL); + + if(array->size==0) { + array->vals=malloc(sizeof(void *)); + assert(array->vals!=NULL); + + array->size=1; + array->vals[0]=val; + array->count++; + } else { + array->size++; + + array->vals=realloc(array->vals,array->size*sizeof(void *)); + assert(array->vals!=NULL); + + array->vals[array->size]=val; + array->count++; + } + val->refcount++; +} + +cTval *cFarray_pop(cTarray *array) +{ + cTval *val; + + assert(array!=NULL); + + if(array->count==0) return NULL; + + int c=0; + for(int i=0;icount;i++) { + if(array->vals[i]!=NULL) { + c++; + } + + if(c==array->count) { + val=array->vals[i]; + array->vals[i]=NULL; + array->count--; + val->refcount--; + return val; + } + } + assert(1!=1); +} + +void *cFarray_foreach(cTarray *array, void *(*callback)(cTval *v)) +{ + void *userdata; + + for(int i=0;isize;i++) { + if(array->vals[i]!=NULL) { + userdata=callback(array->vals[i]); + if(userdata!=NULL) { + return userdata; + } + } + } + return NULL; +} + +void cFarray_free(cTarray *array) { + for(int i=0;isize;i++) { + if(array->vals[i]!=NULL) { + cFval_free(array->vals[i]); + } + } + free(array->vals); + free(array); +} + +struct cSassoc { + cTarray *names; + cTarray *values; + + hshTlist *forward; + hshTlist *reverse; + + size_t count; +}; + + diff --git a/lc-continuity/mk4/continuity/mecha/dic.c b/lc-continuity/mk4/continuity/mecha/dic.c new file mode 100644 index 0000000000000000000000000000000000000000..64cd81bdadba9a9978ec2ae1cf1f8353a98a47cd --- /dev/null +++ b/lc-continuity/mk4/continuity/mecha/dic.c @@ -0,0 +1,134 @@ +/* + * $Header: /san01/cvs/ashpool/csrc/continuity/mecha/Attic/dic.c,v 1.1 2004/04/30 13:41:56 aleigh Exp $ + */ + +/* + * Copyright (c) 2004 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Use, disclosure, copying, distribution, or transmission of this code without + * express permission is prohibited. + */ + +#include "mecha.h" + +/* + * String values are copied into the dictionary so that they may be freed + * by the calling program. They are free'd with the destruction of the + * forward list; the reverse list does not destroy the keys. + */ +struct dicSdictionary { + /* int -> name */ + hshTvoid_list *forward; + /* name -> int */ + hshTvoid_list *reverse; + /* int -> data */ + hshTvoid_list *userdata; + + void(*userdata_destructor)(void *); +}; + +dicTdictionary *dicFinit(void (*destructor) (void *), + int (*comparator) (const void *s1, + const void *s2, + size_t len)) { + dicTdictionary *d; + + d=(dicTdictionary *)malloc(sizeof(dicTdictionary)); + + assert(d!=NULL); + + /* The forward list will be responsible for destroying + * the values placed into the dictionary, so we will + * give it a destructor + */ + d->forward=hshFvoid_int_init(destructor); + assert(d->forward!=NULL); + + d->reverse=hshFvoid_raw_init(NULL,NULL,comparator,16); + assert(d->reverse!=NULL); + + d->userdata=hshFvoid_int_init(NULL); + assert(d->userdata!=NULL); + + return d; +} + +void dicFuserdata_update (dicTdictionary *d, int idx, void *data) { + hshFvoid_int_update(d->userdata,idx,data); +} + +void *dicFuserdata_find(dicTdictionary *d, int idx) { + return hshFvoid_int_find(d->userdata,idx); +} + +void dicFuserdata_destructor_set(dicTdictionary *d, void (*destructor)(void *)) { + assert(d!=NULL); + hshFvalue_destructor_set(d->userdata,destructor); +} + +void dicFfree(dicTdictionary *d) { + hshFvoid_destroy(d->forward); + hshFvoid_destroy(d->reverse); + hshFvoid_destroy(d->userdata); + free(d); +} + +int dicFupdate(dicTdictionary *d, int idx, void *value, size_t value_len) { + assert(d!=NULL); + assert(value!=NULL); + + hshFvoid_int_update(d->forward,idx,value); + hshFvoid_raw_add(d->reverse,value,value_len,(void *)idx,1); + + return 0; +} + +void *dicFfind(dicTdictionary *d, int idx) { + assert(d!=NULL); + assert(d->forward!=NULL); + + return hshFvoid_int_find(d->forward,idx); +} + +int docFfind_index(dicTdictionary *d, void *value, size_t value_len, int *idx) { + void *p; + + assert(d!=NULL); + assert(d->reverse!=NULL); + assert(value!=NULL); + + p=hshFvoid_raw_find(d->reverse, value, value_len); + + if(p==NULL) { + return -1; + } + + *idx=(int)p; + return 0; +} + +char *dicFchar_find(dicTdictionary *d, int idx) { + assert(d!=NULL); + + return (char *)hshFvoid_int_find(d->forward,idx); +} + +int dicFchar_update(dicTdictionary *d, int idx, char *str, size_t str_len) { + assert(d!=NULL); + assert(str!=NULL); + + return dicFupdate(d,idx,(void *)strFncopy(str,str_len),str_len); +} + +dicTdictionary *dicFchar_init(void) { + return dicFinit(free,strncmp); +} + +int dicFchar_find_index(dicTdictionary *d, char *value, size_t value_len, int *idx) { + return docFfind_index(d,(void *)value,value_len,idx); +} + diff --git a/lc-continuity/mk4/continuity/mecha/dyn.c b/lc-continuity/mk4/continuity/mecha/dyn.c new file mode 100644 index 0000000000000000000000000000000000000000..fdcda9113e6f76224c812b5144217ba8a3fd9945 --- /dev/null +++ b/lc-continuity/mk4/continuity/mecha/dyn.c @@ -0,0 +1,165 @@ +/* + * $Header: /san01/cvs/ashpool/csrc/continuity/mecha/Attic/dyn.c,v 1.18 2004/04/30 13:41:56 aleigh Exp $ + */ + +/* + * Copyright (c) 1994, 2004 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Disclosure, copying, distribution, or transmission of this code without + * express permission is prohibited. + */ + +#define DYN_CHUNK_SZ 1024 + +#include "mecha.h" +#include "dyn.h" + +void dynFreset(dynTstring * ds) +{ + assert(ds != NULL); + ds->strlen = 0; +} + +void dynFfree(dynTstring * ds) +{ + assert(ds); + + if (ds->str != NULL) + free(ds->str); + free(ds); +} + +dynTstring *dynFinit(void) +{ + dynTstring *p; + + p = (dynTstring *) malloc(sizeof(dynTstring)); + + p->str = NULL; + p->len = 0; + p->strlen = 0; + + return p; +} + +static int dynFalloc(dynTstring * ds, int size) +{ + char *p; + + assert(ds != NULL); + + if (ds->str != NULL) { + p = (char *) realloc(ds->str, ds->len + size); + if (p == NULL) + return -1; + + ds->str = p; + ds->len += size; + } else { + ds->str = (char *) malloc(size); + if (ds->str == NULL) + return -1; + + ds->len = size; + + /* make the first byte empty */ + ds->str[0] = 0; + } + return 0; +} + +size_t dynFappend(dynTstring * ds, const char *str, size_t len) +{ + assert(ds != NULL); + assert(str != NULL); + + /* we want to be able to put a NULL at the end */ + if (ds->strlen + len + 1 > ds->len) { + size_t required = len - (ds->len - ds->strlen); + required += DYN_CHUNK_SZ; + dynFalloc(ds, ds->len + required); + } + memcpy(ds->str + ds->strlen, str, len); + ds->strlen += len; + + /* make the end of the string empty */ + ds->str[ds->strlen] = 0; + + return len; +} + +size_t dynFappend_string(dynTstring * ds, const dynTstring * src) +{ + assert(ds != NULL); + assert(src != NULL); + + return (dynFappend(ds, src->str, src->strlen)); +} + +size_t dynFsappend(dynTstring * ds, const char *str) +{ + assert(ds != NULL); + assert(str != NULL); + return dynFappend(ds, str, strlen(str)); +} + +size_t dynFappend_print(dynTstring * ds, const char *fmt, ...) +{ + va_list ap; + char *buf; + size_t size = 1024; + char stack_buf[1024]; + int nchars; + + assert(ds != NULL); + assert(fmt != NULL); + + buf = stack_buf; + size = sizeof(stack_buf); + + assert(buf != NULL); + + va_start(ap, fmt); + + while (1) { + nchars = vsnprintf(buf, size, fmt, ap); + + if (nchars > -1 && nchars < (int) size) + break; + if (nchars > -1) + size = nchars + 1; + else + size *= 2; + + if (buf == stack_buf) { + buf = (char *) malloc(size); + } else { + buf = (char *) realloc(buf, size); + } + } + + va_end(ap); + + dynFappend(ds, buf, nchars); + + if (buf != stack_buf) { + free(buf); + } + return (0); +} + +const char *dynFgetstr(const dynTstring * ds) +{ + assert(ds != NULL); + return ds->str; +} + +size_t dynFgetlen(const dynTstring * ds) +{ + assert(ds != NULL); + return ds->strlen; +} diff --git a/lc-continuity/mk4/continuity/mecha/dyn.h b/lc-continuity/mk4/continuity/mecha/dyn.h new file mode 100644 index 0000000000000000000000000000000000000000..82dca6e70b559639758c38b386e9b18f5fe9bf5d --- /dev/null +++ b/lc-continuity/mk4/continuity/mecha/dyn.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 1994, 2003 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Use, disclosure, copying, distribution, or transmission of of this code + * without express permission is prohibited. + */ + + +#ifndef _DYN_H +#define _DYN_H + +struct dynSstring { + char *str; + size_t len; + size_t strlen; +}; + +#endif diff --git a/lc-continuity/mk4/continuity/mecha/exp.c b/lc-continuity/mk4/continuity/mecha/exp.c new file mode 100644 index 0000000000000000000000000000000000000000..5aec59869ee8c7dddbfc245631c3380a19e8ee2f --- /dev/null +++ b/lc-continuity/mk4/continuity/mecha/exp.c @@ -0,0 +1,312 @@ +/* + * $Header: /san01/cvs/ashpool/csrc/continuity/mecha/Attic/exp.c,v 1.9 2004/04/30 13:41:56 aleigh Exp $ + */ + +/* + * Copyright (c) 2004 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Disclosure, copying, distribution, or transmission of of this code without + * express permission is prohibited. + */ + +#include "mecha.h" +#include "../pcre/pcre.h" + +#define OVECCOUNT 30 /* should be a multiple of 3 */ + +void expFregexp_free(expTregexp * re) +{ + pcre_free(re); +} + +expTregexp *expFregexp_compile(const char *pattern) +{ + pcre *re; + const char *error; + int erroffset; + + re = pcre_compile(pattern, /* the pattern */ + 0, /* default options */ + &error, /* for error message */ + &erroffset, /* for error offset */ + NULL); /* use default character tables */ + return (expTregexp *) re; +} + +int expFregexp_match(const expTregexp * regexp, const char *subject) +{ + return expFregexp_match_len(regexp, subject, strlen(subject)); +} + +/* + * Parts of this code derived from code written by Henry Spencer. + * + * The rest is written by Eric Lindvall. + * + */ +int expFregexp_replace(const expTregexp * regexp, const char *subject, + size_t subject_length, const char *replace, + MECHA_UNUSED_ARGUMENT size_t replace_length, char *output, + size_t output_length) +{ + pcre *re = (pcre *) regexp; + int ovector[OVECCOUNT]; + int rc; + register const char *src; + register char *dst; + register char c; + + rc = pcre_exec((pcre *) re, /* the compiled pattern */ + NULL, /* no extra data - we didn't study the + * pattern */ + subject, /* the subject string */ + subject_length, /* the length of the subject */ + 0, /* start at offset 0 in the subject */ + 0, /* default options */ + ovector, /* output vector for substring information */ + OVECCOUNT); /* number of elements in the output vector */ + + if (rc < 0) { + switch (rc) { + case PCRE_ERROR_NOMATCH: + return 0; + default: + return -1; + } + } + + src = replace; + dst = output; + + while ((c = *src++) != '\0' && output_length > 0) { + register int no; + + if (c == '&') { + no = 0; + } else if ((c == '\\' || c == '$') && '0' <= *src && *src <= '9') { + no = *src++ - '0'; + } else { + no = -1; + } + + if (no < 0) { /* Ordinary character. */ + if (c == '\\' && (*src == '\\' || *src == '&')) { + c = *src++; + } + *dst++ = c; + output_length--; + } else if (no <= rc) { + int len = + pcre_copy_substring(subject, ovector, rc, no, dst, + output_length); + + if (len < 0) { + return (len); + } + output_length -= len; + dst += len; + } + } + + if (output_length < 1) { + return (-1); + } + *dst++ = '\0'; + output_length--; + + return 1; +} + +int expFregexp_match_len(const expTregexp * regexp, const char *subject, + size_t subject_length) +{ + pcre *re = (pcre *) regexp; + int ovector[OVECCOUNT]; + int rc; + + rc = pcre_exec((pcre *) re, /* the compiled pattern */ + NULL, /* no extra data - we didn't study the + * pattern */ + subject, /* the subject string */ + subject_length, /* the length of the subject */ + 0, /* start at offset 0 in the subject */ + 0, /* default options */ + ovector, /* output vector for substring information */ + OVECCOUNT); /* number of elements in the output vector */ + + if (rc < 0) { + switch (rc) { + case PCRE_ERROR_NOMATCH: + return 0; + default: + return -1; + } + } + return 1; +} + +int expFmatch(const char *pattern, const char *subject) +{ + + assert(pattern!=NULL); + assert(subject!=NULL); + + return expFmatch_len(pattern, subject, strlen(subject)); +} + +int expFmatch_len(const char *pattern, const char *subject, + size_t subject_length) +{ + pcre *re; + const char *error; + int erroffset; + int ovector[OVECCOUNT]; + int rc; + + assert(pattern!=NULL); + assert(subject!=NULL); + + /************************************************************************* + * Now we are going to compile the regular expression pattern, and handle * + * and errors that are detected. * + *************************************************************************/ + + re = pcre_compile(pattern, /* the pattern */ + 0, /* default options */ + &error, /* for error message */ + &erroffset, /* for error offset */ + NULL); /* use default character tables */ + + if (re == NULL) { + return -1; + } + + /************************************************************************* + * If the compilation succeeded, we call PCRE again, in order to do a * + * pattern match against the subject string. This just does ONE match. If * + * further matching is needed, it will be done below. * + *************************************************************************/ + + rc = pcre_exec(re, /* the compiled pattern */ + NULL, /* no extra data - we didn't study the + * pattern */ + subject, /* the subject string */ + subject_length, /* the length of the subject */ + 0, /* start at offset 0 in the subject */ + 0, /* default options */ + ovector, /* output vector for substring information */ + OVECCOUNT); /* number of elements in the output vector */ + + pcre_free(re); + + if (rc < 0) { + switch (rc) { + case PCRE_ERROR_NOMATCH: + return 0; + default: + return -1; + } + } + return 1; +} + +int expFapply(const char *pattern, const char *subject, lstTset * output) +{ + pcre *re; + const char *error; + int erroffset; + int ovector[OVECCOUNT]; + int subject_length; + int rc, i; + + assert(pattern != NULL); + assert(subject != NULL); + assert(output != NULL); + + subject_length = (int) strlen(subject); + + /************************************************************************* + * Now we are going to compile the regular expression pattern, and handle * + * and errors that are detected. * + *************************************************************************/ + + re = pcre_compile(pattern, /* the pattern */ + 0, /* default options */ + &error, /* for error message */ + &erroffset, /* for error offset */ + NULL); /* use default character tables */ + + /* Compilation failed: print the error message and exit */ + + if (re == NULL) { + return -1; + } + /************************************************************************* + * If the compilation succeeded, we call PCRE again, in order to do a * + * pattern match against the subject string. This just does ONE match. If * + * further matching is needed, it will be done below. * + *************************************************************************/ + + rc = pcre_exec(re, /* the compiled pattern */ + NULL, /* no extra data - we didn't study the + * pattern */ + subject, /* the subject string */ + subject_length, /* the length of the subject */ + 0, /* start at offset 0 in the subject */ + 0, /* default options */ + ovector, /* output vector for substring information */ + OVECCOUNT); /* number of elements in the output vector */ + + /* Matching failed: handle error cases */ + + if (rc < 0) { + switch (rc) { + case PCRE_ERROR_NOMATCH: + return 0; + default: + return -1; + } + } + + /************************************************************************* + * We have found the first match within the subject string. If the output * + * vector wasn't big enough, set its size to the maximum. Then output any * + * substrings that were captured. * + *************************************************************************/ + + /* The output vector wasn't big enough */ + + if (rc == 0) { + rc = OVECCOUNT / 3; + /* Output vector not big enough */ + return -2; + } + /* + * Show substrings stored in the output vector by number. Obviously, in a + * real application you might want to do things other than print them. + */ + + for (i = 0; i < rc; i++) { + char *substring_start = (char *) subject + ovector[2 * i]; + int substring_length = ovector[2 * i + 1] - ovector[2 * i]; + char back; + + logFmsg(3, "length is %d", substring_length); + + back = substring_start[substring_length + 1]; + substring_start[substring_length + 1] = '\0'; + + lstFset_add(output, utlFshort_to_str(i), substring_start); + + substring_start[substring_length + 1] = back; + + /* printf("%2d: %.*s\n", i, substring_length, substring_start); */ + + } + + return 1; +} diff --git a/lc-continuity/mk4/continuity/mecha/fle.c b/lc-continuity/mk4/continuity/mecha/fle.c new file mode 100644 index 0000000000000000000000000000000000000000..fc642394822afdd6b5f223a2fcc7f5d7015ad5c4 --- /dev/null +++ b/lc-continuity/mk4/continuity/mecha/fle.c @@ -0,0 +1,295 @@ +/* + * $Header: /san01/cvs/ashpool/csrc/continuity/mecha/Attic/fle.c,v 1.18 2004/05/11 20:39:12 aleigh Exp $ + */ + +/* + * Copyright (c) 1994, 2004 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Disclosure, copying, distribution, or transmission of this code without + * express permission is prohibited. + */ + +#include "mecha.h" + +#define MAX_LINKS 32 /* Maximum number of links we are willing to + * recurse */ + +int fleFset_close_exec(int fd) +{ + int fd_flags; + + /* Set the socket to nonblocking */ + if ((fd_flags = fcntl(fd, F_GETFD)) == -1) { + perror("fcntl"); + return -1; + } + fd_flags |= FD_CLOEXEC; + + if (fcntl(fd, F_SETFD, fd_flags) == -1) { + perror("fcntl"); + return -1; + } + return (0); +} + +int fleFpath_combine(const char *path, int path_len, const char *relative, + char *output, int output_len) +{ + int second_length = 0; + + if (output_len < path_len) { + path_len = output_len; + } + memcpy(output, path, path_len); + + /* make sure we even have room to do anything else */ + if (path_len == output_len) { + /* + * should we return what we could do or return -1 because we couldn't + * combine them? + * + * -eric@5stops.com - 1.29.2004 + * + */ + return (path_len); + } + if (output[path_len - 1] == '/') { + output[--path_len] = 0; + } + second_length = + fleFpath_simplify(relative, output + path_len, + output_len - path_len); + + if (output[path_len] != '/') { + if (output_len <= (path_len + second_length + 1)) { + second_length = output_len - path_len - 2; + } + memmove(output + path_len + 1, output + path_len, second_length); + + output[path_len++] = '/'; + + output[path_len + second_length] = 0; + } + return (path_len + second_length); +} + +int fleFpath_simplify(const char *path, char *outpath, int len) +{ + const char *cur_path; + char *cur_outpath; + + assert(path != NULL); + assert(outpath != NULL); + + cur_path = path; + cur_outpath = outpath; + + while (*cur_path != 0 && (cur_outpath - outpath) < (len - 1)) { + if (*cur_path == '/') { + if (cur_path[1] == '.' + && (cur_path[2] == 0 || cur_path[2] == '/')) { + cur_path += 2; + + continue; + } else if (cur_path[1] == '/') { + cur_path++; + + continue; + } else if (cur_path[1] == '.' && cur_path[2] == '.' && + (cur_path[3] == 0 || cur_path[3] == '/')) { + while (cur_outpath > outpath && *(--cur_outpath) != '/'); + + if (cur_outpath == outpath) { + *cur_outpath = '/'; + } + cur_path += 3; + + continue; + } + } + *cur_outpath++ = *cur_path++; + } + + *cur_outpath = 0; + + return ((int) (cur_outpath - outpath)); +} + +void fleFpath_clean(char *pathname) +{ + char *cleanpath, c; + + assert(pathname != NULL); + + cleanpath = pathname; + while ((c = *pathname++)) { + if (c == '/') { + while (1) { + if (*pathname == '/') + pathname++; + else if (*pathname == '.' && *(pathname + 1) == '/') + pathname += 2; + else if (*pathname == '.' && *(pathname + 1) == '.' && + *(pathname + 2) == '/') { + pathname += 3; + } else + break; + } + c = '/'; + } + *cleanpath++ = c; + } + *cleanpath = '\0'; +} + +int fleFlock(const char *filename) +{ + char lockpath[1024]; + int fd; + + assert(filename != NULL); + + snprintf(lockpath, sizeof(lockpath), "%s.lock", filename); + + fd = open(lockpath, O_CREAT | O_EXCL | O_WRONLY, 0644); + + if (fd < 0) + return 0; + + close(fd); + + return 1; +} + +int fleFunlock(const char *filename) +{ + char lockpath[1024]; + + assert(filename != NULL); + + snprintf(lockpath, sizeof(lockpath), "%s.lock", filename); + + if (unlink(lockpath) < 0) + return 0; + return 1; +} + +int fleFsync_mem_to_file(char *filename, const char *memory, size_t len) +{ + int fd; + char *map; + + assert(filename != NULL); + assert(memory != NULL); + + fd = open(filename, O_RDWR, 0644); + if (fd < 0) + return -1; + + map = mmap((void *) 0, len, (PROT_READ | PROT_WRITE), 0, fd, 0); + assert(map != NULL); + + close(fd); + + if (map == MAP_FAILED) + return -1; + + memFcopy(memory, map, len); + + munmap(map, len); + + return len; +} + +int fleFexist(const char *filename) { + struct stat sb; + + assert(filename!=NULL); + + if(stat(filename,&sb)==0) { + return 1; + } + + return 0; +} + +/* How can this return -1 if it's not a ssize_t? -aleigh */ +size_t fleFget_size(const char *filename) +{ + struct stat sb; + + assert(filename != NULL); + + if (stat(filename, &sb) < 0) + return -1; + + return sb.st_size; +} + +char *fleFload_file(const char *filename, size_t * len) +{ + int fd; + size_t size; + char *map; + char *target; + + assert(filename != NULL); + assert(len != NULL); + + fd = open(filename, O_RDONLY, 0644); + if (fd < 0) + return NULL; + + size = fleFget_size(filename); + + map = mmap(0, size, PROT_READ, MAP_SHARED, fd, 0); + + close(fd); + + assert(map != NULL); + + if (map == MAP_FAILED) { + return NULL; + } + target = (char *) malloc(size); + memFcopy(map, target, size); + + *len = size; + + munmap(map, size); + + return target; +} + +void fleFrotate(int count, const char *fn) { + int i; + char buf1[1024]; + char buf2[1024]; + + assert(fn!=NULL); + assert(count>0); + + for(i=count;i>0;i--) { + snprintf(buf1,1024,"%s.%d", fn, i); + + /* The last file we just delete. */ + if(i==count) { + unlink(buf1); + continue; + } + + /* The first file we get from *fn */ + if(i==1) { + snprintf(buf1,1024,"%s.%d",fn,1); + rename(fn,buf1); + break; + } + + snprintf(buf2,1024,"%s.%d",fn,i-1); + rename(buf2,buf1); + } +} diff --git a/lc-continuity/mk4/continuity/mecha/hsh.c b/lc-continuity/mk4/continuity/mecha/hsh.c new file mode 100644 index 0000000000000000000000000000000000000000..db80aca1cec4cd038b454e33b14cf7f406509540 --- /dev/null +++ b/lc-continuity/mk4/continuity/mecha/hsh.c @@ -0,0 +1,837 @@ +/* + * $Header: /san01/cvs/ashpool/csrc/continuity/mecha/Attic/hsh.c,v 1.24 2004/05/27 14:31:42 aleigh Exp $ + */ + +/* + * Copyright (c) 1994, 2004 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Use, disclosure, copying, distribution, or transmission of this code without + * express permission is prohibited. + */ + +/* + * TA/hashlist general purpose hasing algorithm system. Alex Leigh, + * 1994,1997,1999, 2000 $Id: hsh.c,v 1.24 2004/05/27 14:31:42 aleigh Exp $ + */ + +/* + * hsh provides a general purpose, efficient data storage and retrieval + * system. The alogrithm can store an arbitrary list of sequential + * name/keyvalue pairs, each list being keyed by a character string. + * + */ + +#include "mecha.h" + +/* double-check to make sure hashing is working properly */ +#undef VALIDATING_HASH + +#define DEFAULT_HSH_SIZE 16 + +/* + * the maximum number of elements in the hashtable that are allowed for the + * hashtable to use a linear search to find. + */ +#define LINEAR_SEARCH_MAX_COUNT 0 + +unsigned int hshGrand8[256] = + { 16838, 5758, 10113, 17515, 31051, 5627, 23010, + 7419, 16212, 4086, 2749, 12767, 9084, 12060, + 32225, 17543, 25089, 21183, 25137, 25566, 26966, 4978, + 20495, 10311, 11367, 30054, 17031, 13145, 19882, 25736, + 30524, 28505, 28394, 22102, 24851, 19067, 12754, 11653, + 6561, 27096, 13628, 15188, 32085, 4143, 6967, 31406, + 24165, 13403, 25562, 24834, 31353, 920, 10444, 24803, + 7962, 19318, 1422, 31327, 10457, 1945, 14479, 29983, + 18751, 3894, 18670, 8259, 16248, 7757, 15629, 13306, + 28606, 13990, 11738, 12516, 1414, 5262, 17116, 22825, + 3181, 13134, 25343, 8022, 11233, 7536, 9760, 9979, + 29071, 1201, 21336, 13061, 22160, 24005, 30729, 7644, + 27475, 31693, 25514, 14139, 22088, 26521, 5202, 9171, 4434, + 28317, 24582, 6815, 4586, 9653, 26306, 7174, 18451, 23448, + 6473, 32434, 8193, 14110, 24748, 28210, 29320, 32049, + 12956, 14162, 4166, 14997, 7793, 32310, 21391, 19799, + 7926, 14905, 25885, 2582, 15610, 5000, 8052, 30965, 20120, + 32380, 15639, 26204, 24385, 12475, 15725, 17265, 3214, + 19471, 11376, 4697, 25543, 23297, 14619, 23087, 3123, + 31549, 18065, 24256, 18973, 20901, 25613, 6157, 9899, + 9267, 22413, 9598, 18526, 13711, 10046, 14566, 18536, + 15988, 19878, 13626, 4273, 8387, 1171, 32017, 3752, 12388, + 21191, 11483, 18122, 11744, 18528, 15585, 5363, 20159, + 5641, 18176, 9575, 28578, 27363, 27685, 29344, 19489, + 17713, 5511, 21461, 22626, 8645, 3496, 26703, 6270, 13870, + 11529, 27499, 4500, 8607, 5808, 15725, 12457, 16542, 16474, + 11531, 17222, 3952, 17024, 19894, 24015, 18247, 11276, + 26278, 19365, 8746, 21976, 18092, 25851, 29088, 29163, + 2231, 26233, 29732, 21106, 5411, 9874, 5448, 9344, 27589, + 17574, 1191, 6789, 695, 11735, 20364, 17040, 17892, 5035, + 26979, 1092, 850, 12390, 20195, 668, 20531, 29989, 12281, 23902 +}; + +int hshGprimes[] = { 11, 19, 37, 73, 109, 163, 251, 367, 557, + 823, 1237, 1861, 2777, 4177, 6247, 9371, 14057, 21089, + 31627, 47431, 71143, 106721, 160073, 240101, 360163, + 540217, 810343, 1215497, 1823231, 2734867, 4102283, + 6153409, 9230113, 13845163, -1 +}; + +struct hshSvoid_node { + char *name; + unsigned short int hashcode; + + size_t name_len; + void *data; + struct hshSvoid_node *next; +}; +typedef struct hshSvoid_node hshTvoid_node; + +struct hshSvoid_list { + struct hshSvoid_node **nodes; + void (*destructor) (void *); + void (*name_destructor) (void *); + int (*name_comparator) (const void *s1, const void *s2, size_t len); + unsigned int serial; + + unsigned int size; + unsigned int count; + float load_factor; + unsigned int collisions; + unsigned int threshold; +}; + +struct hshSiterator { + unsigned int serial; + unsigned int count; + struct hshSvoid_list *list; + hshTvoid_node *node; +}; + +static int hshFvoid_next_size(int size); +static void hshFvoid_resize(hshTvoid_list * list); +static void hshFvoid_adjust_threshold(hshTvoid_list * list); +static hshTvoid_node *_hshFvoid_raw_find(hshTvoid_list * list, + const char *name, + size_t name_len); +static void _hshFvoid_node_free(hshTvoid_list * list, hshTvoid_node * node, + int free_value); +static void *_hshFvoid_raw_remove(hshTvoid_list * list, const char *name, + size_t name_len, int free_value); + +void hshFvalue_destructor_set(hshTvoid_list *list, void (*destructor)(void *)) { + assert(list!=NULL); + + list->destructor=destructor; +} + +/* + * aleigh- calculate the hash value for a given string. This hash value is + * based on the random set. Assuming the set is sufficiently random, the data + * should distribute in a random way throughout the hashspace. + */ +unsigned short int hshFraw_hash(const char *str, size_t len, + unsigned int buckets) +{ + return (hshFraw_hashcode(str, len) % buckets); +} + +unsigned short int hshFraw_hashcode(const char *str, size_t len) +{ + unsigned short int h; + unsigned char h1, h2; + size_t pos = 0; + + assert(str != NULL); + + h1 = *str; + h2 = *(str + 1); + str++; + pos++; + + if (pos != len) + while (1) { + h1 = hshGrand8[h1 ^ *str]; + h2 = hshGrand8[h2 ^ *str]; + str++; + pos++; + if (pos == len) + break; + } + + h = ((unsigned short int) h1 << 8) | (unsigned short int) h2; + return (h); +} + +unsigned short int hshFhash(const char *str) +{ + assert(str != NULL); + return hshFraw_hash(str, strlen(str), DEFAULT_HSH_SIZE); +} + +/**********************************************************************/ + +/* + * VOID hash list implementation This is the currently recommended + * implementation, because it uses less space in memory and is slightly + * faster. + */ + +hshTvoid_list *hshFvoid_init(void (*destructor) (void *)) +{ + return hshFvoid_raw_init(destructor, free, memcmp, DEFAULT_HSH_SIZE); +} + +hshTvoid_list *hshFvoid_int_init(void (*destructor) (void *)) +{ + return hshFvoid_raw_init(destructor, free, memcmp, DEFAULT_HSH_SIZE); +} + +hshTvoid_list *hshFvoid_raw_init(void (*destructor) (void *), + void (*name_destructor) (void *), + int (name_comparator) (const void *s1, + const void *s2, + size_t len), + unsigned int buckets) +{ + hshTvoid_list *list; + + list = (hshTvoid_list *) malloc(sizeof(hshTvoid_list)); + memFclear(list, sizeof(hshTvoid_list)); + list->destructor = destructor; + list->name_destructor = name_destructor; + list->name_comparator = name_comparator; + list->load_factor = 0.75; + list->count = 0; + + list->nodes = + (hshTvoid_node **) malloc(sizeof(hshTvoid_node) * buckets); + memFclear(list->nodes, sizeof(hshTvoid_node) * buckets); + list->size = buckets; + + hshFvoid_adjust_threshold(list); + + return list; +} + +static int hshFvoid_next_size(int size) +{ + int i; + + size *= 2; + + for (i = 0; hshGprimes[i] != -1; i++) { + if (size <= hshGprimes[i]) { + return (hshGprimes[i]); + } + } + + /* + * if we don't have a prime number big enough, just double the size and + * go with that -- we should fix this. + */ + return (size); +} + +static void hshFvoid_resize(hshTvoid_list * list) +{ + int new_size = hshFvoid_next_size(list->size); + int collisions = 0; + size_t i; + struct hshSvoid_node **nodes; + + nodes = (hshTvoid_node **) calloc(new_size, sizeof(hshTvoid_node)); + + for (i = 0; i < list->size; i++) { + hshTvoid_node *node = list->nodes[i]; + + while (node != NULL) { + hshTvoid_node *next_node = node->next; + int hash = node->hashcode % new_size; + + node->next = NULL; + + if (nodes[hash] == NULL) { + nodes[hash] = node; + } else { + node->next = nodes[hash]; + nodes[hash] = node; + + collisions++; + } + + node = next_node; + } + } + + free(list->nodes); + + list->nodes = nodes; + list->size = new_size; + list->collisions = collisions; + list->serial++; + + hshFvoid_adjust_threshold(list); +} + +static void hshFvoid_adjust_threshold(hshTvoid_list * list) +{ + list->threshold = (int) (((float) list->size) * list->load_factor); + + if (list->threshold >= list->size) { + list->threshold = list->size - 1; + } +} + +int hshFvoid_size(hshTvoid_list * list) +{ + return (list->count); +} + +/* Deprecated */ +void hshFvoid_int_replace(hshTvoid_list *list, const int key, void *data) { + hshFvoid_int_update(list,key,data); +} + +void hshFvoid_int_update(hshTvoid_list * list, const int key, void *data) +{ + char *p = malloc(sizeof(int)); + + memcpy(p, &key, sizeof(int)); + hshFvoid_raw_add(list, p, sizeof(int), data, 1); +} + +int hshFvoid_int_add(hshTvoid_list * list, const int key, void *data) +{ + char *p = malloc(sizeof(int)); + + memcpy(p, &key, sizeof(int)); + return (hshFvoid_raw_add(list, p, sizeof(int), data, 0)); +} + +/* Deprecated */ +void hshFvoid_replace(hshTvoid_list * list, const char *name, void *data) { + hshFvoid_update(list,name,data); +} + +void hshFvoid_update(hshTvoid_list * list, const char *name, void *data) +{ + char *p = strdup(name); + + hshFvoid_raw_add(list, p, strlen(name), data, 1); +} + +int hshFvoid_add(hshTvoid_list * list, const char *name, void *data) +{ + char *p = strdup(name); + + return (hshFvoid_raw_add(list, p, strlen(name), data, 0)); +} + +int hshFvoid_raw_add(hshTvoid_list * list, char *name, size_t name_len, + void *data, int replace) +{ + unsigned short int hash, hashcode; + hshTvoid_node *node; + + if (list->count >= list->threshold) { + hshFvoid_resize(list); + } + hashcode = hshFraw_hashcode(name, name_len); + + hash = hashcode % list->size; + + if (list->nodes[hash] != NULL) { + hshTvoid_node *curNode, *prevNode; + + for (curNode = prevNode = list->nodes[hash]; curNode != NULL; + prevNode = curNode, curNode = curNode->next) { + if (curNode->name_len == name_len && + list->name_comparator(curNode->name, name, + name_len) == 0) { + /* + * if we aren't looking to replace the node, if the node + * already exists, we just return that we didn't add anything + */ + if (replace == 0) { + return (0); + } else { + /* + * if we're supposed to replace the node, we have to + * delete the node if it exists + */ + if (list->nodes[hash] == curNode) { + list->nodes[hash] = curNode->next; + } else { + prevNode->next = curNode->next; + } + + _hshFvoid_node_free(list, curNode, 1); + } + + break; + } + } + } + node = (hshTvoid_node *) malloc(sizeof(hshTvoid_node)); + node->hashcode = hashcode; + node->data = data; + node->name = name; + node->name_len = name_len; + node->next = NULL; + + if (list->nodes[hash] == NULL) { + list->nodes[hash] = node; + } else { + node->next = list->nodes[hash]; + list->nodes[hash] = node; + list->collisions++; + } + + list->serial++; + list->count++; + + return (1); +} + +static hshTvoid_node *_hshFvoid_raw_find_hash(hshTvoid_list * list, + const char *name, + size_t name_len) +{ + unsigned short int hash; + hshTvoid_node *node; + + assert(name != NULL); + + hash = hshFraw_hash(name, name_len, list->size); + + if (list->nodes[hash] == NULL) + return NULL; + + for (node = list->nodes[hash]; node != NULL; node = node->next) { + if (node->name_len == name_len) { + if (list->name_comparator(node->name, name, name_len) == 0) + return node; + } + } + + return NULL; +} + + +static hshTvoid_node *_hshFvoid_raw_find_linear(hshTvoid_list * list, + const char *name, + size_t name_len) +{ + size_t i; + hshTvoid_node *node; + + assert(name != NULL); + + for (i = 0; i < list->size; i++) { + for (node = list->nodes[i]; node != NULL; node = node->next) { + if (node->name_len == name_len) { + if (list->name_comparator(node->name, name, name_len) == 0) + return node; + } + } + } + + return NULL; +} + +static hshTvoid_node *_hshFvoid_raw_find(hshTvoid_list * list, + const char *name, size_t name_len) +{ + hshTvoid_node *node; + + assert(name != NULL); + + if (list->count == 0) { + return (NULL); + } +#ifdef VALIDATING_HASH + { + hshTvoid_node *linear_node, *hash_node; + + linear_node = _hshFvoid_raw_find_linear(list, name, name_len); + hash_node = _hshFvoid_raw_find_hash(list, name, name_len); + + + assert(linear_node == hash_node); + + node = hash_node; + } +#else + if (list->count <= LINEAR_SEARCH_MAX_COUNT) { + node = _hshFvoid_raw_find_linear(list, name, name_len); + } else { + node = _hshFvoid_raw_find_hash(list, name, name_len); + } +#endif + + return (node); +} + +void *hshFvoid_find(hshTvoid_list * list, const char *name) +{ + return hshFvoid_raw_find(list, name, strlen(name)); +} + +void *hshFvoid_int_find(hshTvoid_list * list, int key) +{ + return hshFvoid_raw_find(list, (char *) &key, sizeof(int)); +} + +void *hshFvoid_raw_find(hshTvoid_list * list, const char *name, + size_t name_len) +{ + hshTvoid_node *node; + + assert(list != NULL); + assert(name != NULL); + + node = _hshFvoid_raw_find(list, name, name_len); + if (node == NULL) + return node; + return node->data; +} + +int hshFvoid_contains(hshTvoid_list * list, const char *key) +{ + hshTvoid_node *node = _hshFvoid_raw_find(list, key, strlen(key)); + + if (node != NULL) { + return (1); + } else { + return (0); + } +} + +int hshFvoid_int_contains(hshTvoid_list * list, int key) +{ + hshTvoid_node *node = + _hshFvoid_raw_find(list, (char *) &key, sizeof(int)); + + if (node != NULL) { + return (1); + } else { + return (0); + } +} + +static void _hshFvoid_node_free(hshTvoid_list * list, hshTvoid_node * node, + int free_data) +{ + assert(node->name != NULL); + assert(node->data != NULL); + + if (free_data && list->destructor != NULL && node->data != NULL) { + list->destructor(node->data); + } + if (list->name_destructor != NULL && node->name != NULL) { + list->name_destructor(node->name); + } + free(node); +} + +void hshFvoid_del(hshTvoid_list * list, const char *name) +{ + hshFvoid_raw_del(list, name, strlen(name)); +} + +void hshFvoid_int_del(hshTvoid_list * list, int key) +{ + hshFvoid_raw_del(list, (char *) &key, sizeof(int)); +} + +void hshFvoid_raw_del(hshTvoid_list * list, const char *name, + size_t name_len) +{ + _hshFvoid_raw_remove(list, name, name_len, 1); +} + +void *hshFvoid_remove(hshTvoid_list * list, const char *name) +{ + return (hshFvoid_raw_remove(list, name, strlen(name))); +} + +void *hshFvoid_int_remove(hshTvoid_list * list, int key) +{ + return (hshFvoid_raw_remove(list, (char *) &key, sizeof(int))); +} + +void *hshFvoid_raw_remove(hshTvoid_list * list, const char *name, + size_t name_len) +{ + return (_hshFvoid_raw_remove(list, name, name_len, 0)); +} + +static void *_hshFvoid_raw_remove(hshTvoid_list * list, const char *name, + size_t name_len, int free_value) +{ + hshTvoid_node *p, *last; + unsigned short int hash; + void *data = NULL; + + assert(list != NULL); + assert(name != NULL); + + hash = hshFraw_hash(name, name_len, list->size); + + list->serial++; + + if (list->nodes[hash] == NULL) + return (NULL); + + for (p = last = list->nodes[hash]; p != NULL; last = p, p = p->next) { + if (p->name_len == name_len && + list->name_comparator(p->name, name, name_len) == 0) { + if (list->nodes[hash] == p) { + /* First entry */ + list->nodes[hash] = p->next; + break; + } else { + last->next = p->next; + break; + } + } + } + + if (p != NULL) { + if (free_value) { + data = NULL; + } else { + data = p->data; + } + + _hshFvoid_node_free(list, p, free_value); + + list->count--; + } + return (data); +} + +void hshFvoid_free(hshTvoid_list *list) { + hshFvoid_destroy(list); +} + +/* DEPRECATED */ +void hshFvoid_destroy(hshTvoid_list * list) +{ + size_t i = 0; + + for (i = 0; i < list->size; i++) { + hshTvoid_node *node = list->nodes[i]; + + while (node != NULL) { + hshTvoid_node *next = node->next; + + _hshFvoid_node_free(list, node, 1); + + node = next; + } + } + + free(list->nodes); + + free(list); +} + + +hshTiterator *hshFiterator_init(hshTvoid_list * list) +{ + hshTiterator *it; + + assert(list != NULL); + + it = (hshTiterator *) malloc(sizeof(hshTiterator)); + + it->list = list; + it->count = 0; + it->serial = list->serial; + it->node = NULL; + + return it; + +} + +int hshFiterator_next(hshTiterator * iterator) +{ + assert(iterator != NULL); + + if (iterator->serial != iterator->list->serial) + return -2; + + if (iterator->node != NULL) { + if (iterator->node->next != NULL) { + iterator->node = iterator->node->next; + return 1; + } else { + iterator->count++; + iterator->node = NULL; + } + } + for (; iterator->count < iterator->list->size; iterator->count++) { + iterator->node = iterator->list->nodes[iterator->count]; + if (iterator->node == NULL) + continue; + return 1; + } + + return 0; +} + +void *hshFiterator_current_key(hshTiterator * iterator) +{ + assert(iterator != NULL); + assert(iterator->node != NULL); + + return iterator->node->name; +} + +void *hshFiterator_current_value(hshTiterator * iterator) +{ + assert(iterator != NULL); + assert(iterator->node->data != NULL); + + return iterator->node->data; +} + + +void hshFiterator_free(hshTiterator * iterator) +{ + assert(iterator != NULL); + + free(iterator); +} + +void hshFiterator_reset(hshTiterator * iterator) +{ + iterator->count = 0; + iterator->serial = iterator->list->serial; + iterator->node = NULL; +} + +dynTstring *hshFdiag_output(hshTvoid_list * list) +{ + dynTstring *string = dynFinit(); + + dynFappend_print(string, "hash diag %p:\n", list); + + dynFappend_print(string, " serial: %d size: %d count: %d\n", + list->serial, list->size, list->count); + + dynFappend_print(string, + " load_factor: %.2f collisions: %d threshold: %d\n", + list->load_factor, list->collisions, list->threshold); + + dynFsappend(string, " elems:\n"); + + { + unsigned int i; + + for (i = 0; i < list->size; i++) { + hshTvoid_node *node; + + for (node = list->nodes[i]; node != NULL; node = node->next) { + dynFappend_print(string, " %d] %s: hashcode: %d\n", + i, node->name, node->hashcode); + } + } + } + + return (string); +} + +/* + * 32 bit magic FNV-1a prime + */ +#define FNV_32_PRIME ((uint32_t)0x01000193) +#define FNV1_32_INIT ((uint32_t)0x811c9dc5) +#define FNV1_32A_INIT FNV1_32_INIT + +uint32_t hshFraw_hash32(const void *buf, size_t len, uint32_t buckets) +{ + return hshFraw_hashcode32(buf, len) % buckets; +} + +/* + * fnv_32a_buf - perform a 32 bit Fowler/Noll/Vo FNV-1a hash on a buffer + * + * input: buf - start of buffer to hash len - length of buffer in octets + * hval - previous hash value or 0 if first call + * + * returns: 32 bit hash as a static hash type + * + * NOTE: To use the recommended 32 bit FNV-1a hash, use FNV1_32A_INIT as the + * hval arg on the first call to either fnv_32a_buf() or fnv_32a_str(). + */ +uint32_t hshFraw_hashcode32(const void *buf, size_t len) +{ + uint32_t hval = FNV1_32A_INIT; + unsigned char *bp = (unsigned char *) buf; /* start of buffer */ + unsigned char *be = bp + len; /* beyond end of buffer */ + + /* + * FNV-1a hash each octet in the buffer + */ + while (bp < be) { + + /* xor the bottom with the current octet */ + hval ^= (uint32_t) * bp++; + + /* multiply by the 32 bit FNV magic prime mod 2^32 */ +#if defined(NO_FNV_GCC_OPTIMIZATION) + hval *= FNV_32_PRIME; +#else + hval += + (hval << 1) + (hval << 4) + (hval << 7) + (hval << 8) + + (hval << 24); +#endif + } + + /* return our new hash value */ + return hval; +} + + +/* + * fnv_32a_str - perform a 32 bit Fowler/Noll/Vo FNV-1a hash on a string + * + * input: str - string to hash hval - previous hash value or 0 if first + * call + * + * returns: 32 bit hash as a static hash type + * + * NOTE: To use the recommended 32 bit FNV-1a hash, use FNV1_32A_INIT as the + * hval arg on the first call to either fnv_32a_buf() or fnv_32a_str(). + */ +uint32_t hshFhash32(const char *str) +{ + uint32_t hval = FNV1_32A_INIT; + unsigned char *s = (unsigned char *) str; /* unsigned string */ + + /* + * FNV-1a hash each octet in the buffer + */ + while (*s) { + + /* xor the bottom with the current octet */ + hval ^= (uint32_t) * s++; + + /* multiply by the 32 bit FNV magic prime mod 2^32 */ +#if defined(NO_FNV_GCC_OPTIMIZATION) + hval *= FNV_32_PRIME; +#else + hval += + (hval << 1) + (hval << 4) + (hval << 7) + (hval << 8) + + (hval << 24); +#endif + } + + /* return our new hash value */ + return hval; +} diff --git a/lc-continuity/mk4/continuity/mecha/hsh_dep.c b/lc-continuity/mk4/continuity/mecha/hsh_dep.c new file mode 100644 index 0000000000000000000000000000000000000000..7bc812dea26c025f29d1cb04d263770c06a60fe6 --- /dev/null +++ b/lc-continuity/mk4/continuity/mecha/hsh_dep.c @@ -0,0 +1,267 @@ +/* + * $Header: /cvsroot/csrc/continuity/mecha/hsh_dep.c,v 1.7 2004/01/23 + * 15:38:14 aleigh Exp $ + */ + +/* + * Copyright (c) 1994, 2004 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Use, disclosure, copying, distribution, or transmission of this code without + * express permission is prohibited. + */ + +/* + * TA/hashlist general purpose hasing algorithm system. Alex Leigh, + * 1994,1997,1999, 2000 $Id: hsh_dep.c,v 1.9 2004/03/18 15:04:15 aleigh Exp $ + */ + +/* + * hsh provides a general purpose, efficient data storage and retrieval + * system. The alogrithm can store an arbitrary list of sequential + * name/keyvalue pairs, each list being keyed by a character string. + * + */ + +#include "../include/csys.h" + +struct hshSentry { + char *name; + char *value; + struct hshSentry *next; +}; +typedef struct hshSentry hshTentry; + +struct hshSnode { + struct hshSentry *entry; + char *name; + struct hshSnode *next; +}; +typedef struct hshSnode hshTnode; + +struct hshShash { + struct hshSnode *t; +}; +typedef struct hshShash hshThash; + +struct hshSlist { + struct hshSnode *nodes[65536]; + int ref; +}; +typedef struct hshSlist hshTlist; + +#define _HSH_DEP_C +#include "../include/mecha.h" + +/***************** + * Tradidtional hash list implementation DEPRECATED + * This interface has worked well for a long time, but was originally + * designed to do something else, as evidenced by all the now + * reundant structures. Use of the void interface is therefore + * encouraged. + *****************/ + +hshTnode *hshFlist_node_find(hshTlist * list, char *name) +{ + return list->nodes[hshFhash(name)]; +} + +/* + * Search a node for a given entry and return a pointer to it. + */ +hshTentry *hshFnode_find_entry(hshTnode * node, char *str) +{ + hshTentry *e; + + if (node->entry == NULL) + return NULL; + + e = node->entry; + + while (1) { + if (strcmp(str, e->name) == 0) + return e; + if (e->next == NULL) + break; + e = e->next; + } + return NULL; +} + +hshTentry *hshFlist_find_entry(hshTlist * list, char *nname, char *ename) +{ + hshTnode *n; + hshTentry *e; + + n = (hshTnode *) hshFlist_node_find(list, nname); + + + if (n == NULL) + return NULL; + + e = (hshTentry *) hshFnode_find_entry(n, ename); + + return e; + +} + +char *hshFnode_find_value(hshTnode * node, char *str) +{ + hshTentry *e; + + + e = hshFnode_find_entry(node, str); + if (e == NULL) + return NULL; + return e->value; +} + +/* + * aleigh- Free a hashlist entry structure. The structure should already be + * unreferenced, or you'll break any pre-existing references to it. + */ +void hshFentry_free(hshTentry * entry) +{ + if (entry->name != NULL) + free(entry->name); + if (entry->value != NULL) + free(entry->value); + free(entry); +} + +/* + * aleigh- Free a node, and any entries that may be associated with it. You + * better be sure all the references are gone to the node. + */ +void hshFnode_free(hshTnode * node) +{ + hshTentry *p, *np = NULL; + + p = node->entry; + + while (1) { + if (p == NULL) + break; + np = p->next; + hshFentry_free(p); + p = np; + } + + if (node->entry != NULL) + hshFentry_free(node->entry); + free(node); +} + +/* + * aleigh- Create a hash node out of system memory via malloc(). The node is + * the root unit of the hashlist. + */ +hshTnode *hshFnode_create(char *name) +{ + hshTnode *n; + + n = (hshTnode *) malloc(sizeof(hshTnode)); + /* memFclear(n, sizeof(hshTnode)); */ + memFclear(n, sizeof(hshTnode)); + + n->name = (char *) malloc(strlen(name) + 1); + memFclear(n->name, strlen(name) + 1); + memFcopy(name, n->name, strlen(name)); + + return n; +} + +void hshFnode_entry_add(hshTnode * n, hshTentry * e) +{ + e->next = n->entry; + n->entry = e; +} + +hshTnode *hshFnode_entry_alloc(void) +{ + hshTnode *n; + + n = (hshTnode *) malloc(sizeof(hshTnode)); + memFclear(n, sizeof(hshTnode)); + + return n; +} + +hshTentry *hshFnode_entry_insert(hshTnode * node, char *n, char *v) +{ + hshTentry *e; + + e = (hshTentry *) malloc(sizeof(hshTentry)); + memFclear(e, sizeof(hshTentry)); + + e->name = (char *) malloc(strlen(n) + 1); + memFclear(e->name, strlen(n) + 1); + e->value = (char *) malloc(strlen(v) + 1); + memFclear(e->value, strlen(v) + 1); + + memFcopy(n, e->name, strlen(n)); + memFcopy(v, e->value, strlen(v)); + + hshFnode_entry_add(node, e); + + return e; +} + +hshTentry *hshFlist_entry_insert(hshTlist * list, char *l, char *n, + char *v) +{ + hshTnode *node; + hshTentry *entry; + + node = hshFlist_node_find(list, l); + if (node == NULL) { + node = hshFnode_create(l); + hshFlist_node_add(list, node); + } + entry = hshFnode_entry_insert(node, n, v); + + return entry; +} + +hshTlist *hshFlist_create(void) +{ + hshTlist *p; + + p = (hshTlist *) malloc(sizeof(hshTlist)); + memFclear(p, sizeof(hshTlist)); + /* memFclear(p, sizeof(hshTlist)); */ + + return p; +} + +void hshFlist_node_add(hshTlist * list, hshTnode * node) +{ + unsigned int hash; + + hash = hshFhash(node->name); + + if (list->nodes[hash] == NULL) { + list->nodes[hash] = node; + } else { + node->next = list->nodes[hash]; + list->nodes[hash] = node; + } +} + +void hashFlist_dump(hshTlist * list, unsigned int len) +{ + struct hshSnode *n; + size_t i; + + for (i = 0; i < len; i++) { + n = list->nodes[i]; + if (n->name == NULL) { + printf("node %d - (NULL)\n", i); + } else { + printf("node %d - %s\n", i, n->name); + } + } +} diff --git a/lc-continuity/mk4/continuity/mecha/log.c b/lc-continuity/mk4/continuity/mecha/log.c new file mode 100644 index 0000000000000000000000000000000000000000..edaa2d27192f30d5b247a7b6e7e3e0f4f1cc78b9 --- /dev/null +++ b/lc-continuity/mk4/continuity/mecha/log.c @@ -0,0 +1,254 @@ +/* + * $Header: /san01/cvs/ashpool/csrc/continuity/mecha/Attic/log.c,v 1.8 2004/04/30 13:41:56 aleigh Exp $ + */ + +/* + * Copyright (c) 1994, 2004 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Disclosure, copying, distribution, or transmission of of this code without + * express permission is prohibited. + */ + +#include "mecha.h" + +#define _LOG_ROTATECOUNT 5 +#define _LOG_ROTATETHRESH 100 + +static FILE *logGoutfh; + +/* Should we fclose() the filehandle? 0 for stdout */ +static int logGshould_close=0; + +static int logGwritten=0; + +/* The output filename if not stdout */ +static char *logGoutfn=NULL; + +static pthread_mutex_t logLrotate=PTHREAD_MUTEX_INITIALIZER; + +/* The size all the log files will be allowed to grow to, in + * bytes. Each individual log file will then rotate at around + * (logGrotatesize/_LOG_ROTATECOUNT) + */ +static size_t logGrotatesize=0; + +static void logFrotate_check(void); +void logFoutputfh_set(FILE *fh, int close_flag); + +const char *messages[] = { + "Unknown Internal Error", + "Interrupt handler caught signal, Exiting.", + "Could not open module configuration file. Exiting.", + "Calling 3rd party dispatcher. [d: %s]", + "Unable to map 3rd party dispatcher. [d: %s]", + "netFipv4_listen_tcp failed. [e: %d]", + /* 5 */ + "Starting IPv4 listen loop. [tid: 0x%x] [handler: 0x%x]", + "lsnFipv4_listen_loop: accept() took EINTR.", + "lsnFipv4_listen_loop: accept: %s", + "Thread pool full. Closing connection.", + "Thread pool created. [threads: %d] [queue: %d] [blocking: %d]", + /* 10 */ + "dlFread_entry: sscanf() returned other than 2. [s: %d] [e: %d]", + "stat() failed. [f: %s] [e: %d]", + "Internal Error: %s", + "open() failed. [f: %s] [e: %d]", + "Memory exhausted: %s", + /* 15 */ + "mmap() failed. [e: %d] %s", + "read() failed. [e: %d] %s", + "munmap() failed. [e: %d] %s", + "write() failed. [e: %d] %s" +}; + +static int logFreopen(void); + +void logFinit(void) { + logGoutfh=stdout; +} + +static void logFrotate_check(void) { + size_t filesize; + static int working=0; + + if(logGwritten<_LOG_ROTATETHRESH || working==1) { + return; + } + + if(logGrotatesize==0||logGoutfn==NULL) { + return; + } + + pthread_mutex_lock(&logLrotate); + + /* The point of this is to just help prevent other threads + * from backing up and trying to acquire the lock when we are clearly + * on the case. + */ + working=1; + + filesize=fleFget_size(logGoutfn); + + if(filesize>(logGrotatesize/_LOG_ROTATECOUNT)) { + fleFrotate(_LOG_ROTATECOUNT,logGoutfn); + logFreopen(); + logGwritten=0; + } + + logGwritten=0; + + pthread_mutex_unlock(&logLrotate); + + working=0; +} + +void logFset_rotatesize(size_t size) { + logGrotatesize=size; +} + +static int logFreopen(void) { + FILE *fh; + + assert(logGoutfn!=NULL); + + fh=fopen(logGoutfn,"a"); + if(fh==NULL) { + return -1; + } + + logFoutputfh_set(fh,logGshould_close); + + return 0; +} + +/* + * MT UNSAFE + */ +int logFset_outputfile(const char *filename) { + FILE *nh; + + assert(filename!=NULL); + + nh=fopen(filename,"a"); + if(nh==NULL) { + return -1; + } + + logFoutputfh_set(nh,logGshould_close); + logGoutfn=strFcopy(filename); + + assert(logGoutfn!=NULL); + + logGshould_close=1; + + return 0; +} + +/* + * MT Safe; result is volitile + */ +FILE *logFoutputfh_get(void) { + return logGoutfh; +} + +/* + * MT Unsafe + */ +void logFoutputfh_set(FILE *fh, int close_flag) { + FILE *oldfh = logGoutfh; + + logGoutfh=fh; + + /* We do it this way to minimize the race */ + if(close_flag==1) { + fclose(oldfh); + } +} + +/* + * MT Safe + */ +void logFmsgid(int level, const char *module, int msg_id, ...) +{ + va_list ap; + const char *m = messages[msg_id]; + + va_start(ap, msg_id); + + logGwritten++; + logFrotate_check(); + + switch (level) { + case 0: + fprintf(logGoutfh,"%s/ OK: %s-%05d ", utlFlocal_time(), module, msg_id); + vfprintf(logGoutfh,m, ap); + fprintf(logGoutfh,"\n"); + fflush(logGoutfh); + break; + case 1: + fprintf(logGoutfh,"%s/WARN: %s-%05d ", utlFlocal_time(), module, msg_id); + vfprintf(logGoutfh,m, ap); + fprintf(logGoutfh,"\n"); + fflush(logGoutfh); + break; + case 2: + fprintf(logGoutfh,"%s/ ERR: %s-%05d ", utlFlocal_time(), module, msg_id); + vfprintf(logGoutfh,m, ap); + fprintf(logGoutfh,"\n"); + fflush(logGoutfh); + break; + case 3: + fprintf(logGoutfh,"%s/DIAG: %s-%05d ", utlFlocal_time(), module, msg_id); + vfprintf(logGoutfh,m, ap); + fprintf(logGoutfh,"\n"); + fflush(logGoutfh); + break; + } +} + +/* + * MT Safe + */ +void logF_msg(const char *func, int level, const char *m, ...) +{ + va_list ap; + + logGwritten++; + logFrotate_check(); + + va_start(ap, m); + + switch (level) { + case 0: + fprintf(logGoutfh, "%s/ OK: %s: ", utlFlocal_time(), func); + vfprintf(logGoutfh,m, ap); + fprintf(logGoutfh,"\n"); + fflush(logGoutfh); + break; + + case 1: + fprintf(logGoutfh,"%s/WARN: %s: ", utlFlocal_time(), func); + vfprintf(logGoutfh,m, ap); + fprintf(logGoutfh,"\n"); + fflush(logGoutfh); + break; + + case 2: + fprintf(logGoutfh,"%s/ ERR: %s: ", utlFlocal_time(), func); + vfprintf(logGoutfh,m, ap); + fprintf(logGoutfh,"\n"); + fflush(logGoutfh); + break; + + case 3: + fprintf(logGoutfh,"%s/DIAG: %s: ", utlFlocal_time(), func); + vfprintf(logGoutfh,m, ap); + fprintf(logGoutfh,"\n"); + fflush(logGoutfh); + break; + } +} diff --git a/lc-continuity/mk4/continuity/mecha/lst.c b/lc-continuity/mk4/continuity/mecha/lst.c new file mode 100644 index 0000000000000000000000000000000000000000..1d69155817be26b4cea97bf72ed7cf956cc96c4a --- /dev/null +++ b/lc-continuity/mk4/continuity/mecha/lst.c @@ -0,0 +1,701 @@ +/* + * $Header: /san01/cvs/ashpool/csrc/continuity/mecha/Attic/lst.c,v 1.31 2004/04/30 13:41:56 aleigh Exp $ + */ + +/* + * Copyright (c) 1994, 2004 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Disclosure, copying, distribution, or transmission of this code without + * express permission is prohibited. + */ + +#include "mecha.h" + +#define FALSE 0 +#define TRUE 1 + +#define STREQ(a,b) (((*a) == (*b)) && (strcmp((a),(b)) == 0)) +#define STRIEQ(a,b) (strcasecmp((a),(b)) == 0) + +#include "lst.h" + +static int lstFset_find_cmp_len(const lstTset * set, const char *key, + int key_len, int (*cmp) (const char *s1, + const char *s2)); + +void lstFset_bupdate(lstTset * set, const char *key, size_t key_len, + const char *value, size_t value_len) +{ + assert(set != NULL); + assert(key != NULL); + assert(value != NULL); + + lstFset_delete_key(set, key); + lstFset_badd(set, key, key_len, value, value_len); +} + +void lstFset_update(lstTset * set, const char *key, const char *value) +{ + assert(set != NULL); + assert(key != NULL); + assert(value != NULL); + + lstFset_delete_key(set, key); + lstFset_add(set, key, value); +} + +lstTset *lstFset_init(void) +{ + lstTset *s; + + s = (lstTset *) malloc(sizeof(lstTset)); + + assert(s != NULL); + + memFclear(s, sizeof(lstTset)); + + return s; +} + +lstTset *lstFset_create(const char *name) +{ + lstTset *s; + + s = (lstTset *) malloc(sizeof(lstTset)); + + assert(s != NULL); + + s->size = 0; + s->maxsize = 10; /* default set size */ + + if (name != NULL) + s->name = strFcopy(name); + + s->fields = (lstTfield *) malloc(sizeof(lstTfield) * s->maxsize); + + assert(s->fields != NULL); + + memFclear(s->fields, sizeof(lstTfield) * s->maxsize); + + return s; +} + +void lstFset_free(lstTset * set) +{ + int i; + + if (set != NULL) { + if (set->fields != NULL) { + for (i = 0; i < set->size; i++) { + if (set->fields[i].name != NULL) + free(set->fields[i].name); + if (set->fields[i].value != NULL) + free(set->fields[i].value); + } + free(set->fields); + } + if (set->name != NULL) + free(set->name); + free(set); + } +} + +int lstFset_add(lstTset * set, const char *key, const char *value) +{ + int idx; + + assert(set != NULL); + assert(key != NULL); + + if (value == NULL) { + return -1; + } + idx = set->size; + set->size++; + + if (set->size >= set->maxsize) { + set->maxsize = set->size * 2; + set->fields = + (lstTfield *) realloc(set->fields, + sizeof(lstTfield) * set->maxsize); + } + /* initialize values */ + set->fields[idx].n_len = 0; + set->fields[idx].v_len = 0; + + set->fields[idx].name = strFcopy_size(key, &set->fields[idx].n_len); + set->fields[idx].value = strFcopy_size(value, &set->fields[idx].v_len); + + return idx; +} + + +int lstFset_badd(lstTset * set, const char *key, size_t key_len, + const char *value, size_t value_len) +{ + int idx; + + assert(set != NULL); + assert(key != NULL); + + if (value == NULL) { + return -1; + } + idx = set->size; + set->size++; + + if (set->size >= set->maxsize) { + set->maxsize = set->size * 2; + set->fields = + (lstTfield *) realloc(set->fields, + sizeof(lstTfield) * set->maxsize); + } + set->fields[idx].name = (char *) memFdup(key, key_len); + set->fields[idx].n_len = key_len; + set->fields[idx].value = (char *) memFdup(value, value_len); + set->fields[idx].v_len = value_len; + + return idx; +} + +int lstFset_nadd(lstTset * set, const char *key, int value) +{ + char buf[16]; + + assert(set != NULL); + assert(key != NULL); + + snprintf(buf, sizeof(buf), "%d", value); + return lstFset_add(set, key, buf); +} + + +int lstFset_unique_cmp(lstTset * set, const char *key, + int (*cmp) (const char *s1, const char *s2)) +{ + int i; + char *name; + int found; + + assert(set != NULL); + assert(key != NULL); + assert(cmp != NULL); + + found = 0; + for (i = 0; i < set->size; ++i) { + name = set->fields[i].name; + if ((key == NULL && name == NULL) || + (key != NULL && name != NULL && ((*cmp) (key, name)) == 0)) { + + if (found) { + return FALSE; + } + found = 1; + } + } + return TRUE; +} + +const char *lstFset_get_index(lstTset * set, int idx) +{ + assert(set != NULL); + if (idx >= set->size) + return NULL; + return set->fields[idx].value; +} + +const char *lstFset_get_key_index(lstTset * set, int idx) +{ + assert(set != NULL); + if (idx >= set->size) + return NULL; + return set->fields[idx].name; +} + +int lstFset_find_cmp(const lstTset * set, const char *key, + int (*cmp) (const char *s1, const char *s2)) +{ + int i; + + assert(set != NULL); + assert(key != NULL); + assert(cmp != NULL); + + for (i = 0; i < set->size; ++i) { + char *name = set->fields[i].name; + + if ((key == NULL && name == NULL) || + (key != NULL && name != NULL && ((*cmp) (key, name)) == 0)) { + + return i; + } + } + + return -1; +} + +static int lstFset_find_cmp_len(const lstTset * set, const char *key, + int key_len, int (*cmp) (const char *s1, + const char *s2)) +{ + int i; + + assert(set != NULL); + assert(key != NULL); + assert(cmp != NULL); + + for (i = 0; i < set->size; ++i) { + char *name = set->fields[i].name; + int name_len = set->fields[i].n_len; + + if ((key == NULL && name == NULL) || + (key != NULL && name != NULL && + key_len == name_len && ((*cmp) (key, name)) == 0)) { + + return i; + } + } + + return -1; +} + + +const char *lstFset_get_cmp(const lstTset * set, const char *key, + int (*cmp) (const char *s1, const char *s2)) +{ + int i; + + if (set == NULL) + return NULL; + + assert(key != NULL); + assert(cmp != NULL); + + i = lstFset_find_cmp(set, key, cmp); + + if (i == -1) + return NULL; + + return set->fields[i].value; +} + + +size_t lstFset_get_vsize_cmp(lstTset * set, const char *key, + int (*cmp) (const char *s1, const char *s2)) +{ + int i; + + i = lstFset_find_cmp(set, key, cmp); + if (i == -1) + return -1; + + return set->fields[i].v_len; +} + +size_t lstFset_get_nsize_cmp(lstTset * set, const char *key, + int (*cmp) (const char *s1, const char *s2)) +{ + int i; + + i = lstFset_find_cmp(set, key, cmp); + if (i == -1) + return -1; + + return set->fields[i].n_len; +} + +/* Check to see if a key in a set is unique (case sensitive) */ +int lstFset_unique(lstTset * set, const char *key) +{ + return lstFset_unique_cmp(set, key, + (int (*)(const char *, const char *)) + strcmp); +} + +/* Check if a key in a set is unique (case insensitive) */ +int lstFset_inique(lstTset * set, const char *key) +{ + return lstFset_unique_cmp(set, key, + (int (*)(const char *, const char *)) + strcasecmp); +} + +/* Locate the idx of a field in a set (sensitive) */ +int lstFset_find(lstTset * set, const char *key) +{ + return lstFset_find_cmp(set, key, + (int (*)(const char *, const char *)) strcmp); +} + +/* Locate the idx of a field in a set (insensitive) */ +int lstFset_ifind(lstTset * set, const char *key) +{ + return lstFset_find_cmp(set, key, + (int (*)(const char *, const char *)) + strcasecmp); +} + +/* Return the value associated with a key, sensitive */ +const char *lstFset_get(const lstTset * set, const char *key) +{ + return lstFset_get_cmp(set, key, + (int (*)(const char *, const char *)) strcmp); +} + +ssize_t lstFset_get_vsize(lstTset * set, const char *key) +{ + return lstFset_get_vsize_cmp(set, key, + (int (*)(const char *, const char *)) + strcmp); +} + +ssize_t lstFset_get_nsize(lstTset * set, const char *key) +{ + return lstFset_get_nsize_cmp(set, key, + (int (*)(const char *, const char *)) + strcmp); +} + +const lstTfield *lstFset_get_field(lstTset * set, const char *key, + int key_len) +{ + int i; + + if (set == NULL) + return NULL; + + assert(key != NULL); + + i = lstFset_find_cmp_len(set, key, key_len, strcmp); + + if (i == -1) + return NULL; + + return ((const lstTfield *) &set->fields[i]); +} + +/* Return the value associated with a key, insensitive */ +const char *lstFset_iget(lstTset * set, const char *key) +{ + return lstFset_get_cmp(set, key, + (int (*)(const char *, const char *)) + strcasecmp); +} + +/* Remove all tuples after 'size' */ +void lstFset_trunc(lstTset * set, int size) +{ + if (size < set->size) { + int i; + + for (i = size; i < set->size; i++) { + free(set->fields[i].name); + free(set->fields[i].value); + } + set->size = size; + } +} + +/* Delete a tuple from a set */ +void lstFset_delete(lstTset * set, int idx) +{ + if ((idx != -1) && (idx < set->size)) { + free(set->fields[idx].name); + free(set->fields[idx].value); + + set->fields[idx].name = set->fields[set->size - 1].name; + set->fields[idx].n_len = set->fields[set->size - 1].n_len; + set->fields[idx].value = set->fields[set->size - 1].value; + set->fields[idx].v_len = set->fields[set->size - 1].v_len; + + set->size--; + } +} + +/* Set the value for a given tuple */ +void lstFset_add_value(lstTset * set, int idx, const char *value) +{ + if ((idx != -1) && (idx < set->size)) { + free(set->fields[idx].value); + if (*value == 0) + set->fields[idx].value = strFcopy("(null)"); + else + set->fields[idx].value = strFcopy(value); + } +} + + +void lstFset_delete_key(lstTset * set, const char *key) +{ + lstFset_delete(set, lstFset_find(set, key)); +} + +void lstFset_idelete_key(lstTset * set, const char *key) +{ + lstFset_delete(set, lstFset_ifind(set, key)); +} + +lstTset *lstFset_list_find(lstTset ** sets, const char *name) +{ + while (*sets != NULL) { + if (name == NULL) { + if ((*sets)->name == NULL) { + return (*sets); + } + } else { + if ((*sets)->name != NULL && STREQ((*sets)->name, name)) { + + return (*sets); + } + } + ++sets; + } + return NULL; +} + +/* + * You could be outside, right now. + */ + +void lstFset_list_free(lstTset * sets) +{ + lstTset **s; + + s = (lstTset **) sets; + while (*s != NULL) { + lstFset_free((lstTset *) * s); + s++; + } + free(sets); +} + +void lstFset_merge(lstTset * high, const lstTset * low) +{ + int i, j; + + for (i = 0; i < low->size; ++i) { + j = lstFset_find(high, low->fields[i].name); + if (j == -1) { + lstFset_add(high, low->fields[i].name, low->fields[i].value); + } + } +} + +/* + * return the size, in bytes, of all the name and value data without the list + * overhead. + */ +int lstFset_size(const lstTset * set) +{ + int i; + int size = 0; + + if (set->size == 0) + return 0; + + /* Calculate the size of the list */ + for (i = 0; i < set->size; i++) { + if (set->fields[i].value != NULL && set->fields[i].name != NULL) { + size += strlen(set->fields[i].value); + size += strlen(set->fields[i].name); + } + } + + return size; + +} + +/* + * Return the physical idx location of the nth item in the list. + */ +int lstFnth_find(const lstTset * list, int nth) +{ + int i; + int found = -1; + + for (i = 0; i < list->size; i++) { + if (list->fields[i].name != NULL && list->fields[i].value != NULL) + found++; + if (found == nth) + return i; + } + return -1; +} + +const char *lstFfield_value(const lstTfield * field) +{ + return (field->value); +} + +int lstFfield_value_len(const lstTfield * field) +{ + return (field->v_len); +} + + +/********************************************************/ + +/* + * This code originates with the TA/Velocity telemetry engine. The packs were + * used to transfer lists of telemetry elements between hosts, but, they have + * far more potential general use. + */ + + +#define TA_INT8 1 +#define TA_INT16 2 +#define TA_CHAR8 3 +#define TA_MARKER 4 + +struct pckSelem { + uint16_t len; + uint8_t class; +}; + +int lstFpack(char *dest, char *src, int len, int class) +{ + char *wp; + struct pckSelem bar; + + wp = dest; + + memFclear(&bar,sizeof(struct pckSelem)); + + bar.len = len; + bar.class = class; + + memFcopy(&bar, wp, sizeof(struct pckSelem)); + wp += sizeof(struct pckSelem); + + memFcopy(src, wp, len); + + return len + sizeof(struct pckSelem); +} + +/* + * mowin down MC's, like I'm mowin the lawn but now, I'd like to ask you how, + * you like the feel of the bass in your face in the crowd + */ + +void lstFset_dump(char *pack) +{ + char *pp; + struct pckSelem bar; + + pp = pack; + + while (1) { + memFcopy(pp, &bar, sizeof(struct pckSelem)); + pp += sizeof(struct pckSelem); + + printf("len: %d class: %d\n", bar.len, bar.class); + if (bar.class == TA_MARKER) + break; + pp += bar.len; + } +} + +/* + * It's not paranoia to think that everyone is out to get you. They are, + * that's just common sense. Paranoia is thinking that they are conspiring. + */ + +lstTset *lstFset_unpack(const char *pack) +{ + const char *pp; + struct pckSelem bar; + char nbuf[256], vbuf[256]; + lstTset *set; + + pp = pack; + + set = lstFset_create("pack"); + + while (1) { + memFcopy(pp, &bar, sizeof(struct pckSelem)); + if (bar.class == TA_MARKER) + break; + pp += sizeof(struct pckSelem); + + memFclear(&nbuf, 256); /* TODO: lame */ + memFcopy(pp, &nbuf, bar.len); + pp += bar.len; + + memFcopy(pp, &bar, sizeof(struct pckSelem)); + if (bar.class == TA_MARKER) + break; + pp += sizeof(struct pckSelem); + + memFclear(&vbuf, 256); /* TODO: lame */ + memFcopy(pp, &vbuf, bar.len); + pp += bar.len; + + lstFset_add(set, (char *) &nbuf, (char *) &vbuf); + } + + return set; +} + +/* + * Pack a set into a single message for transport. Returns the packed string + * in allocated space. + */ + +char *lstFset_pack(const lstTset * set, size_t * len) +{ + char *pack, *pp; + int i; + int size; + int ret; + struct pckSelem bar; + + assert(set!=NULL); + + size = lstFset_size(set); + + if (size == 0) + return NULL; + + /* + * The size of the pack is going to be the payload, plus four bytes per + * tuple + */ + + size += ((sizeof(struct pckSelem) * 2) * set->size); + size += sizeof(struct pckSelem); /* For marker */ + + /* 4 int 16 per tuple and 2int16 for marker */ + + pack = (char *) malloc(size); + + memFclear(pack, size); + + pp = pack; + + for (i = 0; i < set->size; i++) { + if (set->fields[i].name != NULL && set->fields[i].value != NULL) { + ret = + lstFpack(pp, set->fields[i].name, + strlen(set->fields[i].name), TA_CHAR8); + pp += ret; + ret = + lstFpack(pp, set->fields[i].value, + strlen(set->fields[i].value), TA_CHAR8); + pp += ret; + } + } + + /* Insert marker */ + memFclear(&bar,sizeof(struct pckSelem)); + bar.len = 0; + bar.class = TA_MARKER; + memFcopy(&bar, pp, sizeof(struct pckSelem)); + + *len = size; + + return pack; +} diff --git a/lc-continuity/mk4/continuity/mecha/lst.h b/lc-continuity/mk4/continuity/mecha/lst.h new file mode 100644 index 0000000000000000000000000000000000000000..98dab879c9365694a52b1a05d066507e452ac52f --- /dev/null +++ b/lc-continuity/mk4/continuity/mecha/lst.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 1994, 2003 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Use, disclosure, copying, distribution, or transmission of this code without + * express permission is prohibited. + */ + +#ifndef _LST_H +#define _LST_H + +struct lstSfield { + char *name; + char *value; + size_t n_len; + size_t v_len; +}; +/* typedef struct lstSfield lstTfield; */ + +struct lstSset { + char *name; + int size; + int maxsize; + lstTfield *fields; +}; + +#endif diff --git a/lc-continuity/mk4/continuity/mecha/lst_void.c b/lc-continuity/mk4/continuity/mecha/lst_void.c new file mode 100644 index 0000000000000000000000000000000000000000..d35aa5dd708add954d69f0907bea30910e99ba00 --- /dev/null +++ b/lc-continuity/mk4/continuity/mecha/lst_void.c @@ -0,0 +1,235 @@ +/* + * $Header: /san01/cvs/ashpool/csrc/continuity/mecha/Attic/lst_void.c,v 1.12 2004/04/30 13:41:56 aleigh Exp $ + */ + +/* + * Copyright (c) 1994, 2004 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Disclosure, copying, distribution, or transmission of this code without + * express permission is prohibited. + */ + +#include "mecha.h" + +struct lstSlist_elem { + void *data; + lstTlist_elem *next; + lstTlist_elem *prev; +}; + +struct lstSlist { + int size; + + void (*destroy) (void *); /* passed lstTlist_elem->data */ + + lstTlist_elem *head; + lstTlist_elem *tail; +}; + +/** Linked list code **/ + +/* + * Initialize a new linked list, with the destructor destory. + */ +void lstFlist_init(lstTlist * list, void (*destroy) (void *)) +{ + list->size = 0; + list->destroy = destroy; + + list->head = NULL; + list->tail = NULL; + + return; +} + +/* + * destroy the given list, freeing all memory + */ +void lstFlist_destroy(lstTlist * list) +{ + void *data; + + while (lstFlist_size(list) > 0) { + if (lstFlist_remove(list, lstFlist_tail(list), &data) == 0 && + list->destroy != NULL) + list->destroy(data); + } + + memFclear(list, sizeof(lstTlist)); +} + +/* + * THESE SHOULD REPLACE THE CURRENT INIT AND DESTROY FUNCTIONS + */ +lstTlist *lstFlist_create(void (*destroy) (void *)) +{ + lstTlist *list = malloc(sizeof(lstTlist)); + + lstFlist_init(list, destroy); + + return (list); +} + +void lstFlist_free(lstTlist * list) +{ + lstFlist_destroy(list); + + free(list); +} + +int lstFlist_add_next(lstTlist * list, lstTlist_elem * elem, void *data) +{ + lstTlist_elem *new_elem; + + if (lstFlist_size(list) != 0 && elem == NULL) + return (-1); + + new_elem = (lstTlist_elem *) malloc(sizeof(lstTlist_elem)); + + if (new_elem == NULL) + return (-1); + + new_elem->data = data; + + if (lstFlist_size(list) == 0) { + new_elem->next = new_elem->prev = NULL; + + list->head = list->tail = new_elem; + } else { + /* insert after elem */ + + new_elem->next = elem->next; + new_elem->prev = elem; + + if (elem->next == NULL) + list->tail = new_elem; + else + elem->next->prev = new_elem; + + elem->next = new_elem; + } + + list->size++; + + return (0); +} + +int lstFlist_add_prev(lstTlist * list, lstTlist_elem * elem, void *data) +{ + lstTlist_elem *new_elem; + + if (lstFlist_size(list) != 0 && elem == NULL) + return (-1); + + new_elem = (lstTlist_elem *) malloc(sizeof(lstTlist_elem)); + + if (new_elem == NULL) + return (-1); + + new_elem->data = data; + + if (lstFlist_size(list) == 0) { + new_elem->next = new_elem->prev = NULL; + + list->head = list->tail = new_elem; + } else { + /* insert before elem */ + + new_elem->prev = elem->prev; + new_elem->next = elem; + + if (elem->prev == NULL) + list->head = new_elem; + else + elem->prev->next = new_elem; + + elem->prev = new_elem; + } + + list->size++; + + return (0); +} + +int lstFlist_remove(lstTlist * list, lstTlist_elem * elem, void **data) +{ + if (lstFlist_size(list) == 0 || elem == NULL) + return (-1); + + if (data) + *data = elem->data; + + if (elem == list->head) { + list->head = elem->next; + + if (list->head == NULL) + list->tail = NULL; + else + list->head->prev = NULL; + } else { + elem->prev->next = elem->next; + + if (elem->next == NULL) + list->tail = elem->prev; + else + elem->next->prev = elem->prev; + } + + free(elem); + + list->size--; + + return (0); +} + +lstTlist_elem *lstFlist_next(lstTlist_elem * elem) +{ + return (elem->next); +} + +lstTlist_elem *lstFlist_prev(lstTlist_elem * elem) +{ + return (elem->prev); +} + +void *lstFlist_data(lstTlist_elem * elem) +{ + return (elem->data); +} + +int lstFlist_is_head(lstTlist * list, lstTlist_elem * elem) +{ + if (list->head == elem) { + return (1); + } else { + return (0); + } +} + +int lstFlist_is_tail(lstTlist * list, lstTlist_elem * elem) +{ + if (list->tail == elem) { + return (1); + } else { + return (0); + } +} + +lstTlist_elem *lstFlist_head(lstTlist * list) +{ + return (list->head); +} + +lstTlist_elem *lstFlist_tail(lstTlist * list) +{ + return (list->tail); +} + +int lstFlist_size(lstTlist * list) +{ + return (list->size); +} diff --git a/lc-continuity/mk4/continuity/mecha/mecha.c b/lc-continuity/mk4/continuity/mecha/mecha.c new file mode 100644 index 0000000000000000000000000000000000000000..3595d06b2f7f1438e3e462884e3aeb7997f7fff9 --- /dev/null +++ b/lc-continuity/mk4/continuity/mecha/mecha.c @@ -0,0 +1,9 @@ +#include "mecha.h" + +void mecha_init(void) { + logFinit(); + thrFmod_init(); + rndFinit(); + tlsFinit(); + +} diff --git a/lc-continuity/mk4/continuity/mecha/mem.c b/lc-continuity/mk4/continuity/mecha/mem.c new file mode 100644 index 0000000000000000000000000000000000000000..d32e11607e347255754ee0d8b4d362b0296860d0 --- /dev/null +++ b/lc-continuity/mk4/continuity/mecha/mem.c @@ -0,0 +1,35 @@ +/* + * $Header: /san01/cvs/ashpool/csrc/continuity/mecha/Attic/mem.c,v 1.9 2004/04/30 13:41:56 aleigh Exp $ + */ + +/* + * Copyright (c) 2004 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Disclosure, copying, distribution, or transmission of of this code without + * express permission is prohibited. + */ + +#include "mecha.h" + +void *memFdup(const void *p, size_t len) +{ + char *a; + + assert(p != NULL); + + /* add an extra byte to put a trailing NULL */ + a = malloc(len + 1); + + assert(a != NULL); + + memFcopy(p, a, len); + + /* add a trailing NULL incase this is a string */ + a[len] = 0; + + return a; +} diff --git a/lc-continuity/mk4/continuity/mecha/net.c b/lc-continuity/mk4/continuity/mecha/net.c new file mode 100644 index 0000000000000000000000000000000000000000..c0765708733d14a4f11d969a791c244b040475df --- /dev/null +++ b/lc-continuity/mk4/continuity/mecha/net.c @@ -0,0 +1,559 @@ +/* + * $Header: /san01/cvs/ashpool/csrc/continuity/mecha/Attic/net.c,v 1.14 2004/05/27 13:32:22 aleigh Exp $ + */ + +/* + * Copyright (c) 2004 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Use, disclosure, copying, distribution, or transmission of this code without + * express permission is prohibited. + */ + +#include "mecha.h" +#include "net.h" + +#define EAGAIN_TRYCOUNT 28 +#define EAGAIN_WAIT 15 + +ssize_t netFconn_writev(netTconn * conn, const struct iovec * iov,int iovcnt); + +int netFset_reuse(int sd) +{ + int reuse = 1; + + if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) != + 0) { + return -1; + } + return 0; +} + +int netFset_nodelay(int sd) +{ + int opt = 1; +#ifndef DARWIN + if (setsockopt(sd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt)) != 0) + return -1; +#endif + return 0; +} + +int netFipv4_listen_tcp(int port, unsigned int ip, int maxconnect) +{ + int newport; + struct sockaddr_in dest; + int on = 1; + + newport = socket(AF_INET, SOCK_STREAM, 6); + if (newport == -1) { + logFmsg(2, "netFipv4_listen_tcp: socket failed [e: %s]", + strerror(errno)); + return -1; + } + dest.sin_family = AF_INET; + dest.sin_port = htons(port); + dest.sin_addr.s_addr = htonl(ip); + + fleFset_close_exec(newport); + + setsockopt(newport, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); + + if (bind(newport, (struct sockaddr *) &dest, sizeof(dest)) == -1) { + logFmsg(2, "netFipv4_listen_tcp: bind failed: %s", + strerror(errno)); + return (-1); + } + listen(newport, maxconnect); + + return (newport); +} + +static ssize_t netFconn_reader_read(netTconn * conn, netTreader * reader) +{ + ssize_t ret; + + bzero(reader->buf, READER_CHUNK_SZ); + + thrFtrigger_set(10, conn->sd); + + ret = conn->io_read(conn, reader->buf, READER_CHUNK_SZ); + + thrFtrigger_clear(); + + if (ret == -1) + return -1; + + reader->len = ret; + + reader->pos = 0; + + return reader->len; +} + +/* + * Reads and writes into buf until either len-1 occurs, or a newline is found + * in the input sd. Always null terminates and returns the number of bytes + * written including the null. + */ + +ssize_t netFconn_read_line(netTconn * conn, netTreader * reader, + char *buf, ssize_t len) +{ + char *p; + ssize_t i, ret; + + assert(conn != NULL); + assert(reader != NULL); + assert(buf != NULL); + assert(len > 1); + + p = reader->buf + reader->pos; + + for (i = 0; i < len; i++) { + if ((reader->len == 0) || (reader->pos > (reader->len - 1))) { + /* No data in the buffer; read. */ + ret = netFconn_reader_read(conn, reader); + + /* error trap / null read trap */ + if (ret == -1 || ret == 0) { + return i; + } + p = reader->buf + reader->pos; + } + if (*p == '\n') { + reader->pos++; + + /* lets go back one to the newline */ + i--; + buf[i] = '\0'; /* Null terminate the string */ + return i; + } + if (*p != '\r') + buf[i] = *p; + + p++; + reader->pos++; + + } + return i; +} + +int netFisready(int fd) +{ + int rc; + fd_set fds; + struct timeval tv; + + FD_ZERO(&fds); + FD_SET(fd, &fds); + tv.tv_sec = 5; + tv.tv_usec = 0; + + rc = select(fd + 1, &fds, NULL, NULL, &tv); + if (rc < 0) + return -1; + + return FD_ISSET(fd, &fds) ? 1 : 0; +} + +int netFtcp_connect(char *addr, unsigned int port) +{ + int sock; + struct sockaddr_in sa; + struct hostent *hp; + + bzero((char *) &sa, sizeof(struct sockaddr_in)); + if (!(hp = gethostbyname(addr))) { + logFmsg(1, "gethostbyname failed."); + return -1; + } + sa.sin_family = AF_INET; + memcpy((char *) &sa.sin_addr, hp->h_addr_list[0], hp->h_length); + sa.sin_port = htons(port); + + if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + logFmsg(1, "socket [a: %s] [e: %s]", + addr, strerror(errno)); + return -1; + } + fleFset_close_exec(sock); + + if (connect(sock, (struct sockaddr *) &sa, + sizeof(struct sockaddr_in)) < 0) { + close(sock); + logFmsg(1, "connect failed: %s", strerror(errno)); + + return -1; + } + return sock; +} + +int netFconn_close(netTconn *conn) { + return conn->io_close(conn); +} + +ssize_t netFconn_read(netTconn * conn, netTreader * reader, + char *buf, ssize_t len) +{ + char *p; + ssize_t i, ret; + + p = reader->buf + reader->pos; + + for (i = 0; i < len; i++) { + if ((reader->len == 0) || (reader->pos > (reader->len - 1))) { + /* No data in the buffer; read. */ + ret = netFconn_reader_read(conn, reader); + + /* error trap / null read trap */ + if (ret == -1 || ret == 0) { + return i; + } + p = reader->buf + reader->pos; + } + buf[i] = *p; + p++; + reader->pos++; + } + return i; +} + +ssize_t netFconn_write_two(netTconn * conn, const char *buf1, + size_t buf1_len, const char *buf2, + size_t buf2_len) +{ + struct iovec io[2]; + ssize_t ret; + + io[0].iov_base = (char *) buf1; + io[0].iov_len = buf1_len; + io[1].iov_base = (char *) buf2; + io[1].iov_len = buf2_len; + + ret = conn->io_writev(conn, io, 2); + + if (ret > (ssize_t)buf1_len) + return ret - buf1_len; + else + return ret; +} + +ssize_t netFconn_writev(netTconn * conn, const struct iovec * iov, + int iovcnt) +{ + ssize_t ret = conn->io_writev(conn, iov, iovcnt); + return ret; +} + +ssize_t netFconn_write(netTconn * conn, const char *buf, ssize_t len) +{ + const char *bp = buf; + size_t blen = len; + ssize_t ret; + int tc = 0; + ssize_t written = 0; + + while (blen != 0) { + while ((ret = conn->io_write(conn, bp, blen)) == -1) { + if (errno == EAGAIN || errno == EINTR) { + if (errno == EPIPE) { + return -1; + } + if (tc == EAGAIN_TRYCOUNT) { + /* + * We have tried as many times as we are going to for + * this connection, so pass out an error and our caller + * can decide what to do. Register this as an EAGAIN + * failure. + */ + return -1; + } + tc++; + thrFsleep(EAGAIN_WAIT); + continue; + } else { + return -1; + } + } + blen -= ret; + bp += ret; + written += ret; + } + return written; +} + +int netFudp_send(int sd, const void *msg, size_t msg_len, unsigned int port, unsigned int ip) +{ + struct sockaddr_in sa; + sa.sin_family = AF_INET; + sa.sin_addr.s_addr = htonl(ip); + sa.sin_port = htons(port); + + return sendto(sd, msg, msg_len, 0, (struct sockaddr *) &sa, sizeof sa); +} + +int netFudp_recv(int sd, char *msg, size_t msg_len, struct sockaddr_in *sa, + size_t * sa_len) +{ + return recvfrom(sd, msg, msg_len, 0, (struct sockaddr *) sa, sa_len); +} + +/* + * port - Writes back the port that is actually used. Must be 0. defport - A + * default port in case it's not in services service - The service name to + * look in services + */ +int netFudp_open(uint16_t * port, int defport, char *service) +{ + int fd; + int result; + struct servent *svp; + struct sockaddr_in *sin_local; + struct sockaddr_in salocal; + uint16_t lport; + + /* + * If port already has an assignment, use it. This provides a kind of + * caching but requires that port be initialized to zero previous to this + * call + */ + + if (*port > 5) { + lport = htons(*port); + } else { + svp = getservbyname(service, "udp"); + if (svp != (struct servent *) NULL) { + lport = (unsigned short) svp->s_port; + } else { + lport = htons(defport); + } + *port = ntohs(lport); + } + + fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd < 0) { + logFmsg(2, "netFudp_open: socket error. [e: %d] [s: %s]", errno, + service); + return -1; + } + fleFset_close_exec(fd); + + sin_local = (struct sockaddr_in *) &salocal; + memset((char *) sin_local, '\0', sizeof(salocal)); + sin_local->sin_family = AF_INET; + sin_local->sin_addr.s_addr = INADDR_ANY; + sin_local->sin_port = lport; + + result = bind(fd, (struct sockaddr *) &salocal, sizeof(*sin_local)); + if (result < 0) { + logFmsg(2, "netFudp_open: bind error. [e: %d] [s: %s]", errno, + service); + return -1; + } + return fd; +} + +/* + * Create a socket for UDP Broadcast use. Returns the socket or -1/errno on + * error. + */ +int netFudp_bcast_connect(void) +{ + int sock; + struct sockaddr_in sa; + int on = 1; + int fd_flags; + + bzero((char *) &sa, sizeof(struct sockaddr_in)); + + sa.sin_family = AF_INET; + sa.sin_addr.s_addr = htonl(INADDR_ANY); + /* sa.sin_port=htons(port); random source port */ + + if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + return -1; + + fleFset_close_exec(sock); + + if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof on) == -1) + return -1; + + if ((fd_flags = fcntl(sock, F_GETFL)) == -1) + return -1; + fd_flags |= O_NONBLOCK; + if (fcntl(sock, F_SETFL, fd_flags) == -1) + return -1; + + if (bind(sock, (struct sockaddr *) &sa, sizeof sa) == -1) + return -1; + + return sock; +} + +int netFconn_writef(netTconn * conn, const char *fmt, ...) +{ + va_list ap; + char *buf; + int size = 1024; + int e; + + buf = (char *) malloc(size); + + va_start(ap, fmt); + + while (1) { + int nchars = vsnprintf(buf, size, fmt, ap); + + if (nchars > -1 && nchars < size) + break; + if (nchars > -1) + size = nchars + 1; + else + size *= 2; + buf = (char *) realloc(buf, size); + } + + va_end(ap); + + if ((e = netFconn_write(conn, buf, strlen(buf))) == -1) + e = -errno; + + free(buf); + + return e; +} + +int _netFconn_writef(netTconn * conn, const char *fmt, va_list * ap) +{ + char *buf; + int size = 1024; + int e; + + buf = (char *) malloc(size); + + while (1) { + int nchars = vsnprintf(buf, size, fmt, *ap); + + if (nchars > -1 && nchars < size) + break; + if (nchars > -1) { + size = nchars + 1; + } else { + size *= 2; + } + + buf = (char *) realloc(buf, size); + } + + if ((e = netFconn_write(conn, buf, strlen(buf))) == -1) { + e = -errno; + } + + free(buf); + + return e; +} + +netTreader *netFreader_init(void) +{ + netTreader *r; + + r = (netTreader *) malloc(sizeof(netTreader)); + bzero(r, sizeof(netTreader)); + + return r; +} + +void netFreader_free(netTreader * reader) +{ + free(reader); +} + +ssize_t netFconn_os_read(netTconn * conn, void *buf, size_t len) +{ + return read(conn->sd, buf, len); +} + +ssize_t netFconn_os_write(netTconn * conn, const void *buf, size_t len) +{ + size_t ret; + + thrFtrigger_set(10,conn->sd); + ret=write(conn->sd, buf, len); + thrFtrigger_clear(); + + return ret; +} + +int netFconn_os_close(netTconn * conn) +{ + return close(conn->sd); +} + +ssize_t netFconn_os_writev(netTconn * conn, const struct iovec * iov, + int iovcnt) +{ + return writev(conn->sd, iov, iovcnt); +} + +void netFconn_free(netTconn * conn) +{ + if (conn->data_free != NULL && conn->data != NULL) + conn->data_free(conn->data); + free(conn); +} + +netTconn *netFconn_make(int sd) +{ + netTconn *conn = memFalloc(sizeof(netTconn)); + + conn->sd = sd; + conn->io_read = &netFconn_os_read; + conn->io_write = &netFconn_os_write; + conn->io_close = &netFconn_os_close; + conn->io_writev = &netFconn_os_writev; + conn->data_free = NULL; + + return conn; +} + +/** IPv4 Multicast **/ + +#define MSGBUFSIZE 256 + +int netFipv4_mcast_create(unsigned int port, char *group) +{ + struct sockaddr_in addr; + int sd; + struct ip_mreq mreq; + + if((sd=socket(AF_INET,SOCK_DGRAM,0))<0) { + logFmsg(1,"socket() failed. [e: %d]", errno); + return -1; + } + + netFset_reuse(sd); + + memFclear(&addr,sizeof(addr)); + addr.sin_family=AF_INET; + addr.sin_addr.s_addr=htonl(INADDR_ANY); + addr.sin_port=htons(port); + + if(bind(sd,(struct sockaddr *)&addr,sizeof(addr))<0) { + logFmsg(1,"bind() failed. [e: %d]", errno); + return -1; + } + + mreq.imr_multiaddr.s_addr=inet_addr(group); + mreq.imr_interface.s_addr=htonl(INADDR_ANY); + if (setsockopt(sd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq)) < 0) { + logFmsg(1,"setsockopt() 2 failed. [e: %d]", errno); + return -1; + } + + return sd; +} diff --git a/lc-continuity/mk4/continuity/mecha/net.h b/lc-continuity/mk4/continuity/mecha/net.h new file mode 100644 index 0000000000000000000000000000000000000000..d653f6761fb8b92c424b069e6d3d28b775c5358d --- /dev/null +++ b/lc-continuity/mk4/continuity/mecha/net.h @@ -0,0 +1,28 @@ +/* + * $Header: /cvsroot/csrc/continuity/mecha/net.h,v 1.1 2004/03/11 19:05:20 + * aleigh Exp $ + */ + +/* + * Copyright (c) 1994, 2003 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Use, disclosure, copying, distribution, or transmission of this code without + * express permission is prohibited. + */ + +#ifndef _NET_H +#define _NET_H + +#define READER_CHUNK_SZ 1024 + +struct netSreader { + char buf[READER_CHUNK_SZ]; + ssize_t pos; + ssize_t len; +}; + +#endif diff --git a/lc-continuity/mk4/continuity/mecha/pat.c b/lc-continuity/mk4/continuity/mecha/pat.c new file mode 100644 index 0000000000000000000000000000000000000000..f8c0ce95a48bf1938c920ad00fc74142f35b8907 --- /dev/null +++ b/lc-continuity/mk4/continuity/mecha/pat.c @@ -0,0 +1,120 @@ +/* + * $Header: /san01/cvs/ashpool/csrc/continuity/mecha/Attic/pat.c,v 1.6 2004/04/30 13:41:56 aleigh Exp $ + * + * Copyright (c) 2004, Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH. The copyright + * notice above does not evidence any actual or intended publication of + * such source code. + * + * Use, disclosure, copying, distribution, or transmission of this code without + * express permission is prohibited. + */ + +#include "mecha.h" + +struct patSstack { + struct patSpattern *patterns; + size_t count; + void (*destructor) (void *); +}; + +/* Some other time we will extend this to include the per-compiled version of the + * regular expression for performance reasons, but I've got other fish to fry + * right now. -aleigh + */ +struct patSpattern { + const char *regexp; + void *target; +}; +typedef struct patSpattern patTpattern; + +/* This may need to take a destructor if we say that the list is going to be + * responsible for freeing the void pointers passed into it. -aleigh + */ + +/* + * MT - Does not require a lock. + */ +patTstack *patFstack_init(void (*destructor) (void *)) +{ + patTstack *stack = (patTstack *) malloc(sizeof(patTstack)); + + assert(stack != NULL); + + memFclear(stack, sizeof(patTstack)); + + stack->destructor = destructor; + + return stack; +} + +/* + * MT - Requires a write lock. + * */ +void patFstack_free(patTstack * stack) +{ + size_t i; + + for (i = 0; i < stack->count; i++) { + if (stack->destructor != NULL) { + (stack->destructor)(stack->patterns[i].target); + } + free((void *)stack->patterns[i].regexp); /* We added this field with strFcopy() */ + } + + free(stack->patterns); + free(stack); +} + +/* + * MT - Does not require a lock. + */ +size_t patFstack_size(patTstack * stack) +{ + return stack->count; +} + +/* + * MT - Requires a write lock on the stack. + */ +void patFstack_append(patTstack * stack, const char *regexp, void *target) +{ + assert(stack != NULL); + assert(regexp != NULL); + assert(target != NULL); + + if (stack->count == 0) { + stack->patterns = (patTpattern *) malloc(sizeof(patTpattern)); + stack->patterns[0].regexp = strFcopy(regexp); + stack->patterns[0].target = target; + stack->count = 1; + } else { + stack->count++; + stack->patterns = + (patTpattern *) realloc(stack->patterns, + sizeof(patTpattern) * stack->count); + stack->patterns[stack->count].regexp = strFcopy(regexp); + stack->patterns[stack->count].target = target; + } +} + +/* + * MT - requires at least a read lock on the stack. Patterns are searched in the order + * that they were appended into the stack. + */ +void *patFstack_search(patTstack * stack, const char *needle) +{ + size_t i; + + assert(stack != NULL); + assert(needle != NULL); + + for(i=0;icount;i++) { + if(expFmatch(stack->patterns[i].regexp, needle)==1) { + logFmsg(3,"pat: Matched."); + return stack->patterns[i].target; + } + } + return NULL; +} diff --git a/lc-continuity/mk4/continuity/mecha/qry.c b/lc-continuity/mk4/continuity/mecha/qry.c new file mode 100644 index 0000000000000000000000000000000000000000..20e3ca64362898c03493b806e329a7165d019f83 --- /dev/null +++ b/lc-continuity/mk4/continuity/mecha/qry.c @@ -0,0 +1,90 @@ +/* + * $Header: /san01/cvs/ashpool/csrc/continuity/mecha/Attic/qry.c,v 1.9 2004/04/30 13:41:56 aleigh Exp $ + * + * Copyright (c) 1994, 2004 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Disclosure, copying, distribution, or transmission of this code without + * express permission is prohibited. + */ + +#include "mecha.h" + +#define QRY_M_INIT 1 +#define QRY_M_NCOPY 2 +#define QRY_M_VCOPY 3 +#define QRY_M_SCAN 4 + +/* This is my December, this is my time of the year */ + +lstTset *qryFlst_parse(const char *query) +{ + lstTset *set = lstFset_create("query"); + int mode = QRY_M_INIT; + char nbuf[1024], vbuf[1024], *y; + const char *x; + + /* x points to the input query. */ + /* y points to the output buffer, n, or v */ + + assert(query != NULL); + + x = query; + + while (1) { + if (mode == QRY_M_INIT) { + mode = QRY_M_NCOPY; + y = nbuf; + nbuf[0] = '\0'; + } + if (mode == QRY_M_NCOPY) { + if (*x == '=') { + /* finished with the name */ + mode = QRY_M_VCOPY; + x++; + *y = '\0'; + + y = (char *) vbuf; + *y = '\0'; + continue; + } + *y = *x; + + y++; + x++; + + /* If this matches, the query is short. */ + if (*x == '\0') { + break; + } + continue; + } + if (mode == QRY_M_VCOPY) { + if (*x == '&' || *x == '\0') { + /* Finished with the value */ + mode = QRY_M_INIT; + if (*vbuf != '\0') { + *y = '\0'; + lstFset_add(set, nbuf, vbuf); + } + /* If not, then we have another argument. */ + if (*x == '\0') + break; + + x++; + *y = '\0'; + continue; + + } + *y = *x; + y++; + x++; + continue; + } + } + + return set; +} diff --git a/lc-continuity/mk4/continuity/mecha/rnd.c b/lc-continuity/mk4/continuity/mecha/rnd.c new file mode 100644 index 0000000000000000000000000000000000000000..c7dab285ae219afc04f131138fbdf5902705441d --- /dev/null +++ b/lc-continuity/mk4/continuity/mecha/rnd.c @@ -0,0 +1,69 @@ +/* + * $Header: /san01/cvs/ashpool/csrc/continuity/mecha/Attic/rnd.c,v 1.8 2004/04/30 13:41:56 aleigh Exp $ + */ + +/* + * Copyright (c) 1994, 2004 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Disclosure, copying, distribution, or transmission of this code without + * express permission is prohibited. + */ + +/* + * Generate len random bytes and write them into buf. + */ + +#include "mecha.h" + +static unsigned int rndGseed; + +void rndFinit(void) +{ + rndGseed = utlFtime(); + +#ifdef HAVE_RAND_R + srand(rndGseed); +#endif +} + +void rndFrandom_bytes(unsigned char *buf, int len) +{ + unsigned char *p = buf; + int i; + + for (i = 0; i < len; i++) { +#ifdef HAVE_RAND_R + *p = rand_r(&rndGseed) % 256; +#else + +#ifdef WIN32 + *p = rand() % 256; +#else + *p = random() % 256; +#endif /* WIN32 */ + +#endif /* HAVE_RAND_R */ + p++; + } +} + +unsigned int rndFnumber(void) +{ +#ifdef HAVE_RAND_R + unsigned int seed; + + return rand_r(&seed); +#else + +#ifdef WIN32 + return rand(); +#else + return random(); +#endif /* WIN32 */ + +#endif /* HAVE_RAND_R */ +} diff --git a/lc-continuity/mk4/continuity/mecha/str.c b/lc-continuity/mk4/continuity/mecha/str.c new file mode 100644 index 0000000000000000000000000000000000000000..75c353835338679a777c17743479b2cd765dddcb --- /dev/null +++ b/lc-continuity/mk4/continuity/mecha/str.c @@ -0,0 +1,322 @@ +/* + * $Header: /san01/cvs/ashpool/csrc/continuity/mecha/Attic/str.c,v 1.21 2004/04/30 13:41:56 aleigh Exp $ + */ + +/* + * Copyright (c) 1994, 2004 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Disclosure, copying, distribution, or transmission of this code without + * express permission is prohibited. + */ + +#include "mecha.h" + +#ifndef MAX +#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#endif +#ifndef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +void strFstrip_crlf(char *s, const size_t len) +{ + char *p; + + for (p = s + len; p != s; p--) { + if (*p == '\r' || *p == '\n' || *p == '\0') { + *p = '\0'; + } else { + return; + } + } +} + +void strFtoupper(char *s) +{ + char *p; + + for (p = s; *p != '\0'; p++) { + *p = toupper(*p); + } +} + +void strFtolower(char *s) +{ + char *p; + + for (p = s; *p != '\0'; p++) { + *p = tolower(*p); + } +} + +/* + * Duplicate the string s, and write back the length of the string into len. + * The duplicate string is returned. + */ +char *strFdup_size(const char *s, size_t * len) +{ + char *t; + size_t l_len; + + assert(s != NULL); + + l_len = strlen(s); + + t = (char *) malloc(l_len + 1); + + /* we know the length so we can use memcpy instead of strcpy */ + memcpy(t, s, l_len); + + /* add the trailing null */ + t[l_len] = 0; + + *len = l_len; + + return t; +} + +/* + * duplicate the length of the string, and write the strlen back into the + * pointer provided by len. If the input string is NULL, nothing will be + * written into len. + */ +char *strFcopy_size(const char *s, size_t * len) +{ + return (s == NULL ? NULL : strFdup_size(s, len)); +} + +/* TODO: strFdup() and strFcopy() are now functionally identical. */ + +/* + * Duplicate the string and return the duplicate, or, return NULL if the + * provided string was NULL + */ +char *strFcopy(const char *s) +{ + size_t unused; + + return (strFcopy_size(s, &unused)); +} + +char *strFncopy(const char *s, size_t len) { + assert(s!=NULL); + + return (char *)memFdup(s,len); +} + +/* from thttpd */ +static int str_alloc_count = 0; +static long str_alloc_size = 0; + +void strFrealloc(char **strP, int *maxsizeP, int size) +{ + if (*maxsizeP == 0) { + *maxsizeP = MAX(200, size); /* arbitrary */ + *strP = (char *) malloc(*maxsizeP + 1); + ++str_alloc_count; + str_alloc_size += *maxsizeP; + } else if (size > *maxsizeP) { + str_alloc_size -= *maxsizeP; + *maxsizeP = MAX(*maxsizeP * 2, size * 5 / 4); + *strP = (char *) realloc(*strP, *maxsizeP + 1); + str_alloc_size += *maxsizeP; + } else + return; + if (*strP == (char *) 0) { + /* logFmsgid(1,"CON",15,"strFrealloc"); */ + abort(); + } +} + +const char *strFcasestr(const char *haystack, const char *needle) +{ + const char *hptr, *hlast; + const char *nptr; + + hptr = haystack; + nptr = needle; + + while (*hptr) { + if (tolower(*hptr++) == tolower(*nptr)) { + hlast = hptr; + + while (*nptr && tolower(*hptr++) == tolower(*++nptr)) + continue; + + if (*nptr) { + hptr = hlast; + nptr = needle; + } else + return hlast - 1; + } + } + return (NULL); +} + +int strFis_whitespace(char c) +{ + if (c == '\n' || c == '\r' || c == ' ' || c == '\t') + return 1; + return 0; +} + +int strFis_blank(char *s) +{ + char *p; + + for (p = s; *p != 0; p++) { + if (strFis_whitespace(*p) == 0) + return 0; + } + + return 1; +} + + +#define CM_COPY 1 +#define CM_WHITE 2 +dynTstring *strFcollapse_whitespace(char *str) +{ + dynTstring *new = dynFinit(); + char *p; + int mode = CM_COPY; + + assert(str != NULL); + + for (p = str; *p != '\0'; p++) { + switch (mode) { + case CM_COPY: + if (*p == '\r') + continue; + + if (strFis_whitespace(*p) == 1) { + dynFappend(new, " ", 1); + mode = CM_WHITE; + continue; + } + dynFappend(new, p, 1); + + break; + + case CM_WHITE: + if (strFis_whitespace(*p) == 1) + continue; + dynFappend(new, p, 1); + mode = CM_COPY; + break; + } + } + return new; +} + +#define P_SEARCH 3 +#define P_NAME 1 +#define P_VAL 2 + +lstTset *strFattrib_parser(const char *str) +{ + int mode = P_SEARCH; + const char *p; + char nbuf[128]; + int nbufc = 0; + char vbuf[128]; + int vbufc = 0; + lstTset *set = lstFset_init(); + + assert(str != NULL); + assert(set != NULL); + + for (p = str; *p != 0; p++) { + switch (mode) { + case P_SEARCH: + if (strFis_whitespace(*p) == 1) + break; + mode = P_NAME; + + case P_NAME: + if (*p == '=') { + nbuf[nbufc] = 0; + mode = P_VAL; + p++; + break; + } + nbuf[nbufc] = *p; + nbufc++; + break; + + case P_VAL: + if (*p == '"') { + mode = P_SEARCH; + vbuf[vbufc] = 0; + lstFset_add(set, nbuf, vbuf); + /* printf("Got %s %s\n", nbuf, vbuf); */ + vbufc = 0; + nbufc = 0; + break; + } + vbuf[vbufc] = *p; + vbufc++; + break; + } + } + return set; +} + + +unsigned int strFsplit(char *str, char **list, unsigned int list_size, + const char delim, const char quotechar) +{ + register char *p, *sp; + register unsigned int listc = 0; + register short inquote = 0; + + assert(str != NULL); + assert(list != NULL); + assert(list_size > 0); + + list_size--; + + if (quotechar == 0) + inquote = 3; + + for (sp = p = str; *p != 0; p++) { + if (inquote == 1) { + if (*p == quotechar) + inquote = 0; + continue; + } + if (inquote == 0) + if (*p == quotechar) { + inquote = 1; + continue; + } + if (*p == delim) { + *p = '\0'; + list[listc] = sp; + if (listc == list_size) + return listc + 1; + listc++; + sp = (p + 1); + } + } + + list[listc] = sp; + return listc + 1; +} + +const char *strFskip_whitespace(const char *p) +{ + while (isspace(*p)) p++; + return p; +} + +const char *strFskip_token(const char *p) +{ + while (isspace(*p)) p++; + while (*p && !isspace(*p)) p++; + return p; +} diff --git a/lc-continuity/mk4/continuity/mecha/sys.c b/lc-continuity/mk4/continuity/mecha/sys.c new file mode 100644 index 0000000000000000000000000000000000000000..1008e5be66d96e5ba7c7e263ecfacc667a18ca5c --- /dev/null +++ b/lc-continuity/mk4/continuity/mecha/sys.c @@ -0,0 +1,618 @@ +/* + * Copyright (c) 1994, 2004 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Use, disclosure, copying, distribution, or transmission of of this code without + * express permission is prohibited. + */ + +#include "mecha.h" + +#ifdef LINUX + +/* Have faith; it's really here but you need a weird collection + of define's to get the declaration for it. */ + +extern int getloadavg(double loadavg[], int nelem); + +static unsigned int sysGstart_time=0; + +#define PAGESIZE 4096 + +int sysFnet_usage(uint32_t *obytes, uint32_t *ibytes, + uint32_t *opkts, uint32_t *ipkts) +{ + int fd; + char *stack[24]; + char buf[4096]; + size_t len; + int lines, i; + + fd=open("/proc/net/dev",O_RDONLY); + if(fd==-1) { + logFmsg(2,"Cannot open /proc/net/dev. [e: %d]", errno); + return -1; + } + + len=read(fd,buf,4095); + close(fd); + buf[len]=0; + + lines=strFsplit(buf,stack,24,'\n','"'); + lines--; + + if(lines<2) { + logFmsg(2,"Unable to parse the /proc/net/dev file. Invalid format."); + return -1; + } + + unsigned long ob=0, op=0, ib=0, ip=0; + + char *p; + + for(i=2;i +#include +#ifdef HAVE_GETLOADAVG +#include +#endif +#include + +int sysFfs_info(lstTset * set) +{ + FILE *mnttab; + struct mnttab me; + struct statvfs fse; + char nbuf[128]; + char vbuf[128]; + + assert(set!=NULL); + + mnttab = fopen("/etc/mnttab", "r"); + + if (mnttab == NULL) { + logFmsg(2, "Unable to open /etc/mnttab [e: %d]", errno); + return -1; + } + + while (getmntent(mnttab, &me) == 0) { + if (strcmp(me.mnt_fstype, "ufs") == 0 + || strcmp(me.mnt_fstype, "vxfs") == 0 + || strcmp(me.mnt_fstype, "tmpfs") == 0) { + if (statvfs(me.mnt_mountp, &fse) != 0) { + logFmsg(2, "statvfs() failed [e: %d] [mp: %s]", + errno, me.mnt_mountp); + } + sprintf(nbuf, "fs_%s_blocks", me.mnt_mountp); + sprintf(vbuf, "%u", fse.f_blocks); + lstFset_add(set, (char *) &nbuf, (char *) &vbuf); + + sprintf(nbuf, "fs_%s_bavail", me.mnt_mountp); + sprintf(vbuf, "%u", fse.f_bavail); + lstFset_add(set, (char *) &nbuf, (char *) &vbuf); + + sprintf(nbuf, "fs_%s_bsize", me.mnt_mountp); + sprintf(vbuf, "%u", fse.f_bsize); + lstFset_add(set, (char *) &nbuf, (char *) &vbuf); + + sprintf(nbuf, "fs_%s_files", me.mnt_mountp); + sprintf(vbuf, "%u", fse.f_files); + lstFset_add(set, (char *) &nbuf, (char *) &vbuf); + + sprintf(nbuf, "fs_%s_favail", me.mnt_mountp); + sprintf(vbuf, "%u", fse.f_favail); + lstFset_add(set, (char *) &nbuf, (char *) &vbuf); + } + } + fclose(mnttab); +} + +/* + * PercentLoad = 100 * (1 - D/(D+Load)) + * where D determines which load value should be associated with which + * load percentage. D=50 means that 128 is 50% load, 256 is 80%, etc. + */ +int sysFget_load(double *one_min, double *five_min, double *fifteen_min) +{ + double x[3]; + +#ifdef HAVE_GETLOADAVG + if (getloadavg(x, 3) == -1) { + logFmsg(2, "getloadvg failed [e: %d]", errno); + return -1; + } +#else + x[0]=0; + x[1]=0; + x[2]=0; +#endif + + *one_min=x[0]; + *five_min=x[1]; + *fifteen_min=x[2]; + + return 0; +} + +static kstat_ctl_t *sysGkc=NULL; +static pthread_mutex_t sysLkc=PTHREAD_MUTEX_INITIALIZER; + +static kstat_ctl_t *sysFgetkc(void) { + if(sysGkc!=NULL) { + return sysGkc; + } + + pthread_mutex_lock(&sysLkc); + + if(sysGkc!=NULL) { + /* Someone else opened it */ + pthread_mutex_unlock(&sysLkc); + return sysGkc; + } + + sysGkc=kstat_open(); + pthread_mutex_unlock(&sysLkc); + return sysGkc; +} + +/* + * Return the startup time of the host, in unix time. + */ +unsigned int sysFboot_time(void) +{ + + kstat_ctl_t *kc; + kstat_t *ksp; + kstat_named_t *kn; + + kc = sysFgetkc(); + + if (kc == NULL) { + perror("kstat_open"); + abort(); + } + ksp = kstat_lookup(kc, "unix", -1, "system_misc"); + + kstat_read(kc, ksp, NULL); + + kn = kstat_data_lookup(ksp, "boot_time"); + + switch (kn->data_type) { +#ifdef KSTAT_DATA_INT32 + case KSTAT_DATA_INT32: + return kn->value.i32; + break; + case KSTAT_DATA_UINT32: + return kn->value.ui32; + break; + case KSTAT_DATA_INT64: + return kn->value.i64; + break; + case KSTAT_DATA_UINT64: + return kn->value.ui64; + break; +#endif + } + + return -1; +} + +int sysFmem_usage(uint32_t *pages_total, uint32_t *pages_free, + uint32_t *phys_mem, uint32_t *availr_mem, + uint32_t *free_mem) +{ + + kstat_ctl_t *kc; + kstat_t *ksp; + kstat_named_t *kn; + + kc = sysFgetkc(); + + if (kc == NULL) { + logFmsg(2,"kstat_open failed [e: %d]", errno); + return -1; + } + + ksp = kstat_lookup(kc, "unix", -1, "system_pages"); + + assert(ksp!=NULL); + + kstat_read(kc, ksp, NULL); + + kn = kstat_data_lookup(ksp, "pagestotal"); + assert(kn!=NULL); + *pages_total = kn->value.ui32; + + kn = kstat_data_lookup(ksp, "pagesfree"); + assert(kn!=NULL); + *pages_free = kn->value.ui32; + + kn = kstat_data_lookup(ksp, "physmem"); + assert(kn!=NULL); + *phys_mem = kn->value.ui32; + + kn = kstat_data_lookup(ksp, "availrmem"); + assert(kn!=NULL); + *availr_mem = kn->value.ui32; + + kn = kstat_data_lookup(ksp, "freemem"); + assert(kn!=NULL); + *free_mem=kn->value.ui32; + + return 0; +} + +struct sysScpu { + kstat_t *ksp; + struct sysScpu *next; +}; +typedef struct sysScpu sysTcpu; + +static sysTcpu *sysGcpus=NULL; +static pthread_mutex_t sysLcpus=PTHREAD_MUTEX_INITIALIZER; + +static int sysFcpu_init(kstat_ctl_t *kc) { + int i; + kstat_t *ksp; + sysTcpu *cpu; + + assert(kc!=NULL); + + for(i=0;i<128;i++) { + ksp=kstat_lookup(kc,"cpu_stat",i,NULL); + if(ksp==NULL) continue; + + logFmsg(3,"Found CPU: %d", i); + cpu=(sysTcpu *)malloc(sizeof(sysTcpu)); + cpu->ksp=ksp; + cpu->next=sysGcpus; + sysGcpus=cpu; + } + + return 0; +} + +int sysFcpu_usage(uint32_t *idle_time, uint32_t *user_time, + uint32_t *kernel_time, uint32_t *wait_time) +{ + kstat_ctl_t *kc; + sysTcpu *cpu; + cpu_stat_t cpu_stat; + + kc=sysFgetkc(); + + assert(kc!=NULL); + + *idle_time=0; + *user_time=0; + *kernel_time=0; + *wait_time=0; + + if(sysGcpus==NULL) { + pthread_mutex_lock(&sysLcpus); + if(sysGcpus==NULL) { + sysFcpu_init(kc); + } + pthread_mutex_unlock(&sysLcpus); + } + + for(cpu=sysGcpus;cpu!=NULL;cpu=cpu->next) { + assert(cpu!=NULL); + assert(cpu->ksp!=NULL); + + if(kstat_read(kc,cpu->ksp,&cpu_stat)==-1) { + return -1; + } + *idle_time += cpu_stat.cpu_sysinfo.cpu[0]; + *user_time += cpu_stat.cpu_sysinfo.cpu[1]; + *kernel_time += cpu_stat.cpu_sysinfo.cpu[2]; + *wait_time += cpu_stat.cpu_sysinfo.cpu[3]; + } + + return 0; +} + +struct sysSnet { + kstat_t *ksp; + struct sysSnet *next; +}; +typedef struct sysSnet sysTnet; + +static sysTnet *sysGnet=NULL; +static pthread_mutex_t sysLnet = PTHREAD_MUTEX_INITIALIZER; + +/* Must own sysLnet */ +static void sysFnet_register(kstat_t *ksp) { + sysTnet *net; + + assert(ksp!=NULL); + + net=(sysTnet *)malloc(sizeof(sysTnet)); + assert(net!=NULL); + + net->ksp=ksp; + net->next=sysGnet; + sysGnet=net; +} + +static int sysFnet_init(kstat_ctl_t *kc) { + kstat_t *ksp; + int i; + + assert(kc!=NULL); + + for(i=0;i<128;i++) { + ksp=kstat_lookup(kc,"hme",i,NULL); + if(ksp!=NULL) { + logFmsg(3,"Found network interface hme%d", i); + sysFnet_register(ksp); + } + + ksp=kstat_lookup(kc,"qfe",i,NULL); + if(ksp!=NULL) { + logFmsg(3,"Found network interface qfe%d", i); + sysFnet_register(ksp); + } + + ksp=kstat_lookup(kc,"le",i,NULL); + if(ksp!=NULL) { + logFmsg(3,"Found network interface le%d", i); + sysFnet_register(ksp); + } + + ksp=kstat_lookup(kc,"ge",i,NULL); + if(ksp!=NULL) { + logFmsg(3,"Found network interface ge%d", i); + sysFnet_register(ksp); + } + } + + return i; +} + +int sysFnet_usage(uint32_t *obytes, uint32_t *ibytes, + uint32_t *opkts, uint32_t *ipkts) +{ + kstat_ctl_t *kc; + kstat_named_t *kn; + sysTnet *net; + + kc=sysFgetkc(); + + assert(kc!=NULL); + + *obytes=0; + *ibytes=0; + *opkts=0; + *ipkts=0; + + if(sysGnet==NULL) { + pthread_mutex_lock(&sysLnet); + if(sysGnet==NULL) { + sysFnet_init(kc); + } + pthread_mutex_unlock(&sysLnet); + } + + for(net=sysGnet;net!=NULL;net=net->next) { + kstat_read(kc,net->ksp,NULL); + + kn=kstat_data_lookup(net->ksp,"obytes"); + if(kn!=NULL) { + *obytes+=kn->value.ui32; + } + + kn=kstat_data_lookup(net->ksp,"rbytes"); + if(kn!=NULL) { + *ibytes+=kn->value.ui32; + } + + kn=kstat_data_lookup(net->ksp,"ipackets"); + if(kn!=NULL) { + *ipkts+=kn->value.ui32; + } + + kn=kstat_data_lookup(net->ksp,"opackets"); + if(kn!=NULL) { + *opkts+=kn->value.ui32; + } + } + + return 0; +} + +#endif diff --git a/lc-continuity/mk4/continuity/mecha/thr.c b/lc-continuity/mk4/continuity/mecha/thr.c new file mode 100644 index 0000000000000000000000000000000000000000..6519caff42b02ec4943729473319d46844f2c4de --- /dev/null +++ b/lc-continuity/mk4/continuity/mecha/thr.c @@ -0,0 +1,533 @@ +/* + * $Header: /san01/cvs/ashpool/csrc/continuity/mecha/Attic/thr.c,v 1.24 2004/05/27 13:55:00 aleigh Exp $ + */ + +/* + * Copyright (c) 1994, 2004 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Disclosure, copying, distribution, or transmission of of this code without + * express permission is prohibited. + */ + +#include "mecha.h" + +/* #define PRECREATE */ + +struct thrSinfo { + struct thrStpool *tpool; + int index; +}; +typedef struct thrSinfo thrTinfo; + +struct thrStrigger { + unsigned int time; + int fd; + pthread_t tid; +}; + +typedef struct tpool_work { + void (*routine) (void *data); + void *arg; + struct tpool_work *next; +} thrTtpool_work; + +struct thrStpool { + /* pool characteristics */ + int num_threads; + int max_queue_size; + int started; + int inuse; + + int blocking_mode; + /* pool state */ + int cur_queue_size; + pthread_t *threads; + thrTtpool_work *queue_head; + thrTtpool_work *queue_tail; + int queue_closed; + int shutdown; + /* pool synchronization */ + pthread_mutex_t queue_lock; + pthread_mutex_t thread_lock; + pthread_cond_t queue_not_empty; + pthread_cond_t queue_not_full; + pthread_cond_t queue_empty; + struct thrStrigger *trigger; +}; + +pthread_key_t thrKtrigger; +void *thrFthread(void *); + +void thrFmod_init(void) +{ + if (pthread_key_create(&thrKtrigger, NULL) == -1) { + logFmsg(3, "thrFmod_init: Failed to create trigger TLS key."); + } +} + +int thrFsleep(int ms) +{ + struct timespec then; + int ret; + +#ifdef LINUX + + then.tv_sec = ms / 1000; + then.tv_nsec = (ms % 1000) * 1000000; + + /* shut up vgrind, not required */ + ret = nanosleep (&then, NULL); + +#else + pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; + pthread_cond_t cond = PTHREAD_COND_INITIALIZER; + struct timeval now; + int deltams; + + gettimeofday(&now, NULL); + + deltams = (now.tv_usec / 1000) + ms; + + then.tv_sec = now.tv_sec + (deltams / 1000); + then.tv_nsec = (deltams % 1000) * 1000000; + + /* + * OpenBSD requires that the mutex be locked, or else cond_timedwait will + * return EINVAL. We can get away with this on Linux so far even though + * it is bad behavior. Will generate valgrind warnings. + */ +#if defined(OPENBSD) || defined(FREEBSD) + pthread_mutex_lock(&mut); + pthread_mutex_lock(&mut); +#endif + + ret = pthread_cond_timedwait(&cond, &mut, (struct timespec *) &then); +#endif /* LINUX */ + + return 0; +} + +thrTtrigger *thrFgettrigger(void) +{ + return pthread_getspecific(thrKtrigger); +} + +int thrFtrigger_set(unsigned int delta, int fd) +{ + thrTtrigger *trig = thrFgettrigger(); + + if (trig == NULL) { +// logFmsg(3, "trig NULL tid %d", pthread_self()); + return -1; + } + trig->fd = fd; + trig->time = utlFtime() + delta; + + return 0; +} + +int thrFtrigger_clear(void) +{ + thrTtrigger *trig = thrFgettrigger(); + + if (trig == NULL) + return -1; + + trig->time = 0; + + return 0; + + +} + +void thrFcheck_triggers(thrTtpool * tp) +{ + int i; + unsigned int now = utlFtime(); + + for (i = 0; i < tp->num_threads; i++) { + if (tp->trigger[i].time <= now && tp->trigger[i].time != 0) { + /* + * logFmsg(3, "thrFcheck_triggers: Triggering fd %d", + * tp->trigger[i].fd); + */ + shutdown(tp->trigger[i].fd, 2); + tp->trigger[i].time = 0; + } + } +} + +/* + * This thread runs continuously and keeps statistics about the threadpool + * current. It is also responsable for outputting messages when the pool + * filles. + */ + +void thrFstat_thr(void *tp) +{ + thrTtpool *tpool = (thrTtpool *) tp; + + while (1) { + if (tpool->cur_queue_size > 0) { + logFmsg(0, "thr_pool: [queue: %d/%d] [threads: %d/%d (%d)]", + tpool->cur_queue_size, tpool->max_queue_size, + tpool->inuse, tpool->started, tpool->num_threads); + } + thrFcheck_triggers(tpool); + thrFsleep(1000); + } +} + +thrTtpool *thrFinit(int num_worker_threads, + int max_queue_size, int blocking_mode) +{ + unsigned int i; + int ret; + thrTtpool *tpool; + + /* allocate a pool data structure */ + if ((tpool = (thrTtpool *) malloc(sizeof(thrTtpool))) == NULL) { + logFmsg(3, "thrFinit: malloc()"); + exit(1); + } + /* initialize th fields */ + tpool->num_threads = num_worker_threads; + tpool->max_queue_size = max_queue_size; + tpool->blocking_mode = blocking_mode; + tpool->started = 1; + tpool->inuse = 0; + + if ((tpool->threads = + (pthread_t *) malloc(sizeof(pthread_t) * num_worker_threads)) + == NULL) + perror("malloc"), exit(1); + tpool->cur_queue_size = 0; + tpool->queue_head = NULL; + tpool->queue_tail = NULL; + tpool->queue_closed = 0; + tpool->shutdown = 0; + + tpool->trigger = + (thrTtrigger *) malloc(sizeof(thrTtrigger) * num_worker_threads); + memFclear(tpool->trigger, sizeof(thrTtrigger) * num_worker_threads); + + /* Start the statistics output thread */ + pthread_create((pthread_t *) & i, NULL, + (void *(*)(void *)) thrFstat_thr, (void *) tpool); + + if ((ret = pthread_mutex_init(&(tpool->queue_lock), NULL)) != 0) { + logFmsg(2, "thrFinit: pthread_mutex_init failed. (e: %d)", ret); + exit(1); + } + if ((ret = pthread_mutex_init(&(tpool->thread_lock), NULL)) != 0) { + logFmsg(2, "thrFinit: pthread_mutex_init failed. (e: %d)", ret); + exit(1); + } + if ((ret = pthread_cond_init(&(tpool->queue_not_empty), NULL)) != 0) { + logFmsg(2, "thrFinit: conditional not_empty failed. (e: %d)", ret); + exit(1); + } + if ((ret = pthread_cond_init(&(tpool->queue_not_full), NULL)) != 0) { + logFmsg(2, "thrFinit: conditional not_full failed. (e: %d)", ret); + exit(1); + } + if ((ret = pthread_cond_init(&(tpool->queue_empty), NULL)) != 0) { + logFmsg(2, "thrFinit: conditional empty failed. (e: %d)", ret); + exit(1); + } + { + thrTinfo *info = (thrTinfo *) malloc(sizeof(thrTinfo)); + pthread_t tid; + + info->index = 0; + info->tpool = tpool; + + if ((ret = + pthread_create((pthread_t *) & tid, NULL, thrFthread, + (void *) info)) != 0) { + logFmsg(2, + "thrFinit: Unable to create first pool thread. (e: %d)", + ret); + exit(1); + } + } + +#ifdef PRECREATE + for (i = 1; i != num_worker_threads; i++) { + thrTinfo *info = (thrTinfo *) malloc(sizeof(thrTinfo)); + pthread_t tid; + + info->index = i; + info->tpool = tpool; + + if ((ret = pthread_create((pthread_t *) & tid, + NULL, thrFthread, (void *) info)) != 0) { + logFmsg(2, "thrFinit: Unable to create pool thread: %d", ret); + exit(1); + } + } +#endif + + return tpool; +} + +/* + * Beyond, Amon Hen is before us. + */ + +int thrFadd_work(thrTtpool * tpool, void (*routine) (void *data), + void *arg) +{ + int ret; + thrTtpool_work *workp; + + if ((ret = pthread_mutex_lock(&(tpool->queue_lock))) != 0) { + logFmsg(2, "thrFadd_work: mutex lock failed. (e: %d)", ret); + exit(1); + } + /* + * If the blocking mode is 1 and the queue is full than we are going to + * return immediately. Otherwise we will go ahead and try to add the work + * but will block until it is able to be accepted. + */ + + if ((tpool->cur_queue_size == tpool->max_queue_size) && + tpool->blocking_mode == 1) { + if ((ret = pthread_mutex_unlock(&(tpool->queue_lock))) != 0) { + logFmsg(2, "thrFadd_work: mutex unlock failed. (e: %d)", ret); + exit(1); + } + return -1; + } + while ((tpool->cur_queue_size == tpool->max_queue_size) && + (!(tpool->shutdown || tpool->queue_closed))) { + if ((ret = pthread_cond_wait(&(tpool->queue_not_full), + &(tpool->queue_lock))) != 0) { + logFmsg(2, "thrFadd_work: cond_wait failed. (e: %d)", ret); + exit(1); + } + } + + if (tpool->shutdown || tpool->queue_closed) { + if ((ret = pthread_mutex_unlock(&(tpool->queue_lock))) != 0) { + logFmsg(2, "thrFadd_work: mutex unlock failed. (e: %d)", ret); + exit(1); + } + return -1; + } + if ((workp = + (thrTtpool_work *) malloc(sizeof(thrTtpool_work))) == NULL) { + logFmsg(2, "thrFadd_work: malloc() failed."); + exit(1); + } + workp->routine = routine; + workp->arg = arg; + workp->next = NULL; + + if (tpool->cur_queue_size == 0) { + tpool->cur_queue_size++; + + tpool->queue_tail = tpool->queue_head = workp; + + if ((ret = pthread_cond_signal(&(tpool->queue_not_empty))) != 0) { + logFmsg(2, + "thrFadd_work: conditional signal on pool failed. (e: %d)", + ret); + exit(1); + } + } else { + tpool->cur_queue_size++; + + tpool->queue_tail->next = workp; + tpool->queue_tail = workp; + + if ((ret = pthread_cond_signal(&(tpool->queue_not_empty))) != 0) { + logFmsg(2, + "thrFadd_work: conditional signal on not empty failed. (e: %d)", + ret); + exit(1); + } + } + + if ((ret = pthread_mutex_unlock(&(tpool->queue_lock))) != 0) { + logFmsg(2, "thrFadd_work: mutex unlock on queue failed. (e: %d)", + ret); + exit(1); + } + /* + * Check to see if all the threads are currently in use, and if we've + * started them all or not. If we haven't, we're going to go ahead and + * start another one now. This is coded like this so that the mutex isn't + * locked every time work is added, rather, only when it's likely that + * another thread is needed. Synchronization on demand. Once all the + * threads are started, we won't check at all. + */ + + if (tpool->started < tpool->num_threads) { + if ((tpool->started - tpool->inuse) <= 5) { + pthread_mutex_lock(&tpool->thread_lock); + if (tpool->started < tpool->num_threads) { + thrTinfo *info = (thrTinfo *) malloc(sizeof(thrTinfo)); + pthread_t tid; + + info->index = tpool->started - 1; + info->tpool = tpool; + + /* + * logFmsg (3, "thrFadd_work: starting new worker thread. + * (sid: %d)", info->index); + */ + + if ((ret = + pthread_create((pthread_t *) & tid, NULL, thrFthread, + (void *) info)) != 0) { + logFmsg(2, + "thrFinit: Unable to create first pool thread. (e: %d)", + ret); + exit(1); + } + tpool->started++; + } + pthread_mutex_unlock(&tpool->thread_lock); + } + } + return 1; +} + +int thrFdestroy(thrTtpool * tpool, int finish) +{ + int i, ret; + thrTtpool_work *cur_nodep; + + if ((ret = pthread_mutex_lock(&(tpool->queue_lock))) != 0) + fprintf(stderr, "pthread_mutex_lock %d", ret), exit(1); + + /* Is a shutdown already in progress? */ + if (tpool->queue_closed || tpool->shutdown) { + if ((ret = pthread_mutex_unlock(&(tpool->queue_lock))) != 0) + fprintf(stderr, "pthread_mutex_unlock %d", ret), exit(1); + return 0; + } + tpool->queue_closed = 1; + + if (finish == 1) { + while (tpool->cur_queue_size != 0) { + if ((ret = pthread_cond_wait(&(tpool->queue_empty), + &(tpool->queue_lock))) != 0) + fprintf(stderr, "pthread_cond_wait %d", ret), exit(1); + } + } + tpool->shutdown = 1; + + if ((ret = pthread_mutex_unlock(&(tpool->queue_lock))) != 0) + fprintf(stderr, "pthread_mutex_unlock %d", ret), exit(1); + + + if ((ret = pthread_cond_signal(&(tpool->queue_not_empty))) != 0) + fprintf(stderr, "pthread_cond_signal %d", ret), exit(1); + if ((ret = pthread_cond_broadcast(&(tpool->queue_not_full))) != 0) + fprintf(stderr, "pthread_cond_broadcast %d", ret), exit(1); + + + for (i = 0; i < tpool->num_threads; i++) { + if ((ret = pthread_cancel(tpool->threads[i])) != 0) + logFmsg(2, "tpool: pthread_cancel (e:%d)", ret); + + if ((ret = pthread_join(tpool->threads[i], NULL)) != 0) + logFmsg(2, "tpool: pthread_join (e:%d)", ret); + } + + free(tpool->threads); + while (tpool->queue_head != NULL) { + cur_nodep = tpool->queue_head->next; + tpool->queue_head = tpool->queue_head->next; + free(cur_nodep); + } + free(tpool); + + return 1; +} + +void *thrFthread(void *arg) +{ + thrTinfo *info = (thrTinfo *) arg; + int ret; + thrTtpool_work *my_workp; + + info->tpool->threads[info->index] = pthread_self(); + info->tpool->trigger[info->index].tid = pthread_self(); + if (pthread_setspecific + (thrKtrigger, &info->tpool->trigger[info->index]) + != 0) { + logFmsg(2, "thrFthread: pthread_setspecific() failed. e: %d", + errno); + logFmsg(3, "thrFthread: Failed to register I/O trigger."); + exit(0); + } + while (1) { + if ((ret = pthread_mutex_lock(&(info->tpool->queue_lock))) != 0) { + logFmsg(2, "tpool: Mutex lock returned error. (e: %d)", ret); + } + while ((info->tpool->cur_queue_size == 0) + && (!info->tpool->shutdown)) { + if ((ret = + pthread_cond_wait(&(info->tpool->queue_not_empty), + &(info->tpool->queue_lock))) != 0) { + logFmsg(2, "tpool: cond_wait returned fatally. (e: %d)", + ret); + exit(1); + } + } + + info->tpool->inuse++; + + if (info->tpool->shutdown == 1) { + if ((ret = + pthread_mutex_unlock(&(info->tpool->queue_lock))) != 0) { + logFmsg(2, "tpool: pthread_mutex_unlock (e: %d)", ret); + exit(1); + } + free(info); + pthread_exit(NULL); + } + my_workp = info->tpool->queue_head; + info->tpool->cur_queue_size--; + + if (info->tpool->cur_queue_size == 0) { + info->tpool->queue_head = info->tpool->queue_tail = NULL; + } else { + info->tpool->queue_head = my_workp->next; + } + + /* Handle waiting add_work threads */ + if ((!info->tpool->blocking_mode) && + (info->tpool->cur_queue_size == + (info->tpool->max_queue_size - 1))) { + if ((ret = + pthread_cond_broadcast(&(info->tpool->queue_not_full))) != + 0) { + logFmsg(2, "itpool: pthread_cond_broadcast (e: %d)", ret); + exit(1); + } + } + /* Handle waiting destroyer threads */ + if (info->tpool->cur_queue_size == 0) { + if ((ret = + pthread_cond_signal(&(info->tpool->queue_empty))) != 0) { + logFmsg(2, "pthread_cond_signal (e:%d)", ret); + exit(1); + } + } + if ((ret = pthread_mutex_unlock(&(info->tpool->queue_lock))) != 0) { + logFmsg(2, "tpool: pthread_mutex_unlock (e: %d)", ret); + exit(1); + } + (*(my_workp->routine)) (my_workp->arg); + free(my_workp); + info->tpool->inuse--; + } +} diff --git a/lc-continuity/mk4/continuity/mecha/tls.c b/lc-continuity/mk4/continuity/mecha/tls.c new file mode 100644 index 0000000000000000000000000000000000000000..d53c3ad1836e815bfcbb381aa2aaf7083c4faf5d --- /dev/null +++ b/lc-continuity/mk4/continuity/mecha/tls.c @@ -0,0 +1,231 @@ +/* + * $Header: /san01/cvs/ashpool/csrc/continuity/mecha/Attic/tls.c,v 1.9 2004/04/30 13:41:56 aleigh Exp $ + */ + +/* + * Copyright (c) 1994, 2004 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Disclosure, copying, distribution, or transmission of this code without + * express permission is prohibited. + */ + +#include "mecha.h" + +static pthread_key_t tls_key; +static void **clean_funcs; +static int clean_count = 0; + +struct tlsSent { + void *data; + int class; + char *name; + struct tlsSent *next; +}; +typedef struct tlsSent tlsTent; + +static void tlsFfree(tlsTent * p); + +static void tlsFadd_internal(void *data, char *name, int class); + +#undef TLS_DEBUG + +/* + * Allow another piece of code to register a cleanup handler. This function + * will return an integer which is the TLS class. This class needs to be + * provided for subsequent calls to the TLS system. + */ +int tlsFregister(void *(*clean_fn) (void *)) +{ + if (clean_count == 0) { + clean_funcs = (void *) malloc(sizeof(void *)); + clean_funcs[0] = (void *) clean_fn; + clean_count++; + } else { + clean_count++; + clean_funcs = realloc(clean_funcs, sizeof(void *) * clean_count); + clean_funcs[clean_count - 1] = (void *) clean_fn; + } + return clean_count - 1; +} + +/* + * Free a TLS entry and call it's associated cleanup function if it has + * client data + */ +static void tlsFfree(tlsTent * p) +{ + void (*f) (void *data); + +#ifdef TLS_DEBUG + logFmsg(3, "tlsFfree: freeing a TLS entity %s class %d data 0x%x", + p->name, p->class, p->data); +#endif + + if (p->data != NULL) { + + f = (void (*)(void *)) clean_funcs[p->class]; +#ifdef TLS_DEBUG + logFmsg(3, "tlsFfree: calling 0x%x for cleanup", f); +#endif + (*f) (p->data); + } + free(p->name); + free(p); +} + +/* + * Destroy an entire TLS list, calling any associated cleanup functions for + * it's client data. + */ +void tlsFdestroy(void *p) +{ + tlsTent *ent, *next = NULL; + + if (p == NULL) + return; + + ent = (tlsTent *) p; + + while (1) { + next = ent->next; + tlsFfree(ent); + if (next == NULL) + return; + ent = next; + } +} + +/* + * Remove all of a thread's TLS storage. + */ +void tlsFclean(void) +{ + tlsTent *p; + + p = pthread_getspecific(tls_key); + if (p == NULL) + return; + + tlsFdestroy(p); + pthread_setspecific(tls_key, NULL); +} + +void tlsFinit(void) +{ + if (pthread_key_create(&tls_key, tlsFdestroy) != 0) { +#ifdef TLS_DEBUG + logFmsg(2, "tls: Unable to register tls_key. [e: %d]", errno); +#endif + abort(); + } + tlsFregister((void *(*)(void *)) lstFset_free); +} + +void tlsFadd(void *data, char *name, int class) +{ + tlsFadd_internal(data, strFcopy(name), class); +} + +static void tlsFadd_internal(void *data, char *name, int class) +{ + tlsTent *tls; + tlsTent *ent; + +#ifdef TLS_DEBUG + logFmsg(3, "tlsFadd: called to add: 0x%x %s %d", data, name, class); +#endif + ent = malloc(sizeof(tlsTent)); + ent->name = name; + ent->data = data; + ent->class = class; + + tls = pthread_getspecific(tls_key); + + if (tls == NULL) { + ent->next = NULL; + } else { + /* TODO: Lame */ + ent->next = tls; + } + + if (pthread_setspecific(tls_key, ent) != 0) { + logFmsg(2, "tlsFadd: setspecific failed. [e: %d]", errno); + } +#ifdef TLS_DEBUG + else { + + logFmsg(3, "tlsFadd: setspecific 0."); + } +#endif +} + +void tlsFdel(char *name, int class) +{ + tlsTent *e; + void *(*f) (void *data); + +#ifdef TLS_DEBUG + logFmsg(3, "tlsFdel: called for %s %d", name, class); +#endif + + e = pthread_getspecific(tls_key); + + for (; e != NULL; e = e->next) { + /* We do this as two to avoid the strcmp for other classes */ + if (e->class == class) { + if (strcmp(name, e->name) == 0) { +#ifdef TLS_DEBUG + logFmsg(3, "tlsFdel: found match"); +#endif + if (e->data != NULL) { + f = (void *(*)(void *)) clean_funcs[e->class]; + (*f) (e->data); + e->data = NULL; + } + } + } + } +} + +void *tlsFget(char *name, int class) +{ + tlsTent *e; + + assert(name != NULL); + + e = pthread_getspecific(tls_key); + +#ifdef TLS_DEBUG + logFmsg(3, "tlsFget: e is 0x%x", e); +#endif + + if (e == NULL) + return NULL; + + while (1) { + if (strcmp(e->name, name) == 0 && e->class == class) { +#ifdef TLS_DEBUG + logFmsg(3, "tlsFget: returning 0x%x", e->data); +#endif + return e->data; + } + if (e->next == NULL) + return NULL; + e = e->next; + } +} + +char *tlsFadd_makeid(void *data, int class) +{ + char *id = malloc(sizeof(char) * 37); + + uidFgenerate_str(id, 37); + + tlsFadd_internal(data, id, class); + + return id; +} diff --git a/lc-continuity/mk4/continuity/mecha/uid.c b/lc-continuity/mk4/continuity/mecha/uid.c new file mode 100644 index 0000000000000000000000000000000000000000..bd135ec03533243dc69e05650d62bb1902937148 --- /dev/null +++ b/lc-continuity/mk4/continuity/mecha/uid.c @@ -0,0 +1,148 @@ +/* + * $Header: /san01/cvs/ashpool/csrc/continuity/mecha/Attic/uid.c,v 1.9 2004/04/30 13:41:56 aleigh Exp $ + */ + +/* + * Copyright (c) 1994, 2004 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Use, disclosure, copying, distribution, or transmission of of this code without + * express permission is prohibited. + */ + +typedef unsigned char uuidTpack[16]; + +#include "mecha.h" + +struct uuidSid { + uint32_t time_low; + uint16_t time_mid; + uint16_t time_hi_and_version; + uint16_t clock_seq; + uint8_t node[6]; +}; +typedef struct uuidSid uuidTid; + +static void uuidFpack(uuidTid * uu, uuidTpack * ptr); +static void uuidFgenerate(uuidTpack * out); +static void uuidFunpack(uuidTpack * in, uuidTid * uu); +static void uuidFunparse(uuidTpack * uu, char *out); + +static void uuidFunpack(uuidTpack * in, uuidTid * uu) +{ + uint8_t *ptr = (uint8_t *) in; + uint32_t tmp; + + tmp = *ptr++; + tmp = (tmp << 8) | *ptr++; + tmp = (tmp << 8) | *ptr++; + tmp = (tmp << 8) | *ptr++; + uu->time_low = tmp; + + tmp = *ptr++; + tmp = (tmp << 8) | *ptr++; + uu->time_mid = tmp; + + tmp = *ptr++; + tmp = (tmp << 8) | *ptr++; + uu->time_hi_and_version = tmp; + + tmp = *ptr++; + tmp = (tmp << 8) | *ptr++; + uu->clock_seq = tmp; + + memcpy(uu->node, ptr, 6); +} + +static void uuidFunparse(uuidTpack * uu, char *out) +{ + uuidTid uuid; + + uuidFunpack(uu, &uuid); + sprintf(out, + "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + uuid.time_low, uuid.time_mid, uuid.time_hi_and_version, + uuid.clock_seq >> 8, uuid.clock_seq & 0xFF, + uuid.node[0], uuid.node[1], uuid.node[2], + uuid.node[3], uuid.node[4], uuid.node[5]); +} + +static void uuidFpack(uuidTid * uu, uuidTpack * ptr) +{ + uint32_t tmp; + unsigned char *out = (unsigned char *) ptr; + + tmp = uu->time_low; + out[3] = (unsigned char) tmp; + tmp >>= 8; + out[2] = (unsigned char) tmp; + tmp >>= 8; + out[1] = (unsigned char) tmp; + tmp >>= 8; + out[0] = (unsigned char) tmp; + + tmp = uu->time_mid; + out[5] = (unsigned char) tmp; + tmp >>= 8; + out[4] = (unsigned char) tmp; + + tmp = uu->time_hi_and_version; + out[7] = (unsigned char) tmp; + tmp >>= 8; + out[6] = (unsigned char) tmp; + + tmp = uu->clock_seq; + out[9] = (unsigned char) tmp; + tmp >>= 8; + out[8] = (unsigned char) tmp; + + memcpy(out + 10, uu->node, 6); +} + +/* + * generates a UUID based on the current time on the platform. + */ +static void uuidFgenerate(uuidTpack * out) +{ + static unsigned char node_id[6]; + uuidTid uu; + uint32_t clock_mid; + uint32_t node_number; + + if ((node_number = utlFgethostid()) == 0) { + rndFrandom_bytes(node_id, 6); + /* + * Set multicast bit, to prevent conflicts with IEEE 802 addresses + * obtained from network cards + */ + node_id[0] |= 0x80; + } else { + memcpy(node_id, (char *) &node_number, 4); + } + + utlFclock_get(&clock_mid, &uu.time_low, &uu.clock_seq); + uu.clock_seq |= 0x8000; + uu.time_mid = (uint16_t) clock_mid; + uu.time_hi_and_version = (clock_mid >> 16) | 0x1000; + memcpy(uu.node, node_id, 6); + uuidFpack(&uu, out); +} + +/* Generate a uuid, and write it into the provided buffer. */ + +int uidFgenerate_str(char *id, size_t len) +{ + uuidTpack uuid; + + if (len < 37) + return -1; + + memFclear(&uuid, sizeof(uuidTpack)); + uuidFgenerate(&uuid); + uuidFunparse(&uuid, id); + + return 0; +} diff --git a/lc-continuity/mk4/continuity/mecha/utl.c b/lc-continuity/mk4/continuity/mecha/utl.c new file mode 100644 index 0000000000000000000000000000000000000000..b783ba17d464caae69bbccc5036f2d30ffb5b51f --- /dev/null +++ b/lc-continuity/mk4/continuity/mecha/utl.c @@ -0,0 +1,868 @@ +/* + * $Header: /san01/cvs/ashpool/csrc/continuity/mecha/Attic/utl.c,v 1.31 2004/05/13 14:11:25 aleigh Exp $ + */ + +/* + * Copyright (c) 1994, 2004 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Disclosure, copying, distribution, or transmission of of this code without + * express permission is prohibited. + */ + +#include "mecha.h" + +struct utlSswatch { + unsigned int sa_sec; + unsigned int sa_usec; + unsigned int so_sec; + unsigned int so_usec; + unsigned int e_sec; + unsigned int e_usec; + unsigned int e_msec; +}; + +/* + * Stolen from Eric Lindvall 5stops.com + */ +int utlFfd_printf(int fd, const char *fmt, ...) +{ + va_list ap; + char *buf; + int size = 1024; + int e; + + assert(fmt != NULL); + + buf = (char *) malloc(size); + + assert(buf != NULL); + + va_start(ap, fmt); + + while (1) { + int nchars = vsnprintf(buf, size, fmt, ap); + + if (nchars > -1 && nchars < size) + break; + if (nchars > -1) + size = nchars + 1; + else + size *= 2; + buf = (char *) realloc(buf, size); + } + + va_end(ap); + + if ((e = write(fd, buf, strlen(buf))) == -1) + e = -errno; + + free(buf); + + return (e); +} + +unsigned int utlFtime(void) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + + return tv.tv_sec; +} + +/* + * under solaris 2.7, localtime is not MT-safe. localtime_r instead. + * + * this is very crude, and not necessarily the kind of thing that we really want + * to endorse, but it seems effective enough at 560/sec rates. + */ +volatile const struct tm *utlFlocaltime(void) +{ + static struct tm cache_tm; + static unsigned int cache_time; + static unsigned int processing = 0; + unsigned int now; + + now = utlFtime(); + + if (now != cache_time && processing == 0) { + processing = 1; + cache_time = now; + localtime_r((time_t *) & now, &cache_tm); + processing = 0; + } + return &cache_tm; +} + +static const char utlGmonths[48] = + "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec "; +static const char utlGdays[] = "Sun,Mon,Tue,Wed,Thu,Fri,Sat,"; + +/* + * Returns the time in common log format. This returned string is always 29 + * characters long. This looks kind of dubious, but it seems to work quite + * well. + */ +volatile const char *utlFcommonlog_time(void) +{ + volatile const struct tm *t = utlFlocaltime(); + char *p; + unsigned int a; + static char buf[30]; + int time_offset = 0; + + assert(t != NULL); + + p = buf + 29; + *p-- = '\0'; + *p-- = ' '; + *p-- = ']'; + a = abs(time_offset / 60); + *p-- = '0' + a % 10; + a /= 10; + *p-- = '0' + a % 6; + a /= 6; + *p-- = '0' + a % 10; + *p-- = '0' + a / 10; + *p-- = (time_offset > 0) ? '-' : '+'; + *p-- = ' '; + + a = t->tm_sec; + *p-- = '0' + a % 10; + *p-- = '0' + a / 10; + *p-- = ':'; + a = t->tm_min; + *p-- = '0' + a % 10; + *p-- = '0' + a / 10; + *p-- = ':'; + a = t->tm_hour; + *p-- = '0' + a % 10; + *p-- = '0' + a / 10; + *p-- = ':'; + a = 1900 + t->tm_year; + while (a) { + *p-- = '0' + a % 10; + a /= 10; + } + /* p points to an unused spot */ + *p-- = '/'; + p -= 2; + memcpy(p--, utlGmonths + 4 * (t->tm_mon), 3); + *p-- = '/'; + a = t->tm_mday; + *p-- = '0' + a % 10; + *p-- = '0' + a / 10; + *p = '['; + return p; /* should be same as returning buf */ +} + +volatile const char *utlFlocal_time(void) +{ + volatile const struct tm *t; + char *p; + unsigned int a; + static char buf[30]; + + t = utlFlocaltime(); + + assert(t != NULL); + + p = buf + 29; + *p-- = '\0'; + *p-- = ']'; + + a = t->tm_sec; + *p-- = '0' + a % 10; + *p-- = '0' + a / 10; + *p-- = ':'; + a = t->tm_min; + *p-- = '0' + a % 10; + *p-- = '0' + a / 10; + *p-- = ':'; + a = t->tm_hour; + *p-- = '0' + a % 10; + *p-- = '0' + a / 10; + *p-- = ':'; + a = 1900 + t->tm_year; + while (a) { + *p-- = '0' + a % 10; + a /= 10; + } + /* p points to an unused spot */ + *p-- = '/'; + p -= 2; + memcpy(p--, utlGmonths + 4 * (t->tm_mon), 3); + *p-- = '/'; + a = t->tm_mday; + *p-- = '0' + a % 10; + *p-- = '0' + a / 10; + *p = '['; + return p; /* should be same as returning buf */ +} + +utlTswatch *utlFstart_swatch(void) +{ + struct timeval tv; + utlTswatch *sw; + + gettimeofday(&tv, NULL); + + sw = malloc(sizeof(utlTswatch)); + memFclear(sw, sizeof(utlTswatch)); + + sw->sa_sec = tv.tv_sec; + sw->sa_usec = tv.tv_usec; + + return sw; +} + +unsigned int utlFstop_swatch(utlTswatch * sw) +{ + struct timeval tv; + unsigned int x; + + assert(sw != NULL); + + gettimeofday(&tv, NULL); + + sw->so_sec = tv.tv_sec; + sw->so_usec = tv.tv_usec; + + sw->e_sec = sw->so_sec - sw->sa_sec; + sw->e_usec = sw->so_usec - sw->sa_usec; + + x = (sw->e_sec * 1000) * 1000 + (sw->e_usec); + + free(sw); + + return x; +} + +int utlFtv_sub(struct timeval *r, const struct timeval *x, + const struct timeval *y) +{ + struct timeval working; + + assert(r != NULL); + assert(x != NULL); + assert(y != NULL); + + + memcpy(&working, y, sizeof(struct timeval)); + + if (x->tv_usec < working.tv_usec) { + int nsec = (working.tv_usec - x->tv_usec) / 1000000L + 1; + working.tv_usec -= 1000000L * nsec; + working.tv_sec += nsec; + } + if (x->tv_usec - working.tv_usec > 1000000L) { + int nsec = (x->tv_usec - working.tv_usec) / 1000000L; + working.tv_usec += 1000000L * nsec; + working.tv_sec -= nsec; + } + r->tv_sec = x->tv_sec - working.tv_sec; + r->tv_usec = x->tv_usec - working.tv_usec; + + /* Return 1 if result is negative. */ + return x->tv_sec < working.tv_sec; +} + +int utlFip_to_str(unsigned int ip, char *buf, size_t buflen) +{ + int a, b, c, d; + int carry; + + assert(buf != NULL); + + a = ip / 16777216; + carry = ip % 16777216; + + b = carry / 65536; + carry = carry % 65536; + + c = carry / 256; + d = carry % 256; + + return snprintf(buf, buflen, "%d.%d.%d.%d", a, b, c, d); +} + +unsigned int utlFstr_to_ip(const char *ip) +{ + return ntohl(inet_addr(ip)); +} + +int utlFisnum(const char c) +{ + return (c >= '0' && c <= '9' ? 1 : 0); +} + +/* check to see if the given string contains any alphas or is just numbers */ +int utlFstr_has_alphas(const char *p) +{ + const char *c; + int ret = 0; + + assert(p != NULL); + + for (c = p; *c != 0; c++) { + if (utlFisnum(*c) == 0) + ret = 1; + } + + return ret; +} + + +void utlFtv_add(struct timeval *res, struct timeval *t1, + struct timeval *t2) +{ + assert(res != NULL); + assert(t1 != NULL); + assert(t2 != NULL); + + res->tv_sec = t1->tv_sec + t2->tv_sec; + res->tv_usec = t1->tv_usec + t2->tv_usec; + + res->tv_sec += res->tv_usec / 1000000L; + + res->tv_usec %= 1000000L; +} + + +long utlFtv_to_ms(struct timeval *tv) +{ + assert(tv != NULL); + return (tv->tv_sec * 1000 + tv->tv_usec / 1000); +} + +/* + * Encode an URL in the URL encoding format. Arguments are an empty dynamic + * string that will contain the output encoding, and string, which is the + * string to be encoded. A pointer to the string content of the ds will be + * returned on success. + */ + +int utlFurl_encode(dynTstring * dyn, const char *string) +{ + static char safechars[] = + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789:/."; + + assert(dyn != NULL); + + if (string == NULL) + return -1; + + assert(dyn != NULL); + + while (*string != '\0') { + if (strchr(safechars, *string) != NULL) { + dynFappend(dyn, string, 1); + } else { + char buf[4]; + sprintf(buf, "%%%02x", (unsigned char) *string); + dynFappend(dyn, buf, 3); + } + ++string; + } + return 0; +} + +int utlFurl_decode(dynTstring * dyn, const char *string) +{ + unsigned char decoded; + char twobytes[3]; + + assert(dyn != NULL); + assert(string != NULL); + + twobytes[2] = '\0'; + while (*string != '\0') { + + if (*string == '+') { + dynFappend(dyn, " ", 1); + string++; + continue; + } + if (*string != '%') { + dynFappend(dyn, string, 1); + string++; + } else { + if (utlFhexdigit(string[1]) && utlFhexdigit(string[2])) { + twobytes[0] = string[1]; + twobytes[1] = string[2]; + decoded = + (unsigned char) strtol(twobytes, (char **) NULL, 16); + dynFappend(dyn, (char *) &decoded, 1); + string += 3; + } else { + return 0; + } + } + } + return 0; +} + +int utlFhexdigit(char c) +{ + static char hexdigits[] = "0123456789ABCDEFabcdef"; + return (c != '\0' && (strchr(hexdigits, c) != NULL)); +} + +/* + * return a 32-bit number identifying this machine. For Sun, this is the + * hostid. For other PC platforms it should probably return the MAC address + * of the 1st Ethernet controller. + */ +uint32_t utlFgethostid(void) +{ +#ifdef SOLARIS + return gethostid(); +#else + return 0; +#endif +} + +/* Microsecond granularity */ +#define MAX_ADJUSTMENT 10 + +int utlFclock_get(uint32_t * clock_high, uint32_t * clock_low, + uint16_t * ret_clock_seq) +{ + static int adjustment = 0; + static struct timeval last = { 0, 0 }; + uint16_t clock_seq; + struct timeval tv; + unsigned long long clock_reg; + + assert(clock_high != NULL); + assert(clock_low != NULL); + assert(ret_clock_seq != NULL); + + try_again: + gettimeofday(&tv, 0); + if ((last.tv_sec == 0) && (last.tv_usec == 0)) { + rndFrandom_bytes((unsigned char *) &clock_seq, sizeof(clock_seq)); + clock_seq &= 0x1FFF; + last = tv; + last.tv_sec--; + } + if ((tv.tv_sec < last.tv_sec) || + ((tv.tv_sec == last.tv_sec) && (tv.tv_usec < last.tv_usec))) { + clock_seq = (clock_seq + 1) & 0x1FFF; + adjustment = 0; + } else if ((tv.tv_sec == last.tv_sec) && (tv.tv_usec == last.tv_usec)) { + if (adjustment >= MAX_ADJUSTMENT) + goto try_again; + adjustment++; + } else + adjustment = 0; + + clock_reg = tv.tv_usec * 10 + adjustment; + clock_reg += ((unsigned long long) tv.tv_sec) * 10000000; + clock_reg += (((unsigned long long) 0x01B21DD2) << 32) + 0x13814000; + + *clock_high = clock_reg >> 32; + *clock_low = clock_reg; + *ret_clock_seq = clock_seq; + return 0; +} + +/* + * Parse 'when' into HTTP format time, GMT. The receiving buffer must be at + * least 40 characters to fully fit the time. + */ +size_t utlFhttp_time_print(time_t when, char *buf, size_t buflen) +{ + struct tm tmp; + + assert(buf != NULL); + + gmtime_r(&when, &tmp); + tmp.tm_isdst = 0; + + return strftime(buf, buflen, "%a, %d %b %Y %H:%M:%S GMT", &tmp); +} + + +static const char *month_names[12] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" +}; + +static int MakeMonth(char *s) +{ + int i; + + assert(s != NULL); + + /* + * Make sure it's capitalized like this: "Jan" + */ + + *s = toupper(*s); + *(s + 1) = tolower(*(s + 1)); + *(s + 2) = tolower(*(s + 2)); + + for (i = 0; i < 12; i++) { + if (!strncmp(month_names[i], s, 3)) { + return i; + } + } + return 0; +} + +static int MakeNum(char *s) +{ + assert(s != NULL); + + if (*s >= '0' && *s <= '9') { + return (10 * (*s - '0')) + (*(s + 1) - '0'); + } else { + return *(s + 1) - '0'; + } +} + +time_t utlFhttp_time_parse(char *str) +{ + char *s; + struct tm tm; + time_t t; + time_t toff; + + if (str == NULL) { + return 0; + } + /* + * Find the comma after day-of-week + * + * Thursday, 10-Jun-93 01:29:59 GMT ^ +-- s + * + * Thu, 10 Jan 1993 01:29:59 GMT ^ +-- s + */ + + s = strchr(str, ','); + if (s != NULL) { + + /* + * Advance S to the first non-space after the comma which should be + * the first digit of the day. + */ + + s++; + while (*s && *s == ' ') { + s++; + } + + /* + * Figure out which format it is in. If there is a hyphen, then it + * must be the first format. + */ + + if (strchr(s, '-') != NULL) { + if (strlen(s) < 18) { + return 0; + } + /* + * The format is: + * + * Thursday, 10-Jun-93 01:29:59 GMT ^ +--s + */ + + tm.tm_mday = MakeNum(s); + tm.tm_mon = MakeMonth(s + 3); + tm.tm_year = MakeNum(s + 7); + tm.tm_hour = MakeNum(s + 10); + tm.tm_min = MakeNum(s + 13); + tm.tm_sec = MakeNum(s + 16); + } else { + if ((int) strlen(s) < 20) { + return 0; + } + /* + * The format is: + * + * Thu, 10 Jan 1993 01:29:59 GMT Thu, 10 Jan 1993 01:29:59 GMT ^ + * +--s + */ + + tm.tm_mday = MakeNum(s); + tm.tm_mon = MakeMonth(s + 3); + tm.tm_year = (100 * MakeNum(s + 7) - 1900) + MakeNum(s + 9); + tm.tm_hour = MakeNum(s + 12); + tm.tm_min = MakeNum(s + 15); + tm.tm_sec = MakeNum(s + 18); + } + } else { + + /* + * No commas, so it must be the third, fixed field, format: + * + * Wed Jun 9 01:29:59 1993 GMT + * + * Advance s to the first letter of the month. + */ + + s = str; + while (*s && *s == ' ') { + s++; + } + if ((int) strlen(s) < 24) { + return 0; + } + tm.tm_mday = MakeNum(s + 8); + tm.tm_mon = MakeMonth(s + 4); + tm.tm_year = MakeNum(s + 22); + tm.tm_hour = MakeNum(s + 11); + tm.tm_min = MakeNum(s + 14); + tm.tm_sec = MakeNum(s + 17); + } + + /* + * If there are any impossible values, then return an error. + */ + + if (tm.tm_sec < 0 || tm.tm_sec > 59 || + tm.tm_min < 0 || tm.tm_min > 59 || + tm.tm_hour < 0 || tm.tm_hour > 23 || + tm.tm_mday < 1 || tm.tm_mday > 31 || + tm.tm_mon < 0 || tm.tm_mon > 11 || tm.tm_year < 70 + || tm.tm_year > 120) { + return 0; + } + tm.tm_isdst = 0; + toff = (time_t) timezone; + t = mktime(&tm) - toff; + return t; +} + +int utlFgetuid (const char *username) +{ + struct passwd pw; + + assert(username != NULL); + + if (utlFget_pwname(username, &pw) == -1) { + return -1; + } else { + return pw.pw_uid; + } +} + +int utlFgetgid (const char *username) +{ + struct passwd pw; + + assert(username != NULL); + + if (utlFget_pwname(username, &pw) == -1) { + return -1; + } else { + return pw.pw_gid; + } +} + +int utlFget_pwname(const char *username, struct passwd *pw) +{ + struct passwd *pwptr; + char pwbuf[512]; + + assert(username != NULL); + assert(pw != NULL); + +#ifdef SOLARIS + if ((pwptr = getpwnam_r(username, pw, pwbuf, 512)) != NULL) { +#else + if (!getpwnam_r(username, pw, pwbuf, 512, &pwptr) && pwptr) { +#endif + + /* Do Nothing */ + } else { + if (errno == 0) { + /* this can happen with getpwnam() on FreeBSD 4.3 */ + return -1; + } + return -1; + } + return 0; +} + +int utlFget_homedir(const char *username, char *dir, size_t dir_len) +{ +#ifndef WIN32 + struct passwd pw; + size_t len; + + assert(username != NULL); + assert(dir != NULL); + assert(dir_len > 0); + + if (utlFget_pwname(username, &pw) != 0) + return -1; + + len = strlen(pw.pw_dir); + + /* NULL */ + len++; + if (len > dir_len) + return -1; + + memcpy(dir, pw.pw_dir, len); + + return len; +#else + return -1; +#endif +} + +void utlFhours_to_hourmin(double in_time, int *hours, int *mins) +{ + *mins = in_time * 60; + *hours = *mins / 60; + *mins = *mins % 60; +} + +double utlFhourmin_to_hours(const int hours, const int mins) +{ + return hours + ((double) mins / 60.0); +} + +int utlFip_match(unsigned int ipa, unsigned int ipb, unsigned int netmask) +{ + if ((ipa & netmask) == (ipb & netmask)) + return 1; + return 0; +} + +int utlFip_validate(const char *addr) { + int dot_count; + int digit_count; + + dot_count = 0; + digit_count = 0; + while(*addr != '\0' && *addr != ' ') { + if(*addr == '.') { + dot_count++; + digit_count = 0; + } + else if(!isdigit(*addr)) { + dot_count = 5; + } + else { + digit_count++; + if(digit_count > 3) { + dot_count = 5; + } + } + addr++; + } + if(dot_count != 3) { + return(-1); + } + else { + return(0); + } +} + +static const char *utlGnumber_lut[] = { + "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", + "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", + "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", + "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", + "48", "49", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", + "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "70", "71", + "72", "73", "74", "75", "76", "77", "78", "79", "80", "81", "82", "83", + "84", "85", "86", "87", "88", "89", "90", "91", "92", "93", "94", "95", + "96", "97", "98", "99", "100", "101", "102", "103", "104", "105", + "106", + "107", "108", "109", "110", "111", "112", "113", "114", "115", "116", + "117", "118", "119", "120", "121", "122", "123", "124", "125", "126", + "127", "128", "129", "130", "131", "132", "133", "134", "135", "136", + "137", "138", "139", "140", "141", "142", "143", "144", "145", "146", + "147", "148", "149", "150", "151", "152", "153", "154", "155", "156", + "157", "158", "159", "160", "161", "162", "163", "164", "165", "166", + "167", "168", "169", "170", "171", "172", "173", "174", "175", "176", + "177", "178", "179", "180", "181", "182", "183", "184", "185", "186", + "187", "188", "189", "190", "191", "192", "193", "194", "195", "196", + "197", "198", "199", "200", "201", "202", "203", "204", "205", "206", + "207", "208", "209", "210", "211", "212", "213", "214", "215", "216", + "217", "218", "219", "220", "221", "222", "223", "224", "225", "226", + "227", "228", "229", "230", "231", "232", "233", "234", "235", "236", + "237", "238", "239", "240", "241", "242", "243", "244", "245", "246", + "247", "248", "249", "250", "251", "252", "253", "254", "255" +}; + +const char *utlFshort_to_str(unsigned short n) +{ + return utlGnumber_lut[n]; +} + +unsigned int utlFatoui(const char *s) { + assert(sizeof(unsigned long)==sizeof(unsigned int)); + + return (unsigned int)strtoul(s, (char **)NULL, 0); +} + +int utlFatoi(const char *s) { + return (int) strtol (s, (char **)NULL, 10); +} + +void utlFhexdump(void *data, size_t size) +{ + /* dumps size bytes of *data to stdout. Looks like: + * [0000] 75 6E 6B 6E 6F 77 6E 20 + * 30 FF 00 00 00 00 39 00 unknown 0.....9. + * (in a single line of course) + */ + + unsigned char *p = data; + unsigned char c; + int n; + char bytestr[4] = {0}; + char addrstr[10] = {0}; + char hexstr[ 16*3 + 5] = {0}; + char charstr[16*1 + 5] = {0}; + for(n=1;n<=size;n++) { + if (n%16 == 1) { + /* store address for this line */ + snprintf(addrstr, sizeof(addrstr), "%.4x", + ((unsigned int)p-(unsigned int)data) ); + } + + c = *p; + if (isalnum(c) == 0) { + c = '.'; + } + + /* store hex str (for left side) */ + snprintf(bytestr, sizeof(bytestr), "%02X ", *p); + strncat(hexstr, bytestr, sizeof(hexstr)-strlen(hexstr)-1); + + /* store char str (for right side) */ + snprintf(bytestr, sizeof(bytestr), "%c", c); + strncat(charstr, bytestr, sizeof(charstr)-strlen(charstr)-1); + + if(n%16 == 0) { + /* line completed */ + printf("[%4.4s] %-50.50s %s\n", addrstr, hexstr, charstr); + hexstr[0] = 0; + charstr[0] = 0; + } else if(n%8 == 0) { + /* half line: add whitespaces */ + strncat(hexstr, " ", sizeof(hexstr)-strlen(hexstr)-1); + strncat(charstr, " ", sizeof(charstr)-strlen(charstr)-1); + } + p++; /* next byte */ + } + + if (strlen(hexstr) > 0) { + /* print rest of buffer if not empty */ + printf("[%4.4s] %-50.50s %s\n", addrstr, hexstr, charstr); + } +} + + diff --git a/lc-continuity/mk4/continuity/mecha/w32.c b/lc-continuity/mk4/continuity/mecha/w32.c new file mode 100644 index 0000000000000000000000000000000000000000..68ff4d65098e0407c8da5aff6c409870a1358913 --- /dev/null +++ b/lc-continuity/mk4/continuity/mecha/w32.c @@ -0,0 +1,102 @@ +/* + * $Header: /san01/cvs/ashpool/csrc/continuity/mecha/Attic/w32.c,v 1.5 2004/04/30 13:41:56 aleigh Exp $ + */ + +/* + * Copyright (c) 2004 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Use, disclosure, copying, distribution, or transmission of this code without + * express permission is prohibited. + */ + +#include "mecha.h" + +MECHA_UNUSED static int not_empty; + +#ifdef WIN32 + + +int gettimeofday(struct timeval *time_Info, struct timezone *timezone_Info) +{ + static struct timeval starttime = { 0, 0 }; + static __int64 lasttime = 0; + static __int64 freq = 0; + __int64 timer; + LARGE_INTEGER li; + BOOL b; + double dt; + + /* Get the time, if they want it */ + if (time_Info != NULL) { + if (starttime.tv_sec == 0) { + b = QueryPerformanceFrequency(&li); + if (!b) { + starttime.tv_sec = -1; + } else { + freq = li.QuadPart; + b = QueryPerformanceCounter(&li); + if (!b) { + starttime.tv_sec = -1; + } else { + getfilesystemtime(&starttime); + timer = li.QuadPart; + dt = (double) timer / freq; + starttime.tv_usec -= (int) ((dt - (int) dt) * 1000000); + if (starttime.tv_usec < 0) { + starttime.tv_usec += 1000000; + --starttime.tv_sec; + } + starttime.tv_sec -= (int) dt; + } + } + } + if (starttime.tv_sec > 0) { + b = QueryPerformanceCounter(&li); + if (!b) { + starttime.tv_sec = -1; + } else { + timer = li.QuadPart; + if (timer < lasttime) { + getfilesystemtime(time_Info); + dt = (double) timer / freq; + starttime = *time_Info; + starttime.tv_usec -= (int) ((dt - (int) dt) * 1000000); + if (starttime.tv_usec < 0) { + starttime.tv_usec += 1000000; + --starttime.tv_sec; + } + starttime.tv_sec -= (int) dt; + } else { + lasttime = timer; + dt = (double) timer / freq; + time_Info->tv_sec = starttime.tv_sec + (int) dt; + time_Info->tv_usec = + starttime.tv_usec + + (int) ((dt - (int) dt) * 1000000); + if (time_Info->tv_usec > 1000000) { + time_Info->tv_usec -= 1000000; + ++time_Info->tv_sec; + } + } + } + } + if (starttime.tv_sec < 0) { + getfilesystemtime(time_Info); + } + } + /* Get the timezone, if they want it */ + if (timezone_Info != NULL) { + _tzset(); + timezone_Info->tz_minuteswest = _timezone; + timezone_Info->tz_dsttime = _daylight; + } + /* And return */ + return 0; +} + + +#endif diff --git a/lc-continuity/mk4/continuity/mecha/xml.c b/lc-continuity/mk4/continuity/mecha/xml.c new file mode 100644 index 0000000000000000000000000000000000000000..cba8ba6fb53251c0d8b1cae7db01d287d954e869 --- /dev/null +++ b/lc-continuity/mk4/continuity/mecha/xml.c @@ -0,0 +1,555 @@ +/* + * $Header: /san01/cvs/ashpool/csrc/continuity/mecha/Attic/xml.c,v 1.21 2004/04/30 13:41:56 aleigh Exp $ + */ + +/* + * Copyright (c) 2004 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Use, disclosure, copying, distribution, or transmission of this code without + * express permission is prohibited. + */ + +#include "mecha.h" + +#undef _XML_DEBUG + +struct xmlSiterator { + const struct xmlStag *first; + const struct xmlStag *tag; +}; + +struct xmlSconfig { + struct xmlStag *tags; +}; + +struct xmlStag { + char *name; /* My name */ + size_t name_len; + char *value; /* My string value, if I have one */ + size_t value_len; + lstTset *attrib_list; + struct xmlStag *linear_child; /* Child tags */ + struct xmlStag *linear_next; /* Brother Tag */ +}; + +static const char *xmlF_parse(const char *str, const char *level, + xmlTtag * parent, lstTset * arglist); +static void xmlFtag_addchild(xmlTtag * parent, xmlTtag * child); +static xmlTconfig *xmlFconfig_init(void); +static xmlTtag *xmlFtag_init(void); +static void xmlFtag_free(xmlTtag * tag); + +const xmlTtag *xmlFiterator_tag(xmlTiterator *it) { + assert(it!=NULL); + + return it->tag; +} + +const char *xmlFtag_get_name(const xmlTtag * tag, size_t * name_len) +{ + assert(tag != NULL); + assert(name_len != NULL); + + *name_len = tag->name_len; + return tag->name; +} + +const char *xmlFtag_get_value_str(const xmlTtag * tag) +{ + assert(tag != NULL); + + return tag->value; +} + +const char *xmlFtag_get_name_str(const xmlTtag * tag) +{ + assert(tag != NULL); + + return tag->name; +} + +const char *xmlFtag_get_value(const xmlTtag * tag, size_t * value_len) +{ + assert(tag != NULL); + assert(value_len != NULL); + + *value_len = tag->value_len; + return tag->value; +} + +const lstTset *xmlFtag_get_attribs(const xmlTtag * tag) +{ + assert(tag != NULL); + return tag->attrib_list; +} + +const xmlTtag *xmlFtag_get_children(const xmlTtag * tag) +{ + assert(tag != NULL); + + return tag->linear_child; +} + +xmlTiterator *xmlFiterator_init(const xmlTtag * tag) +{ + xmlTiterator *iterator; + + assert(tag != NULL); + + iterator = (xmlTiterator *) malloc(sizeof(xmlTiterator)); + + assert(iterator != NULL); + + iterator->tag = iterator->first = tag; + + return iterator; +} + +void xmlFiterator_reset(xmlTiterator *iterator) { + assert(iterator!=NULL); + iterator->tag=iterator->first; +} + +xmlTiterator *xmlFiterate_children(const xmlTtag * tag) +{ + xmlTiterator *iterator; + + assert(tag != NULL); + + if (tag->linear_child == NULL) + return NULL; + + iterator = (xmlTiterator *) malloc(sizeof(xmlTiterator)); + + iterator->tag = tag->linear_child; + + return iterator; +} + +void xmlFiterator_free(xmlTiterator * iterator) +{ + assert(iterator != NULL); + + free(iterator); +} + +const xmlTtag *xmlFiterator_next_name(xmlTiterator * iterator, + const char *name) +{ + const xmlTtag *t; + + assert(iterator!=NULL); + assert(name!=NULL); + +#ifdef _XML_DEBUG + logFmsg(3,"xmlFiterator_next_name: Called to search for %s", name); +#endif + + + while ((t = xmlFiterator_next(iterator)) != NULL) { +#ifdef _XML_DEBUG + logFmsg(3,"xmlFiterator_next_name: Testing '%s' == '%s'", t->name, name); +#endif + if (strcmp(t->name, name) == 0) { +#ifdef _XML_DEBUG + logFmsg(3,"xmlFiterator_next_name: Returning 0x%x", t); +#endif + return t; + } + } + +#ifdef _XML_DEBUG + logFmsg(3,"xmlFiterator_next_name: Returning NULL"); +#endif + + return NULL; +} + +const xmlTtag *xmlFfind_first_tag_children(const xmlTtag * tag, + const char *name) +{ + const xmlTtag *t; + + assert(tag!=NULL); + assert(name!=NULL); + + t = xmlFfind_first_tag(tag, name); + + if (t == NULL) { + return NULL; + } else { + return t->linear_child; + } +} + +const xmlTtag *xmlFfind_first_child(const xmlTtag *tag, const char *name) { + xmlTiterator *it; + const xmlTtag *match; + + assert(tag!=NULL); + assert(name!=NULL); + + it=xmlFiterate_children(tag); + + if(it==NULL) { + return NULL; + } + + match=xmlFiterator_next_name(it,name); + + xmlFiterator_free(it); + + return match; +} + +const xmlTtag *xmlFfind_first_tag(const xmlTtag * tag, const char *name) +{ + xmlTiterator *it; + const xmlTtag *t; + + assert(tag != NULL); + assert(name != NULL); + + it = xmlFiterator_init(tag); + + assert(it != NULL); + + t = xmlFiterator_next_name(it, name); + + xmlFiterator_free(it); + + return t; +} + +const xmlTtag *xmlFiterator_next(xmlTiterator * iterator) +{ + const xmlTtag *t; + + assert(iterator != NULL); + + if (iterator->tag == NULL) { + return NULL; + } + + t = iterator->tag; + + iterator->tag = iterator->tag->linear_next; + + return t; +} + +static xmlTconfig *xmlFconfig_init(void) +{ + xmlTconfig *config = (xmlTconfig *) malloc(sizeof(xmlTconfig)); + memFclear(config, sizeof(xmlTconfig)); + return config; +} + +/* + * But I will go down with this ship, and I won't hurt myself and surrender, + * there will be no white flag above my door -aleigh + */ + +static xmlTtag *xmlFtag_init(void) +{ + xmlTtag *tag = (xmlTtag *) malloc(sizeof(xmlTtag)); + assert(tag != NULL); + memFclear(tag, sizeof(xmlTtag)); + return tag; +} + +static void xmlFtag_free(xmlTtag * tag) +{ + assert(tag != NULL); + if (tag->name != NULL) + free(tag->name); + if (tag->value != NULL) + free(tag->value); + free(tag); +} + +static void xmlFtag_addchild(xmlTtag * parent, xmlTtag * child) +{ + xmlTtag *p; + + assert(parent != NULL); + assert(child != NULL); + + if (parent->linear_child == NULL) { + parent->linear_child = child; + } else { + for (p = parent->linear_child; p->linear_next != NULL; + p = p->linear_next) { + /* Do Nothing */ + } + assert(p != NULL); + p->linear_next = child; + } +} + +/* I really hope to whatever god is convinient that we do not have to change + * anything in this function ever again -aleigh + */ +#define P_SEARCH 1 /* Searching for 1 */ +#define P_TAG 2 /* In <> tag, break > */ +#define P_NAME 3 /* submode: copying tag name */ +#define P_ARG 4 /* submode: copying tag attributes */ + +static const char *xmlF_parse(const char *str, const char *level, + xmlTtag * parent, lstTset * my_arglist) +{ + const char *p; + int mode = P_SEARCH; + int submode = P_NAME; + char buf[128]; + int buf_p = 0; + char arglist[128]; + int arglist_p = 0; + lstTset *argset = NULL; + xmlTtag *my_tag = xmlFtag_init(); + + assert(str != NULL); + assert(level != NULL); + assert(parent != NULL); + + /* make sure that at least we have an empty arglist */ + arglist[0] = 0; + + my_tag->name = strFcopy_size(level, &my_tag->name_len); + my_tag->attrib_list = my_arglist; + + xmlFtag_addchild(parent, my_tag); + + /* + * When P_SEARCH is high the parser is searching for a tag, while copying + * the value into buf. When P_TAG comes high, the parser is inside a tag + * and is copying the tag name into buf. + */ + + for (p = str; *p != 0; p++) { + switch (mode) { + case P_SEARCH: + if (*p == '<') { + if (buf_p > 0) { + buf[buf_p] = 0; + + if (strFis_blank(buf) == 0) { + my_tag->value = strFcopy(buf); + my_tag->value_len = strlen(buf); + } + buf_p = 0; + } + if (*(p + 1) == '!' && *(p + 2) == '-' && *(p + 3) == '-') { + /* It's */ + for (; *p != 0; p++) { + if (*p == '>' && *(p - 1) == '-' + && *(p - 2) == '-') { + break; + } + } + continue; + } else { + mode = P_TAG; + break; + } + } + /* Copy in value */ + buf[buf_p] = *p; + buf_p++; + break; + case P_TAG: + if (*p == ' ' && submode == P_NAME) { + /* We were doign the name, now we have an arglist */ + /* Finish buf */ + buf[buf_p] = 0; + buf_p = 0; + submode = P_ARG; + break; + } + if (*p == '>') { + + if (submode == P_NAME) { + /* we were copying the tags; so finish that */ + buf[buf_p] = 0; + buf_p = 0; + } else { + /* We were copying attributes; so finish that */ + arglist[arglist_p] = 0; + arglist_p = 0; + } + + if (buf[0] == '/') { + + for (; *p != 0; p++) + if (*p == '>') + return p; + return NULL; + } + argset = strFattrib_parser(arglist); + + /* let's see if this tag closes itself */ + if (buf[0] != '/' && *(p - 1) == '/') { + xmlTtag *child = xmlFtag_init(); + + child->name = strFcopy_size(buf, &child->name_len); + child->attrib_list = argset; + + /* + * add this new child to my_tag (which would be the + * parent + */ + xmlFtag_addchild(my_tag, child); + } else { + p = xmlF_parse(p + 1, (char *) &buf, my_tag, argset); + argset = NULL; + /* Short input stream - collapse */ + if (p == NULL) + return NULL; + } + + mode = P_SEARCH; + submode = P_NAME; + break; + } + if (submode == P_NAME) { + /* We are copying the tag name */ + buf[buf_p] = *p; + buf_p++; + } else { + /* We are copying the tag arglist */ + arglist[arglist_p] = *p; + arglist_p++; + } + break; + } + } + + return NULL; +} + +xmlTconfig *xmlFparse(const char *str) +{ + xmlTtag *tag = xmlFtag_init(); + xmlTconfig *config = xmlFconfig_init(); + + assert(str != NULL); + + tag->name = strFcopy("__base"); + tag->name_len = strlen("__base"); + + xmlF_parse(str, "__base_config", tag, NULL); + + config->tags = tag->linear_child->linear_child; + + xmlFtag_free(tag->linear_child); + xmlFtag_free(tag); + + return config; +} + +xmlTconfig *xmlFload_file(const char *filename) +{ + char *config; + size_t config_len; + xmlTconfig *c; + dynTstring *clean; + + assert(filename != NULL); + + config = fleFload_file(filename, &config_len); + + if (config == NULL) { + return NULL; + } + clean = strFcollapse_whitespace(config); + assert(clean != NULL); + + c = xmlFparse(dynFgetstr(clean)); + + dynFfree(clean); + free(config); + + return c; +} + +xmlTtag *xmlFbase_tag(const xmlTconfig * config) +{ + assert(config != NULL); + + return config->tags; +} + +const char *xmlFtag_get_attrib_value(const xmlTtag * tag, const char *name) +{ + const lstTset *set; + + assert(tag != NULL); + assert(name != NULL); + + set = xmlFtag_get_attribs(tag); + + if (set != NULL) + return lstFset_get(set, name); + else + return NULL; +} + + +lstTset *xmlFcreate_list(const xmlTtag * tag, const char *tagname, + const char *attribname) +{ + lstTset *list; + xmlTiterator *tags; + const xmlTtag *t; + const char *key, *val; + + assert(tag != NULL); + assert(tagname != NULL); + assert(attribname != NULL); + + tags = xmlFiterator_init(tag); + + assert(tags != NULL); + + list = lstFset_init(); + + while ((t = xmlFiterator_next_name(tags, tagname)) != NULL) { + key = xmlFtag_get_attrib_value(t, attribname); + if (key == NULL) + continue; + val = xmlFtag_get_value_str(t); + if (val == NULL) + continue; + lstFset_add(list, key, val); + } + + return list; +} + +const char *xmlFfirst_child_value_str (const xmlTtag *tag, const char *name) { + size_t unused; + + assert(tag!=NULL); + assert(name!=NULL); + + return (xmlFfirst_child_value (tag, name, &unused)); +} + +const char *xmlFfirst_child_value(const xmlTtag *tag, const char *name, size_t *value_len) { + const xmlTtag *child; + + assert(tag!=NULL); + assert(name!=NULL); + + child=xmlFfind_first_child(tag,name); + + if(child==NULL) { + return NULL; + } + + return xmlFtag_get_value(child,value_len); +} diff --git a/lc-continuity/mk4/continuity/pcre/.cvsignore b/lc-continuity/mk4/continuity/pcre/.cvsignore new file mode 100644 index 0000000000000000000000000000000000000000..5cb998dbfa2c44fcb73d30d30483777b65a60d4d --- /dev/null +++ b/lc-continuity/mk4/continuity/pcre/.cvsignore @@ -0,0 +1,15 @@ +*.lo +*.la +config.log +.libs +config.status +Makefile +libtool +pcre.h +pcre-config +RunTest +config.h +chartables.c +pcretest +pcregrep +dftables diff --git a/lc-continuity/mk4/continuity/pcre/AUTHORS b/lc-continuity/mk4/continuity/pcre/AUTHORS new file mode 100644 index 0000000000000000000000000000000000000000..832dddca453191e815c7dc8d636ac3850cd2d3f0 --- /dev/null +++ b/lc-continuity/mk4/continuity/pcre/AUTHORS @@ -0,0 +1,6 @@ +Written by: Philip Hazel + +University of Cambridge Computing Service, +Cambridge, England. Phone: +44 1223 334714. + +Copyright (c) 1997-2001 University of Cambridge diff --git a/lc-continuity/mk4/continuity/pcre/COPYING b/lc-continuity/mk4/continuity/pcre/COPYING new file mode 100644 index 0000000000000000000000000000000000000000..8d680612c434c7410a369053d6d47ac121f7b314 --- /dev/null +++ b/lc-continuity/mk4/continuity/pcre/COPYING @@ -0,0 +1,54 @@ +PCRE LICENCE +------------ + +PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + +Written by: Philip Hazel + +University of Cambridge Computing Service, +Cambridge, England. Phone: +44 1223 334714. + +Copyright (c) 1997-2001 University of Cambridge + +Permission is granted to anyone to use this software for any purpose on any +computer system, and to redistribute it freely, subject to the following +restrictions: + +1. This software 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. + +2. The origin of this software must not be misrepresented, either by + explicit claim or by omission. In practice, this means that if you use + PCRE in software that you distribute to others, commercially or + otherwise, you must put a sentence like this + + Regular expression support is provided by the PCRE library package, + which is open source software, written by Philip Hazel, and copyright + by the University of Cambridge, England. + + somewhere reasonably visible in your documentation and in any relevant + files or online help data or similar. A reference to the ftp site for + the source, that is, to + + ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/ + + should also be given in the documentation. However, this condition is not + intended to apply to whole chains of software. If package A includes PCRE, + it must acknowledge it, but if package B is software that includes package + A, the condition is not imposed on package B (unless it uses PCRE + independently). + +3. Altered versions must be plainly marked as such, and must not be + misrepresented as being the original software. + +4. If PCRE is embedded in any software that is released under the GNU + General Purpose Licence (GPL), or Lesser General Purpose Licence (LGPL), + then the terms of that licence shall supersede any condition above with + which it is incompatible. + +The documentation for PCRE, supplied in the "doc" directory, is distributed +under the same terms as the software itself. + +End diff --git a/lc-continuity/mk4/continuity/pcre/CVS/Entries b/lc-continuity/mk4/continuity/pcre/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..cf2708951aac6f1681d4b00887cb4568881d6dc1 --- /dev/null +++ b/lc-continuity/mk4/continuity/pcre/CVS/Entries @@ -0,0 +1,37 @@ +/.cvsignore/1.1/Thu Mar 11 01:11:48 2004//Tmk4_mod6_rc2 +/AUTHORS/1.1/Fri Nov 7 14:48:15 2003//Tmk4_mod6_rc2 +/COPYING/1.1/Fri Nov 7 14:48:15 2003//Tmk4_mod6_rc2 +/ChangeLog/1.1/Fri Nov 7 14:48:15 2003//Tmk4_mod6_rc2 +/INSTALL/1.1/Fri Nov 7 14:48:15 2003//Tmk4_mod6_rc2 +/LICENCE/1.1/Fri Nov 7 14:48:15 2003//Tmk4_mod6_rc2 +/Makefile.in/1.1/Fri Nov 7 14:48:15 2003//Tmk4_mod6_rc2 +/NEWS/1.1/Fri Nov 7 14:48:15 2003//Tmk4_mod6_rc2 +/NON-UNIX-USE/1.1/Fri Nov 7 14:48:15 2003//Tmk4_mod6_rc2 +/README/1.1/Fri Nov 7 14:48:15 2003//Tmk4_mod6_rc2 +/RunTest.in/1.1/Fri Nov 7 14:48:15 2003//Tmk4_mod6_rc2 +/config.guess/1.1/Fri Nov 7 14:48:15 2003//Tmk4_mod6_rc2 +/config.in/1.1/Fri Nov 7 14:48:15 2003//Tmk4_mod6_rc2 +/config.sub/1.1/Fri Nov 7 14:48:15 2003//Tmk4_mod6_rc2 +/configure/1.1/Fri Nov 7 14:48:15 2003//Tmk4_mod6_rc2 +/configure.in/1.1/Fri Nov 7 14:48:15 2003//Tmk4_mod6_rc2 +/dftables.c/1.1/Fri Nov 7 14:48:15 2003//Tmk4_mod6_rc2 +/get.c/1.1/Fri Nov 7 14:48:15 2003//Tmk4_mod6_rc2 +/install-sh/1.1/Fri Nov 7 14:48:15 2003//Tmk4_mod6_rc2 +/internal.h/1.1/Fri Nov 7 14:48:15 2003//Tmk4_mod6_rc2 +/ltmain.sh/1.1/Fri Nov 7 14:48:15 2003//Tmk4_mod6_rc2 +/maketables.c/1.1/Fri Nov 7 14:48:15 2003//Tmk4_mod6_rc2 +/makevp.bat/1.1/Fri Nov 7 14:48:15 2003//Tmk4_mod6_rc2 +/mkinstalldirs/1.1/Fri Nov 7 14:48:15 2003//Tmk4_mod6_rc2 +/pcre-config.in/1.1/Fri Nov 7 14:48:15 2003//Tmk4_mod6_rc2 +/pcre.c/1.1/Fri Nov 7 14:48:15 2003//Tmk4_mod6_rc2 +/pcre.def/1.1/Fri Nov 7 14:48:15 2003//Tmk4_mod6_rc2 +/pcre.in/1.1/Fri Nov 7 14:48:15 2003//Tmk4_mod6_rc2 +/pcredemo.c/1.2/Tue Feb 24 19:22:06 2004//Tmk4_mod6_rc2 +/pcregrep.c/1.1/Fri Nov 7 14:48:15 2003//Tmk4_mod6_rc2 +/pcreposix.c/1.1/Fri Nov 7 14:48:15 2003//Tmk4_mod6_rc2 +/pcreposix.h/1.1/Fri Nov 7 14:48:15 2003//Tmk4_mod6_rc2 +/pcretest.c/1.1/Fri Nov 7 14:48:15 2003//Tmk4_mod6_rc2 +/perltest/1.1/Fri Nov 7 14:48:15 2003//Tmk4_mod6_rc2 +/printint.c/1.1/Fri Nov 7 14:48:15 2003//Tmk4_mod6_rc2 +/study.c/1.1/Fri Nov 7 14:48:15 2003//Tmk4_mod6_rc2 +D diff --git a/lc-continuity/mk4/continuity/pcre/CVS/Repository b/lc-continuity/mk4/continuity/pcre/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..e8d1b61c9838895034ba61b44ef779896a450b3d --- /dev/null +++ b/lc-continuity/mk4/continuity/pcre/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/continuity/pcre diff --git a/lc-continuity/mk4/continuity/pcre/CVS/Root b/lc-continuity/mk4/continuity/pcre/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/continuity/pcre/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/continuity/pcre/CVS/Tag b/lc-continuity/mk4/continuity/pcre/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/continuity/pcre/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/continuity/pcre/ChangeLog b/lc-continuity/mk4/continuity/pcre/ChangeLog new file mode 100644 index 0000000000000000000000000000000000000000..b9123144bacfd23a9ed2ae739140ed84c1e8ed94 --- /dev/null +++ b/lc-continuity/mk4/continuity/pcre/ChangeLog @@ -0,0 +1,1320 @@ +ChangeLog for PCRE +------------------ + +Version 4.3 21-May-03 +--------------------- + +1. Two instances of @WIN_PREFIX@ omitted from the Windows targets in the + Makefile. + +2. Some refactoring to improve the quality of the code: + + (i) The utf8_table... variables are now declared "const". + + (ii) The code for \cx, which used the "case flipping" table to upper case + lower case letters, now just substracts 32. This is ASCII-specific, + but the whole concept of \cx is ASCII-specific, so it seems + reasonable. + + (iii) PCRE was using its character types table to recognize decimal and + hexadecimal digits in the pattern. This is silly, because it handles + only 0-9, a-f, and A-F, but the character types table is locale- + specific, which means strange things might happen. A private + table is now used for this - though it costs 256 bytes, a table is + much faster than multiple explicit tests. Of course, the standard + character types table is still used for matching digits in subject + strings against \d. + + (iv) Strictly, the identifier ESC_t is reserved by POSIX (all identifiers + ending in _t are). So I've renamed it as ESC_tee. + +3. The first argument for regexec() in the POSIX wrapper should have been + defined as "const". + +4. Changed pcretest to use malloc() for its buffers so that they can be + Electric Fenced for debugging. + +5. There were several places in the code where, in UTF-8 mode, PCRE would try + to read one or more bytes before the start of the subject string. Often this + had no effect on PCRE's behaviour, but in some circumstances it could + provoke a segmentation fault. + +6. A lookbehind at the start of a pattern in UTF-8 mode could also cause PCRE + to try to read one or more bytes before the start of the subject string. + +7. A lookbehind in a pattern matched in non-UTF-8 mode on a PCRE compiled with + UTF-8 support could misbehave in various ways if the subject string + contained bytes with the 0x80 bit set and the 0x40 bit unset in a lookbehind + area. (PCRE was not checking for the UTF-8 mode flag, and trying to move + back over UTF-8 characters.) + + +Version 4.2 14-Apr-03 +--------------------- + +1. Typo "#if SUPPORT_UTF8" instead of "#ifdef SUPPORT_UTF8" fixed. + +2. Changes to the building process, supplied by Ronald Landheer-Cieslak + [ON_WINDOWS]: new variable, "#" on non-Windows platforms + [NOT_ON_WINDOWS]: new variable, "#" on Windows platforms + [WIN_PREFIX]: new variable, "cyg" for Cygwin + * Makefile.in: use autoconf substitution for OBJEXT, EXEEXT, BUILD_OBJEXT + and BUILD_EXEEXT + Note: automatic setting of the BUILD variables is not yet working + set CPPFLAGS and BUILD_CPPFLAGS (but don't use yet) - should be used at + compile-time but not at link-time + [LINK]: use for linking executables only + make different versions for Windows and non-Windows + [LINKLIB]: new variable, copy of UNIX-style LINK, used for linking + libraries + [LINK_FOR_BUILD]: new variable + [OBJEXT]: use throughout + [EXEEXT]: use throughout + : new target + : new target + : use native compiler + : use native linker + : handle Windows platform correctly + : ditto + : ditto + copy DLL to top builddir before testing + + As part of these changes, -no-undefined was removed again. This was reported + to give trouble on HP-UX 11.0, so getting rid of it seems like a good idea + in any case. + +3. Some tidies to get rid of compiler warnings: + + . In the match_data structure, match_limit was an unsigned long int, whereas + match_call_count was an int. I've made them both unsigned long ints. + + . In pcretest the fact that a const uschar * doesn't automatically cast to + a void * provoked a warning. + + . Turning on some more compiler warnings threw up some "shadow" variables + and a few more missing casts. + +4. If PCRE was complied with UTF-8 support, but called without the PCRE_UTF8 + option, a class that contained a single character with a value between 128 + and 255 (e.g. /[\xFF]/) caused PCRE to crash. + +5. If PCRE was compiled with UTF-8 support, but called without the PCRE_UTF8 + option, a class that contained several characters, but with at least one + whose value was between 128 and 255 caused PCRE to crash. + + +Version 4.1 12-Mar-03 +--------------------- + +1. Compiling with gcc -pedantic found a couple of places where casts were +needed, and a string in dftables.c that was longer than standard compilers are +required to support. + +2. Compiling with Sun's compiler found a few more places where the code could +be tidied up in order to avoid warnings. + +3. The variables for cross-compiling were called HOST_CC and HOST_CFLAGS; the +first of these names is deprecated in the latest Autoconf in favour of the name +CC_FOR_BUILD, because "host" is typically used to mean the system on which the +compiled code will be run. I can't find a reference for HOST_CFLAGS, but by +analogy I have changed it to CFLAGS_FOR_BUILD. + +4. Added -no-undefined to the linking command in the Makefile, because this is +apparently helpful for Windows. To make it work, also added "-L. -lpcre" to the +linking step for the pcreposix library. + +5. PCRE was failing to diagnose the case of two named groups with the same +name. + +6. A problem with one of PCRE's optimizations was discovered. PCRE remembers a +literal character that is needed in the subject for a match, and scans along to +ensure that it is present before embarking on the full matching process. This +saves time in cases of nested unlimited repeats that are never going to match. +Problem: the scan can take a lot of time if the subject is very long (e.g. +megabytes), thus penalizing straightforward matches. It is now done only if the +amount of subject to be scanned is less than 1000 bytes. + +7. A lesser problem with the same optimization is that it was recording the +first character of an anchored pattern as "needed", thus provoking a search +right along the subject, even when the first match of the pattern was going to +fail. The "needed" character is now not set for anchored patterns, unless it +follows something in the pattern that is of non-fixed length. Thus, it still +fulfils its original purpose of finding quick non-matches in cases of nested +unlimited repeats, but isn't used for simple anchored patterns such as /^abc/. + + +Version 4.0 17-Feb-03 +--------------------- + +1. If a comment in an extended regex that started immediately after a meta-item +extended to the end of string, PCRE compiled incorrect data. This could lead to +all kinds of weird effects. Example: /#/ was bad; /()#/ was bad; /a#/ was not. + +2. Moved to autoconf 2.53 and libtool 1.4.2. + +3. Perl 5.8 no longer needs "use utf8" for doing UTF-8 things. Consequently, +the special perltest8 script is no longer needed - all the tests can be run +from a single perltest script. + +4. From 5.004, Perl has not included the VT character (0x0b) in the set defined +by \s. It has now been removed in PCRE. This means it isn't recognized as +whitespace in /x regexes too, which is the same as Perl. Note that the POSIX +class [:space:] *does* include VT, thereby creating a mess. + +5. Added the class [:blank:] (a GNU extension from Perl 5.8) to match only +space and tab. + +6. Perl 5.005 was a long time ago. It's time to amalgamate the tests that use +its new features into the main test script, reducing the number of scripts. + +7. Perl 5.8 has changed the meaning of patterns like /a(?i)b/. Earlier versions +were backward compatible, and made the (?i) apply to the whole pattern, as if +/i were given. Now it behaves more logically, and applies the option setting +only to what follows. PCRE has been changed to follow suit. However, if it +finds options settings right at the start of the pattern, it extracts them into +the global options, as before. Thus, they show up in the info data. + +8. Added support for the \Q...\E escape sequence. Characters in between are +treated as literals. This is slightly different from Perl in that $ and @ are +also handled as literals inside the quotes. In Perl, they will cause variable +interpolation. Note the following examples: + + Pattern PCRE matches Perl matches + + \Qabc$xyz\E abc$xyz abc followed by the contents of $xyz + \Qabc\$xyz\E abc\$xyz abc\$xyz + \Qabc\E\$\Qxyz\E abc$xyz abc$xyz + +For compatibility with Perl, \Q...\E sequences are recognized inside character +classes as well as outside them. + +9. Re-organized 3 code statements in pcretest to avoid "overflow in +floating-point constant arithmetic" warnings from a Microsoft compiler. Added a +(size_t) cast to one statement in pcretest and one in pcreposix to avoid +signed/unsigned warnings. + +10. SunOS4 doesn't have strtoul(). This was used only for unpicking the -o +option for pcretest, so I've replaced it by a simple function that does just +that job. + +11. pcregrep was ending with code 0 instead of 2 for the commands "pcregrep" or +"pcregrep -". + +12. Added "possessive quantifiers" ?+, *+, ++, and {,}+ which come from Sun's +Java package. This provides some syntactic sugar for simple cases of what my +documentation calls "once-only subpatterns". A pattern such as x*+ is the same +as (?>x*). In other words, if what is inside (?>...) is just a single repeated +item, you can use this simplified notation. Note that only makes sense with +greedy quantifiers. Consequently, the use of the possessive quantifier forces +greediness, whatever the setting of the PCRE_UNGREEDY option. + +13. A change of greediness default within a pattern was not taking effect at +the current level for patterns like /(b+(?U)a+)/. It did apply to parenthesized +subpatterns that followed. Patterns like /b+(?U)a+/ worked because the option +was abstracted outside. + +14. PCRE now supports the \G assertion. It is true when the current matching +position is at the start point of the match. This differs from \A when the +starting offset is non-zero. Used with the /g option of pcretest (or similar +code), it works in the same way as it does for Perl's /g option. If all +alternatives of a regex begin with \G, the expression is anchored to the start +match position, and the "anchored" flag is set in the compiled expression. + +15. Some bugs concerning the handling of certain option changes within patterns +have been fixed. These applied to options other than (?ims). For example, +"a(?x: b c )d" did not match "XabcdY" but did match "Xa b c dY". It should have +been the other way round. Some of this was related to change 7 above. + +16. PCRE now gives errors for /[.x.]/ and /[=x=]/ as unsupported POSIX +features, as Perl does. Previously, PCRE gave the warnings only for /[[.x.]]/ +and /[[=x=]]/. PCRE now also gives an error for /[:name:]/ because it supports +POSIX classes only within a class (e.g. /[[:alpha:]]/). + +17. Added support for Perl's \C escape. This matches one byte, even in UTF8 +mode. Unlike ".", it always matches newline, whatever the setting of +PCRE_DOTALL. However, PCRE does not permit \C to appear in lookbehind +assertions. Perl allows it, but it doesn't (in general) work because it can't +calculate the length of the lookbehind. At least, that's the case for Perl +5.8.0 - I've been told they are going to document that it doesn't work in +future. + +18. Added an error diagnosis for escapes that PCRE does not support: these are +\L, \l, \N, \P, \p, \U, \u, and \X. + +19. Although correctly diagnosing a missing ']' in a character class, PCRE was +reading past the end of the pattern in cases such as /[abcd/. + +20. PCRE was getting more memory than necessary for patterns with classes that +contained both POSIX named classes and other characters, e.g. /[[:space:]abc/. + +21. Added some code, conditional on #ifdef VPCOMPAT, to make life easier for +compiling PCRE for use with Virtual Pascal. + +22. Small fix to the Makefile to make it work properly if the build is done +outside the source tree. + +23. Added a new extension: a condition to go with recursion. If a conditional +subpattern starts with (?(R) the "true" branch is used if recursion has +happened, whereas the "false" branch is used only at the top level. + +24. When there was a very long string of literal characters (over 255 bytes +without UTF support, over 250 bytes with UTF support), the computation of how +much memory was required could be incorrect, leading to segfaults or other +strange effects. + +25. PCRE was incorrectly assuming anchoring (either to start of subject or to +start of line for a non-DOTALL pattern) when a pattern started with (.*) and +there was a subsequent back reference to those brackets. This meant that, for +example, /(.*)\d+\1/ failed to match "abc123bc". Unfortunately, it isn't +possible to check for precisely this case. All we can do is abandon the +optimization if .* occurs inside capturing brackets when there are any back +references whatsoever. (See below for a better fix that came later.) + +26. The handling of the optimization for finding the first character of a +non-anchored pattern, and for finding a character that is required later in the +match were failing in some cases. This didn't break the matching; it just +failed to optimize when it could. The way this is done has been re-implemented. + +27. Fixed typo in error message for invalid (?R item (it said "(?p"). + +28. Added a new feature that provides some of the functionality that Perl +provides with (?{...}). The facility is termed a "callout". The way it is done +in PCRE is for the caller to provide an optional function, by setting +pcre_callout to its entry point. Like pcre_malloc and pcre_free, this is a +global variable. By default it is unset, which disables all calling out. To get +the function called, the regex must include (?C) at appropriate points. This +is, in fact, equivalent to (?C0), and any number <= 255 may be given with (?C). +This provides a means of identifying different callout points. When PCRE +reaches such a point in the regex, if pcre_callout has been set, the external +function is called. It is provided with data in a structure called +pcre_callout_block, which is defined in pcre.h. If the function returns 0, +matching continues; if it returns a non-zero value, the match at the current +point fails. However, backtracking will occur if possible. [This was changed +later and other features added - see item 49 below.] + +29. pcretest is upgraded to test the callout functionality. It provides a +callout function that displays information. By default, it shows the start of +the match and the current position in the text. There are some new data escapes +to vary what happens: + + \C+ in addition, show current contents of captured substrings + \C- do not supply a callout function + \C!n return 1 when callout number n is reached + \C!n!m return 1 when callout number n is reached for the mth time + +30. If pcregrep was called with the -l option and just a single file name, it +output "" if a match was found, instead of the file name. + +31. Improve the efficiency of the POSIX API to PCRE. If the number of capturing +slots is less than POSIX_MALLOC_THRESHOLD, use a block on the stack to pass to +pcre_exec(). This saves a malloc/free per call. The default value of +POSIX_MALLOC_THRESHOLD is 10; it can be changed by --with-posix-malloc-threshold +when configuring. + +32. The default maximum size of a compiled pattern is 64K. There have been a +few cases of people hitting this limit. The code now uses macros to handle the +storing of links as offsets within the compiled pattern. It defaults to 2-byte +links, but this can be changed to 3 or 4 bytes by --with-link-size when +configuring. Tests 2 and 5 work only with 2-byte links because they output +debugging information about compiled patterns. + +33. Internal code re-arrangements: + +(a) Moved the debugging function for printing out a compiled regex into + its own source file (printint.c) and used #include to pull it into + pcretest.c and, when DEBUG is defined, into pcre.c, instead of having two + separate copies. + +(b) Defined the list of op-code names for debugging as a macro in + internal.h so that it is next to the definition of the opcodes. + +(c) Defined a table of op-code lengths for simpler skipping along compiled + code. This is again a macro in internal.h so that it is next to the + definition of the opcodes. + +34. Added support for recursive calls to individual subpatterns, along the +lines of Robin Houston's patch (but implemented somewhat differently). + +35. Further mods to the Makefile to help Win32. Also, added code to pcregrep to +allow it to read and process whole directories in Win32. This code was +contributed by Lionel Fourquaux; it has not been tested by me. + +36. Added support for named subpatterns. The Python syntax (?P...) is +used to name a group. Names consist of alphanumerics and underscores, and must +be unique. Back references use the syntax (?P=name) and recursive calls use +(?P>name) which is a PCRE extension to the Python extension. Groups still have +numbers. The function pcre_fullinfo() can be used after compilation to extract +a name/number map. There are three relevant calls: + + PCRE_INFO_NAMEENTRYSIZE yields the size of each entry in the map + PCRE_INFO_NAMECOUNT yields the number of entries + PCRE_INFO_NAMETABLE yields a pointer to the map. + +The map is a vector of fixed-size entries. The size of each entry depends on +the length of the longest name used. The first two bytes of each entry are the +group number, most significant byte first. There follows the corresponding +name, zero terminated. The names are in alphabetical order. + +37. Make the maximum literal string in the compiled code 250 for the non-UTF-8 +case instead of 255. Making it the same both with and without UTF-8 support +means that the same test output works with both. + +38. There was a case of malloc(0) in the POSIX testing code in pcretest. Avoid +calling malloc() with a zero argument. + +39. Change 25 above had to resort to a heavy-handed test for the .* anchoring +optimization. I've improved things by keeping a bitmap of backreferences with +numbers 1-31 so that if .* occurs inside capturing brackets that are not in +fact referenced, the optimization can be applied. It is unlikely that a +relevant occurrence of .* (i.e. one which might indicate anchoring or forcing +the match to follow \n) will appear inside brackets with a number greater than +31, but if it does, any back reference > 31 suppresses the optimization. + +40. Added a new compile-time option PCRE_NO_AUTO_CAPTURE. This has the effect +of disabling numbered capturing parentheses. Any opening parenthesis that is +not followed by ? behaves as if it were followed by ?: but named parentheses +can still be used for capturing (and they will acquire numbers in the usual +way). + +41. Redesigned the return codes from the match() function into yes/no/error so +that errors can be passed back from deep inside the nested calls. A malloc +failure while inside a recursive subpattern call now causes the +PCRE_ERROR_NOMEMORY return instead of quietly going wrong. + +42. It is now possible to set a limit on the number of times the match() +function is called in a call to pcre_exec(). This facility makes it possible to +limit the amount of recursion and backtracking, though not in a directly +obvious way, because the match() function is used in a number of different +circumstances. The count starts from zero for each position in the subject +string (for non-anchored patterns). The default limit is, for compatibility, a +large number, namely 10 000 000. You can change this in two ways: + +(a) When configuring PCRE before making, you can use --with-match-limit=n + to set a default value for the compiled library. + +(b) For each call to pcre_exec(), you can pass a pcre_extra block in which + a different value is set. See 45 below. + +If the limit is exceeded, pcre_exec() returns PCRE_ERROR_MATCHLIMIT. + +43. Added a new function pcre_config(int, void *) to enable run-time extraction +of things that can be changed at compile time. The first argument specifies +what is wanted and the second points to where the information is to be placed. +The current list of available information is: + + PCRE_CONFIG_UTF8 + +The output is an integer that is set to one if UTF-8 support is available; +otherwise it is set to zero. + + PCRE_CONFIG_NEWLINE + +The output is an integer that it set to the value of the code that is used for +newline. It is either LF (10) or CR (13). + + PCRE_CONFIG_LINK_SIZE + +The output is an integer that contains the number of bytes used for internal +linkage in compiled expressions. The value is 2, 3, or 4. See item 32 above. + + PCRE_CONFIG_POSIX_MALLOC_THRESHOLD + +The output is an integer that contains the threshold above which the POSIX +interface uses malloc() for output vectors. See item 31 above. + + PCRE_CONFIG_MATCH_LIMIT + +The output is an unsigned integer that contains the default limit of the number +of match() calls in a pcre_exec() execution. See 42 above. + +44. pcretest has been upgraded by the addition of the -C option. This causes it +to extract all the available output from the new pcre_config() function, and to +output it. The program then exits immediately. + +45. A need has arisen to pass over additional data with calls to pcre_exec() in +order to support additional features. One way would have been to define +pcre_exec2() (for example) with extra arguments, but this would not have been +extensible, and would also have required all calls to the original function to +be mapped to the new one. Instead, I have chosen to extend the mechanism that +is used for passing in "extra" data from pcre_study(). + +The pcre_extra structure is now exposed and defined in pcre.h. It currently +contains the following fields: + + flags a bitmap indicating which of the following fields are set + study_data opaque data from pcre_study() + match_limit a way of specifying a limit on match() calls for a specific + call to pcre_exec() + callout_data data for callouts (see 49 below) + +The flag bits are also defined in pcre.h, and are + + PCRE_EXTRA_STUDY_DATA + PCRE_EXTRA_MATCH_LIMIT + PCRE_EXTRA_CALLOUT_DATA + +The pcre_study() function now returns one of these new pcre_extra blocks, with +the actual study data pointed to by the study_data field, and the +PCRE_EXTRA_STUDY_DATA flag set. This can be passed directly to pcre_exec() as +before. That is, this change is entirely upwards-compatible and requires no +change to existing code. + +If you want to pass in additional data to pcre_exec(), you can either place it +in a pcre_extra block provided by pcre_study(), or create your own pcre_extra +block. + +46. pcretest has been extended to test the PCRE_EXTRA_MATCH_LIMIT feature. If a +data string contains the escape sequence \M, pcretest calls pcre_exec() several +times with different match limits, until it finds the minimum value needed for +pcre_exec() to complete. The value is then output. This can be instructive; for +most simple matches the number is quite small, but for pathological cases it +gets very large very quickly. + +47. There's a new option for pcre_fullinfo() called PCRE_INFO_STUDYSIZE. It +returns the size of the data block pointed to by the study_data field in a +pcre_extra block, that is, the value that was passed as the argument to +pcre_malloc() when PCRE was getting memory in which to place the information +created by pcre_study(). The fourth argument should point to a size_t variable. +pcretest has been extended so that this information is shown after a successful +pcre_study() call when information about the compiled regex is being displayed. + +48. Cosmetic change to Makefile: there's no need to have / after $(DESTDIR) +because what follows is always an absolute path. (Later: it turns out that this +is more than cosmetic for MinGW, because it doesn't like empty path +components.) + +49. Some changes have been made to the callout feature (see 28 above): + +(i) A callout function now has three choices for what it returns: + + 0 => success, carry on matching + > 0 => failure at this point, but backtrack if possible + < 0 => serious error, return this value from pcre_exec() + + Negative values should normally be chosen from the set of PCRE_ERROR_xxx + values. In particular, returning PCRE_ERROR_NOMATCH forces a standard + "match failed" error. The error number PCRE_ERROR_CALLOUT is reserved for + use by callout functions. It will never be used by PCRE itself. + +(ii) The pcre_extra structure (see 45 above) has a void * field called + callout_data, with corresponding flag bit PCRE_EXTRA_CALLOUT_DATA. The + pcre_callout_block structure has a field of the same name. The contents of + the field passed in the pcre_extra structure are passed to the callout + function in the corresponding field in the callout block. This makes it + easier to use the same callout-containing regex from multiple threads. For + testing, the pcretest program has a new data escape + + \C*n pass the number n (may be negative) as callout_data + + If the callout function in pcretest receives a non-zero value as + callout_data, it returns that value. + +50. Makefile wasn't handling CFLAGS properly when compiling dftables. Also, +there were some redundant $(CFLAGS) in commands that are now specified as +$(LINK), which already includes $(CFLAGS). + +51. Extensions to UTF-8 support are listed below. These all apply when (a) PCRE +has been compiled with UTF-8 support *and* pcre_compile() has been compiled +with the PCRE_UTF8 flag. Patterns that are compiled without that flag assume +one-byte characters throughout. Note that case-insensitive matching applies +only to characters whose values are less than 256. PCRE doesn't support the +notion of cases for higher-valued characters. + +(i) A character class whose characters are all within 0-255 is handled as + a bit map, and the map is inverted for negative classes. Previously, a + character > 255 always failed to match such a class; however it should + match if the class was a negative one (e.g. [^ab]). This has been fixed. + +(ii) A negated character class with a single character < 255 is coded as + "not this character" (OP_NOT). This wasn't working properly when the test + character was multibyte, either singly or repeated. + +(iii) Repeats of multibyte characters are now handled correctly in UTF-8 + mode, for example: \x{100}{2,3}. + +(iv) The character escapes \b, \B, \d, \D, \s, \S, \w, and \W (either + singly or repeated) now correctly test multibyte characters. However, + PCRE doesn't recognize any characters with values greater than 255 as + digits, spaces, or word characters. Such characters always match \D, \S, + and \W, and never match \d, \s, or \w. + +(v) Classes may now contain characters and character ranges with values + greater than 255. For example: [ab\x{100}-\x{400}]. + +(vi) pcregrep now has a --utf-8 option (synonym -u) which makes it call + PCRE in UTF-8 mode. + +52. The info request value PCRE_INFO_FIRSTCHAR has been renamed +PCRE_INFO_FIRSTBYTE because it is a byte value. However, the old name is +retained for backwards compatibility. (Note that LASTLITERAL is also a byte +value.) + +53. The single man page has become too large. I have therefore split it up into +a number of separate man pages. These also give rise to individual HTML pages; +these are now put in a separate directory, and there is an index.html page that +lists them all. Some hyperlinking between the pages has been installed. + +54. Added convenience functions for handling named capturing parentheses. + +55. Unknown escapes inside character classes (e.g. [\M]) and escapes that +aren't interpreted therein (e.g. [\C]) are literals in Perl. This is now also +true in PCRE, except when the PCRE_EXTENDED option is set, in which case they +are faulted. + +56. Introduced HOST_CC and HOST_CFLAGS which can be set in the environment when +calling configure. These values are used when compiling the dftables.c program +which is run to generate the source of the default character tables. They +default to the values of CC and CFLAGS. If you are cross-compiling PCRE, +you will need to set these values. + +57. Updated the building process for Windows DLL, as provided by Fred Cox. + + +Version 3.9 02-Jan-02 +--------------------- + +1. A bit of extraneous text had somehow crept into the pcregrep documentation. + +2. If --disable-static was given, the building process failed when trying to +build pcretest and pcregrep. (For some reason it was using libtool to compile +them, which is not right, as they aren't part of the library.) + + +Version 3.8 18-Dec-01 +--------------------- + +1. The experimental UTF-8 code was completely screwed up. It was packing the +bytes in the wrong order. How dumb can you get? + + +Version 3.7 29-Oct-01 +--------------------- + +1. In updating pcretest to check change 1 of version 3.6, I screwed up. +This caused pcretest, when used on the test data, to segfault. Unfortunately, +this didn't happen under Solaris 8, where I normally test things. + +2. The Makefile had to be changed to make it work on BSD systems, where 'make' +doesn't seem to recognize that ./xxx and xxx are the same file. (This entry +isn't in ChangeLog distributed with 3.7 because I forgot when I hastily made +this fix an hour or so after the initial 3.7 release.) + + +Version 3.6 23-Oct-01 +--------------------- + +1. Crashed with /(sens|respons)e and \1ibility/ and "sense and sensibility" if +offsets passed as NULL with zero offset count. + +2. The config.guess and config.sub files had not been updated when I moved to +the latest autoconf. + + +Version 3.5 15-Aug-01 +--------------------- + +1. Added some missing #if !defined NOPOSIX conditionals in pcretest.c that +had been forgotten. + +2. By using declared but undefined structures, we can avoid using "void" +definitions in pcre.h while keeping the internal definitions of the structures +private. + +3. The distribution is now built using autoconf 2.50 and libtool 1.4. From a +user point of view, this means that both static and shared libraries are built +by default, but this can be individually controlled. More of the work of +handling this static/shared cases is now inside libtool instead of PCRE's make +file. + +4. The pcretest utility is now installed along with pcregrep because it is +useful for users (to test regexs) and by doing this, it automatically gets +relinked by libtool. The documentation has been turned into a man page, so +there are now .1, .txt, and .html versions in /doc. + +5. Upgrades to pcregrep: + (i) Added long-form option names like gnu grep. + (ii) Added --help to list all options with an explanatory phrase. + (iii) Added -r, --recursive to recurse into sub-directories. + (iv) Added -f, --file to read patterns from a file. + +6. pcre_exec() was referring to its "code" argument before testing that +argument for NULL (and giving an error if it was NULL). + +7. Upgraded Makefile.in to allow for compiling in a different directory from +the source directory. + +8. Tiny buglet in pcretest: when pcre_fullinfo() was called to retrieve the +options bits, the pointer it was passed was to an int instead of to an unsigned +long int. This mattered only on 64-bit systems. + +9. Fixed typo (3.4/1) in pcre.h again. Sigh. I had changed pcre.h (which is +generated) instead of pcre.in, which it its source. Also made the same change +in several of the .c files. + +10. A new release of gcc defines printf() as a macro, which broke pcretest +because it had an ifdef in the middle of a string argument for printf(). Fixed +by using separate calls to printf(). + +11. Added --enable-newline-is-cr and --enable-newline-is-lf to the configure +script, to force use of CR or LF instead of \n in the source. On non-Unix +systems, the value can be set in config.h. + +12. The limit of 200 on non-capturing parentheses is a _nesting_ limit, not an +absolute limit. Changed the text of the error message to make this clear, and +likewise updated the man page. + +13. The limit of 99 on the number of capturing subpatterns has been removed. +The new limit is 65535, which I hope will not be a "real" limit. + + +Version 3.4 22-Aug-00 +--------------------- + +1. Fixed typo in pcre.h: unsigned const char * changed to const unsigned char *. + +2. Diagnose condition (?(0) as an error instead of crashing on matching. + + +Version 3.3 01-Aug-00 +--------------------- + +1. If an octal character was given, but the value was greater than \377, it +was not getting masked to the least significant bits, as documented. This could +lead to crashes in some systems. + +2. Perl 5.6 (if not earlier versions) accepts classes like [a-\d] and treats +the hyphen as a literal. PCRE used to give an error; it now behaves like Perl. + +3. Added the functions pcre_free_substring() and pcre_free_substring_list(). +These just pass their arguments on to (pcre_free)(), but they are provided +because some uses of PCRE bind it to non-C systems that can call its functions, +but cannot call free() or pcre_free() directly. + +4. Add "make test" as a synonym for "make check". Corrected some comments in +the Makefile. + +5. Add $(DESTDIR)/ in front of all the paths in the "install" target in the +Makefile. + +6. Changed the name of pgrep to pcregrep, because Solaris has introduced a +command called pgrep for grepping around the active processes. + +7. Added the beginnings of support for UTF-8 character strings. + +8. Arranged for the Makefile to pass over the settings of CC, CFLAGS, and +RANLIB to ./ltconfig so that they are used by libtool. I think these are all +the relevant ones. (AR is not passed because ./ltconfig does its own figuring +out for the ar command.) + + +Version 3.2 12-May-00 +--------------------- + +This is purely a bug fixing release. + +1. If the pattern /((Z)+|A)*/ was matched agained ZABCDEFG it matched Z instead +of ZA. This was just one example of several cases that could provoke this bug, +which was introduced by change 9 of version 2.00. The code for breaking +infinite loops after an iteration that matches an empty string was't working +correctly. + +2. The pcretest program was not imitating Perl correctly for the pattern /a*/g +when matched against abbab (for example). After matching an empty string, it +wasn't forcing anchoring when setting PCRE_NOTEMPTY for the next attempt; this +caused it to match further down the string than it should. + +3. The code contained an inclusion of sys/types.h. It isn't clear why this +was there because it doesn't seem to be needed, and it causes trouble on some +systems, as it is not a Standard C header. It has been removed. + +4. Made 4 silly changes to the source to avoid stupid compiler warnings that +were reported on the Macintosh. The changes were from + + while ((c = *(++ptr)) != 0 && c != '\n'); +to + while ((c = *(++ptr)) != 0 && c != '\n') ; + +Totally extraordinary, but if that's what it takes... + +5. PCRE is being used in one environment where neither memmove() nor bcopy() is +available. Added HAVE_BCOPY and an autoconf test for it; if neither +HAVE_MEMMOVE nor HAVE_BCOPY is set, use a built-in emulation function which +assumes the way PCRE uses memmove() (always moving upwards). + +6. PCRE is being used in one environment where strchr() is not available. There +was only one use in pcre.c, and writing it out to avoid strchr() probably gives +faster code anyway. + + +Version 3.1 09-Feb-00 +--------------------- + +The only change in this release is the fixing of some bugs in Makefile.in for +the "install" target: + +(1) It was failing to install pcreposix.h. + +(2) It was overwriting the pcre.3 man page with the pcreposix.3 man page. + + +Version 3.0 01-Feb-00 +--------------------- + +1. Add support for the /+ modifier to perltest (to output $` like it does in +pcretest). + +2. Add support for the /g modifier to perltest. + +3. Fix pcretest so that it behaves even more like Perl for /g when the pattern +matches null strings. + +4. Fix perltest so that it doesn't do unwanted things when fed an empty +pattern. Perl treats empty patterns specially - it reuses the most recent +pattern, which is not what we want. Replace // by /(?#)/ in order to avoid this +effect. + +5. The POSIX interface was broken in that it was just handing over the POSIX +captured string vector to pcre_exec(), but (since release 2.00) PCRE has +required a bigger vector, with some working space on the end. This means that +the POSIX wrapper now has to get and free some memory, and copy the results. + +6. Added some simple autoconf support, placing the test data and the +documentation in separate directories, re-organizing some of the +information files, and making it build pcre-config (a GNU standard). Also added +libtool support for building PCRE as a shared library, which is now the +default. + +7. Got rid of the leading zero in the definition of PCRE_MINOR because 08 and +09 are not valid octal constants. Single digits will be used for minor values +less than 10. + +8. Defined REG_EXTENDED and REG_NOSUB as zero in the POSIX header, so that +existing programs that set these in the POSIX interface can use PCRE without +modification. + +9. Added a new function, pcre_fullinfo() with an extensible interface. It can +return all that pcre_info() returns, plus additional data. The pcre_info() +function is retained for compatibility, but is considered to be obsolete. + +10. Added experimental recursion feature (?R) to handle one common case that +Perl 5.6 will be able to do with (?p{...}). + +11. Added support for POSIX character classes like [:alpha:], which Perl is +adopting. + + +Version 2.08 31-Aug-99 +---------------------- + +1. When startoffset was not zero and the pattern began with ".*", PCRE was not +trying to match at the startoffset position, but instead was moving forward to +the next newline as if a previous match had failed. + +2. pcretest was not making use of PCRE_NOTEMPTY when repeating for /g and /G, +and could get into a loop if a null string was matched other than at the start +of the subject. + +3. Added definitions of PCRE_MAJOR and PCRE_MINOR to pcre.h so the version can +be distinguished at compile time, and for completeness also added PCRE_DATE. + +5. Added Paul Sokolovsky's minor changes to make it easy to compile a Win32 DLL +in GnuWin32 environments. + + +Version 2.07 29-Jul-99 +---------------------- + +1. The documentation is now supplied in plain text form and HTML as well as in +the form of man page sources. + +2. C++ compilers don't like assigning (void *) values to other pointer types. +In particular this affects malloc(). Although there is no problem in Standard +C, I've put in casts to keep C++ compilers happy. + +3. Typo on pcretest.c; a cast of (unsigned char *) in the POSIX regexec() call +should be (const char *). + +4. If NOPOSIX is defined, pcretest.c compiles without POSIX support. This may +be useful for non-Unix systems who don't want to bother with the POSIX stuff. +However, I haven't made this a standard facility. The documentation doesn't +mention it, and the Makefile doesn't support it. + +5. The Makefile now contains an "install" target, with editable destinations at +the top of the file. The pcretest program is not installed. + +6. pgrep -V now gives the PCRE version number and date. + +7. Fixed bug: a zero repetition after a literal string (e.g. /abcde{0}/) was +causing the entire string to be ignored, instead of just the last character. + +8. If a pattern like /"([^\\"]+|\\.)*"/ is applied in the normal way to a +non-matching string, it can take a very, very long time, even for strings of +quite modest length, because of the nested recursion. PCRE now does better in +some of these cases. It does this by remembering the last required literal +character in the pattern, and pre-searching the subject to ensure it is present +before running the real match. In other words, it applies a heuristic to detect +some types of certain failure quickly, and in the above example, if presented +with a string that has no trailing " it gives "no match" very quickly. + +9. A new runtime option PCRE_NOTEMPTY causes null string matches to be ignored; +other alternatives are tried instead. + + +Version 2.06 09-Jun-99 +---------------------- + +1. Change pcretest's output for amount of store used to show just the code +space, because the remainder (the data block) varies in size between 32-bit and +64-bit systems. + +2. Added an extra argument to pcre_exec() to supply an offset in the subject to +start matching at. This allows lookbehinds to work when searching for multiple +occurrences in a string. + +3. Added additional options to pcretest for testing multiple occurrences: + + /+ outputs the rest of the string that follows a match + /g loops for multiple occurrences, using the new startoffset argument + /G loops for multiple occurrences by passing an incremented pointer + +4. PCRE wasn't doing the "first character" optimization for patterns starting +with \b or \B, though it was doing it for other lookbehind assertions. That is, +it wasn't noticing that a match for a pattern such as /\bxyz/ has to start with +the letter 'x'. On long subject strings, this gives a significant speed-up. + + +Version 2.05 21-Apr-99 +---------------------- + +1. Changed the type of magic_number from int to long int so that it works +properly on 16-bit systems. + +2. Fixed a bug which caused patterns starting with .* not to work correctly +when the subject string contained newline characters. PCRE was assuming +anchoring for such patterns in all cases, which is not correct because .* will +not pass a newline unless PCRE_DOTALL is set. It now assumes anchoring only if +DOTALL is set at top level; otherwise it knows that patterns starting with .* +must be retried after every newline in the subject. + + +Version 2.04 18-Feb-99 +---------------------- + +1. For parenthesized subpatterns with repeats whose minimum was zero, the +computation of the store needed to hold the pattern was incorrect (too large). +If such patterns were nested a few deep, this could multiply and become a real +problem. + +2. Added /M option to pcretest to show the memory requirement of a specific +pattern. Made -m a synonym of -s (which does this globally) for compatibility. + +3. Subpatterns of the form (regex){n,m} (i.e. limited maximum) were being +compiled in such a way that the backtracking after subsequent failure was +pessimal. Something like (a){0,3} was compiled as (a)?(a)?(a)? instead of +((a)((a)(a)?)?)? with disastrous performance if the maximum was of any size. + + +Version 2.03 02-Feb-99 +---------------------- + +1. Fixed typo and small mistake in man page. + +2. Added 4th condition (GPL supersedes if conflict) and created separate +LICENCE file containing the conditions. + +3. Updated pcretest so that patterns such as /abc\/def/ work like they do in +Perl, that is the internal \ allows the delimiter to be included in the +pattern. Locked out the use of \ as a delimiter. If \ immediately follows +the final delimiter, add \ to the end of the pattern (to test the error). + +4. Added the convenience functions for extracting substrings after a successful +match. Updated pcretest to make it able to test these functions. + + +Version 2.02 14-Jan-99 +---------------------- + +1. Initialized the working variables associated with each extraction so that +their saving and restoring doesn't refer to uninitialized store. + +2. Put dummy code into study.c in order to trick the optimizer of the IBM C +compiler for OS/2 into generating correct code. Apparently IBM isn't going to +fix the problem. + +3. Pcretest: the timing code wasn't using LOOPREPEAT for timing execution +calls, and wasn't printing the correct value for compiling calls. Increased the +default value of LOOPREPEAT, and the number of significant figures in the +times. + +4. Changed "/bin/rm" in the Makefile to "-rm" so it works on Windows NT. + +5. Renamed "deftables" as "dftables" to get it down to 8 characters, to avoid +a building problem on Windows NT with a FAT file system. + + +Version 2.01 21-Oct-98 +---------------------- + +1. Changed the API for pcre_compile() to allow for the provision of a pointer +to character tables built by pcre_maketables() in the current locale. If NULL +is passed, the default tables are used. + + +Version 2.00 24-Sep-98 +---------------------- + +1. Since the (>?) facility is in Perl 5.005, don't require PCRE_EXTRA to enable +it any more. + +2. Allow quantification of (?>) groups, and make it work correctly. + +3. The first character computation wasn't working for (?>) groups. + +4. Correct the implementation of \Z (it is permitted to match on the \n at the +end of the subject) and add 5.005's \z, which really does match only at the +very end of the subject. + +5. Remove the \X "cut" facility; Perl doesn't have it, and (?> is neater. + +6. Remove the ability to specify CASELESS, MULTILINE, DOTALL, and +DOLLAR_END_ONLY at runtime, to make it possible to implement the Perl 5.005 +localized options. All options to pcre_study() were also removed. + +7. Add other new features from 5.005: + + $(?<= positive lookbehind + $(?a*))*/ (a PCRE_EXTRA facility). + + +Version 1.00 18-Nov-97 +---------------------- + +1. Added compile-time macros to support systems such as SunOS4 which don't have +memmove() or strerror() but have other things that can be used instead. + +2. Arranged that "make clean" removes the executables. + + +Version 0.99 27-Oct-97 +---------------------- + +1. Fixed bug in code for optimizing classes with only one character. It was +initializing a 32-byte map regardless, which could cause it to run off the end +of the memory it had got. + +2. Added, conditional on PCRE_EXTRA, the proposed (?>REGEX) construction. + + +Version 0.98 22-Oct-97 +---------------------- + +1. Fixed bug in code for handling temporary memory usage when there are more +back references than supplied space in the ovector. This could cause segfaults. + + +Version 0.97 21-Oct-97 +---------------------- + +1. Added the \X "cut" facility, conditional on PCRE_EXTRA. + +2. Optimized negated single characters not to use a bit map. + +3. Brought error texts together as macro definitions; clarified some of them; +fixed one that was wrong - it said "range out of order" when it meant "invalid +escape sequence". + +4. Changed some char * arguments to const char *. + +5. Added PCRE_NOTBOL and PCRE_NOTEOL (from POSIX). + +6. Added the POSIX-style API wrapper in pcreposix.a and testing facilities in +pcretest. + + +Version 0.96 16-Oct-97 +---------------------- + +1. Added a simple "pgrep" utility to the distribution. + +2. Fixed an incompatibility with Perl: "{" is now treated as a normal character +unless it appears in one of the precise forms "{ddd}", "{ddd,}", or "{ddd,ddd}" +where "ddd" means "one or more decimal digits". + +3. Fixed serious bug. If a pattern had a back reference, but the call to +pcre_exec() didn't supply a large enough ovector to record the related +identifying subpattern, the match always failed. PCRE now remembers the number +of the largest back reference, and gets some temporary memory in which to save +the offsets during matching if necessary, in order to ensure that +backreferences always work. + +4. Increased the compatibility with Perl in a number of ways: + + (a) . no longer matches \n by default; an option PCRE_DOTALL is provided + to request this handling. The option can be set at compile or exec time. + + (b) $ matches before a terminating newline by default; an option + PCRE_DOLLAR_ENDONLY is provided to override this (but not in multiline + mode). The option can be set at compile or exec time. + + (c) The handling of \ followed by a digit other than 0 is now supposed to be + the same as Perl's. If the decimal number it represents is less than 10 + or there aren't that many previous left capturing parentheses, an octal + escape is read. Inside a character class, it's always an octal escape, + even if it is a single digit. + + (d) An escaped but undefined alphabetic character is taken as a literal, + unless PCRE_EXTRA is set. Currently this just reserves the remaining + escapes. + + (e) {0} is now permitted. (The previous item is removed from the compiled + pattern). + +5. Changed all the names of code files so that the basic parts are no longer +than 10 characters, and abolished the teeny "globals.c" file. + +6. Changed the handling of character classes; they are now done with a 32-byte +bit map always. + +7. Added the -d and /D options to pcretest to make it possible to look at the +internals of compilation without having to recompile pcre. + + +Version 0.95 23-Sep-97 +---------------------- + +1. Fixed bug in pre-pass concerning escaped "normal" characters such as \x5c or +\x20 at the start of a run of normal characters. These were being treated as +real characters, instead of the source characters being re-checked. + + +Version 0.94 18-Sep-97 +---------------------- + +1. The functions are now thread-safe, with the caveat that the global variables +containing pointers to malloc() and free() or alternative functions are the +same for all threads. + +2. Get pcre_study() to generate a bitmap of initial characters for non- +anchored patterns when this is possible, and use it if passed to pcre_exec(). + + +Version 0.93 15-Sep-97 +---------------------- + +1. /(b)|(:+)/ was computing an incorrect first character. + +2. Add pcre_study() to the API and the passing of pcre_extra to pcre_exec(), +but not actually doing anything yet. + +3. Treat "-" characters in classes that cannot be part of ranges as literals, +as Perl does (e.g. [-az] or [az-]). + +4. Set the anchored flag if a branch starts with .* or .*? because that tests +all possible positions. + +5. Split up into different modules to avoid including unneeded functions in a +compiled binary. However, compile and exec are still in one module. The "study" +function is split off. + +6. The character tables are now in a separate module whose source is generated +by an auxiliary program - but can then be edited by hand if required. There are +now no calls to isalnum(), isspace(), isdigit(), isxdigit(), tolower() or +toupper() in the code. + +7. Turn the malloc/free funtions variables into pcre_malloc and pcre_free and +make them global. Abolish the function for setting them, as the caller can now +set them directly. + + +Version 0.92 11-Sep-97 +---------------------- + +1. A repeat with a fixed maximum and a minimum of 1 for an ordinary character +(e.g. /a{1,3}/) was broken (I mis-optimized it). + +2. Caseless matching was not working in character classes if the characters in +the pattern were in upper case. + +3. Make ranges like [W-c] work in the same way as Perl for caseless matching. + +4. Make PCRE_ANCHORED public and accept as a compile option. + +5. Add an options word to pcre_exec() and accept PCRE_ANCHORED and +PCRE_CASELESS at run time. Add escapes \A and \I to pcretest to cause it to +pass them. + +6. Give an error if bad option bits passed at compile or run time. + +7. Add PCRE_MULTILINE at compile and exec time, and (?m) as well. Add \M to +pcretest to cause it to pass that flag. + +8. Add pcre_info(), to get the number of identifying subpatterns, the stored +options, and the first character, if set. + +9. Recognize C+ or C{n,m} where n >= 1 as providing a fixed starting character. + + +Version 0.91 10-Sep-97 +---------------------- + +1. PCRE was failing to diagnose unlimited repeats of subpatterns that could +match the empty string as in /(a*)*/. It was looping and ultimately crashing. + +2. PCRE was looping on encountering an indefinitely repeated back reference to +a subpattern that had matched an empty string, e.g. /(a|)\1*/. It now does what +Perl does - treats the match as successful. + +**** diff --git a/lc-continuity/mk4/continuity/pcre/INSTALL b/lc-continuity/mk4/continuity/pcre/INSTALL new file mode 100644 index 0000000000000000000000000000000000000000..08802812deb48df8728d3780a70951ea4ab9c657 --- /dev/null +++ b/lc-continuity/mk4/continuity/pcre/INSTALL @@ -0,0 +1,185 @@ +Basic Installation +================== + + These are generic installation instructions that apply to systems that +can run the `configure' shell script - Unix systems and any that imitate +it. They are not specific to PCRE. There are PCRE-specific instructions +for non-Unix systems in the file NON-UNIX-USE. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. diff --git a/lc-continuity/mk4/continuity/pcre/LICENCE b/lc-continuity/mk4/continuity/pcre/LICENCE new file mode 100644 index 0000000000000000000000000000000000000000..8d680612c434c7410a369053d6d47ac121f7b314 --- /dev/null +++ b/lc-continuity/mk4/continuity/pcre/LICENCE @@ -0,0 +1,54 @@ +PCRE LICENCE +------------ + +PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + +Written by: Philip Hazel + +University of Cambridge Computing Service, +Cambridge, England. Phone: +44 1223 334714. + +Copyright (c) 1997-2001 University of Cambridge + +Permission is granted to anyone to use this software for any purpose on any +computer system, and to redistribute it freely, subject to the following +restrictions: + +1. This software 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. + +2. The origin of this software must not be misrepresented, either by + explicit claim or by omission. In practice, this means that if you use + PCRE in software that you distribute to others, commercially or + otherwise, you must put a sentence like this + + Regular expression support is provided by the PCRE library package, + which is open source software, written by Philip Hazel, and copyright + by the University of Cambridge, England. + + somewhere reasonably visible in your documentation and in any relevant + files or online help data or similar. A reference to the ftp site for + the source, that is, to + + ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/ + + should also be given in the documentation. However, this condition is not + intended to apply to whole chains of software. If package A includes PCRE, + it must acknowledge it, but if package B is software that includes package + A, the condition is not imposed on package B (unless it uses PCRE + independently). + +3. Altered versions must be plainly marked as such, and must not be + misrepresented as being the original software. + +4. If PCRE is embedded in any software that is released under the GNU + General Purpose Licence (GPL), or Lesser General Purpose Licence (LGPL), + then the terms of that licence shall supersede any condition above with + which it is incompatible. + +The documentation for PCRE, supplied in the "doc" directory, is distributed +under the same terms as the software itself. + +End diff --git a/lc-continuity/mk4/continuity/pcre/Makefile.in b/lc-continuity/mk4/continuity/pcre/Makefile.in new file mode 100644 index 0000000000000000000000000000000000000000..ecdd6eff0770cbd1c356b841e7e45fabedb59768 --- /dev/null +++ b/lc-continuity/mk4/continuity/pcre/Makefile.in @@ -0,0 +1,282 @@ + +# Makefile.in for PCRE (Perl-Compatible Regular Expression) library. + +#---------------------------------------------------------------------------# +# MinGW DLLs are built automatically with this configure.in and Makefile.in # +# as long you are using autoconf 2.50 or higher. The Win32 static libraries # +# have not been tested, but appear to be generated. This functionality is # +# by courtesy of Fred Cox. I (Philip Hazel) don't know anything about it, # +# as I live entirely in a non-Windows world. # +#---------------------------------------------------------------------------# + + +############################################################################# + +# PCRE is developed on a Unix system. I do not use Windows or Macs, and know +# nothing about building software on them. Although the code of PCRE should +# be very portable, the building system in this Makefile is designed for Unix +# systems, with the exception of the mingw32 stuff just mentioned. + +# This setting enables Unix-style directory scanning in pcregrep, triggered +# by the -f option. Maybe one day someone will add code for other systems. + +PCREGREP_OSTYPE=-DIS_UNIX + +############################################################################# + + +#---------------------------------------------------------------------------# +# The following lines are modified by "configure" to insert data that it is # +# given in its arguments, or which it finds out for itself. # +#---------------------------------------------------------------------------# + +SHELL = @SHELL@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ +top_srcdir = @top_srcdir@ + +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs + +# NB: top_builddir is not referred to directly below, but it is used in the +# setting of $(LIBTOOL), so don't remove it! + +top_builddir = . + +# BINDIR is the directory in which the pcregrep, pcretest, and pcre-config +# commands are installed. +# INCDIR is the directory in which the public header files pcre.h and +# pcreposix.h are installed. +# LIBDIR is the directory in which the libraries are installed. +# MANDIR is the directory in which the man pages are installed. + +BINDIR = @bindir@ +LIBDIR = @libdir@ +INCDIR = @includedir@ +MANDIR = @mandir@ + +# EXEEXT is set by configure to the extention of an executable file +# OBJEXT is set by configure to the extention of an object file +# The BUILD_* equivalents are the same but for the host we're building on + +EXEEXT = @EXEEXT@ +OBJEXT = @OBJEXT@ +# Note that these are just here to have a convenient place to look at the +# outcome. +BUILD_EXEEXT = @BUILD_EXEEXT@ +BUILD_OBJEXT = @BUILD_OBJEXT@ + +# The compiler, C flags, preprocessor flags, etc + +CC = @CC@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@ +UTF8 = @UTF8@ +NEWLINE = @NEWLINE@ +POSIX_MALLOC_THRESHOLD = @POSIX_MALLOC_THRESHOLD@ +LINK_SIZE = @LINK_SIZE@ +MATCH_LIMIT= @MATCH_LIMIT@ + +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ + +# LIBTOOL enables the building of shared and static libraries. It is set up +# to do one or the other or both by ./configure. + +LIBTOOL = @LIBTOOL@ +LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) -c $(CFLAGS) -I. -I$(top_srcdir) $(NEWLINE) $(LINK_SIZE) $(MATCH_LIMIT) +@ON_WINDOWS@LINK = $(CC) $(CFLAGS) -I. -I$(top_srcdir) -L.libs +@NOT_ON_WINDOWS@LINK = $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -I. -I$(top_srcdir) +LINKLIB = $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -I. -I$(top_srcdir) +LINK_FOR_BUILD = $(LIBTOOL) --mode=link $(CC_FOR_BUILD) $(CFLAGS_FOR_BUILD) -I. -I$(top_srcdir) + +# These are the version numbers for the shared libraries + +PCRELIBVERSION = @PCRE_LIB_VERSION@ +PCREPOSIXLIBVERSION = @PCRE_POSIXLIB_VERSION@ + +############################################################################## + + +OBJ = maketables.@OBJEXT@ get.@OBJEXT@ study.@OBJEXT@ pcre.@OBJEXT@ @POSIX_OBJ@ +LOBJ = maketables.lo get.lo study.lo pcre.lo @POSIX_LOBJ@ + +all: libpcre.la @POSIX_LIB@ pcretest@EXEEXT@ pcregrep@EXEEXT@ @ON_WINDOWS@ winshared + +pcregrep@EXEEXT@: libpcre.la pcregrep.@OBJEXT@ @ON_WINDOWS@ winshared + $(LINK) -o pcregrep@EXEEXT@ pcregrep.@OBJEXT@ -lpcre + +pcretest@EXEEXT@: libpcre.la @POSIX_LIB@ pcretest.@OBJEXT@ @ON_WINDOWS@ winshared + $(LINK) $(PURIFY) $(EFENCE) -o pcretest@EXEEXT@ pcretest.@OBJEXT@ \ + -lpcre @POSIX_LIB@ + +libpcre.la: $(OBJ) + -rm -f libpcre.la + $(LINKLIB) -rpath $(LIBDIR) -version-info \ + '$(PCRELIBVERSION)' -o libpcre.la $(LOBJ) + +libpcreposix.la: pcreposix.@OBJEXT@ + -rm -f libpcreposix.la + $(LINKLIB) -rpath $(LIBDIR) -L. -lpcre -version-info \ + '$(PCREPOSIXLIBVERSION)' -o libpcreposix.la pcreposix.lo + +pcre.@OBJEXT@: $(top_srcdir)/chartables.c $(top_srcdir)/pcre.c \ + $(top_srcdir)/internal.h $(top_srcdir)/printint.c \ + pcre.h config.h Makefile + $(LTCOMPILE) $(UTF8) $(POSIX_MALLOC_THRESHOLD) $(top_srcdir)/pcre.c + +pcreposix.@OBJEXT@: $(top_srcdir)/pcreposix.c $(top_srcdir)/pcreposix.h \ + $(top_srcdir)/internal.h pcre.h config.h Makefile + $(LTCOMPILE) $(POSIX_MALLOC_THRESHOLD) $(top_srcdir)/pcreposix.c + +maketables.@OBJEXT@: $(top_srcdir)/maketables.c $(top_srcdir)/internal.h \ + pcre.h config.h Makefile + $(LTCOMPILE) $(top_srcdir)/maketables.c + +get.@OBJEXT@: $(top_srcdir)/get.c $(top_srcdir)/internal.h \ + pcre.h config.h Makefile + $(LTCOMPILE) $(top_srcdir)/get.c + +study.@OBJEXT@: $(top_srcdir)/study.c $(top_srcdir)/internal.h \ + pcre.h config.h Makefile + $(LTCOMPILE) $(UTF8) $(top_srcdir)/study.c + +pcretest.@OBJEXT@: $(top_srcdir)/pcretest.c $(top_srcdir)/internal.h \ + $(top_srcdir)/printint.c \ + pcre.h config.h Makefile + $(CC) -c $(CFLAGS) -I. $(UTF8) $(LINK_SIZE) $(top_srcdir)/pcretest.c + +pcregrep.@OBJEXT@: $(top_srcdir)/pcregrep.c pcre.h Makefile config.h + $(CC) -c $(CFLAGS) -I. $(UTF8) $(PCREGREP_OSTYPE) $(top_srcdir)/pcregrep.c + +# Some Windows-specific targets, for Cygwin and MinGW + +winshared : .libs/@WIN_PREFIX@pcre.dll .libs/@WIN_PREFIX@pcreposix.dll + +.libs/@WIN_PREFIX@pcre.dll : libpcre.la + $(CC) $(CFLAGS) -shared -o $@ \ + -Wl,--whole-archive .libs/libpcre.a \ + -Wl,--out-implib,.libs/libpcre.dll.a \ + -Wl,--output-def,.libs/@WIN_PREFIX@pcre.dll-def \ + -Wl,--export-all-symbols \ + -Wl,--no-whole-archive + sed -e "s#dlname=''#dlname='../bin/@WIN_PREFIX@pcre.dll'#" \ + -e "s#library_names=''#library_names='libpcre.dll.a'#" \ + < .libs/libpcre.lai > .libs/libpcre.lai.tmp && \ + mv .libs/libpcre.lai.tmp .libs/libpcre.lai + sed -e "s#dlname=''#dlname='../bin/@WIN_PREFIX@pcre.dll'#" \ + -e "s#library_names=''#library_names='libpcre.dll.a'#" \ + < libpcre.la > libpcre.la.tmp && \ + mv libpcre.la.tmp libpcre.la + + +.libs/@WIN_PREFIX@pcreposix.dll: libpcreposix.la libpcre.la + $(CC) $(CFLAGS) -shared -o $@ \ + -Wl,--whole-archive .libs/libpcreposix.a \ + -Wl,--out-implib,.libs/lib@WIN_PREFIX@pcreposix.dll.a \ + -Wl,--output-def,.libs/@WIN_PREFIX@pcreposix.dll-def \ + -Wl,--export-all-symbols \ + -Wl,--no-whole-archive .libs/libpcre.a + sed -e "s#dlname=''#dlname='../bin/@WIN_PREFIX@pcreposix.dll'#" \ + -e "s#library_names=''#library_names='libpcreposix.dll.a'#"\ + < .libs/libpcreposix.lai > .libs/libpcreposix.lai.tmp && \ + mv .libs/libpcreposix.lai.tmp .libs/libpcreposix.lai + sed -e "s#dlname=''#dlname='../bin/@WIN_PREFIX@pcreposix.dll'#" \ + -e "s#library_names=''#library_names='libpcreposix.dll.a'#"\ + < libpcreposix.la > libpcreposix.la.tmp && \ + mv libpcreposix.la.tmp libpcreposix.la + + +wininstall : winshared + $(mkinstalldirs) $(DESTDIR)$(LIBDIR) + $(mkinstalldirs) $(DESTDIR)$(BINDIR) + $(INSTALL) .libs/@WIN_PREFIX@pcre.dll $(DESTDIR)$(BINDIR)/@WIN_PREFIX@pcre.dll + $(INSTALL) .libs/@WIN_PREFIX@pcreposix.dll $(DESTDIR)$(BINDIR)/@WIN_PREFIX@pcreposix.dll + $(INSTALL) .libs/@WIN_PREFIX@libpcreposix.dll.a $(DESTDIR)$(LIBDIR)/@WIN_PREFIX@libpcreposix.dll.a + $(INSTALL) .libs/@WIN_PREFIX@libpcre.dll.a $(DESTDIR)$(LIBDIR)/@WIN_PREFIX@libpcre.dll.a + -strip -g $(DESTDIR)$(BINDIR)/@WIN_PREFIX@pcre.dll + -strip -g $(DESTDIR)$(BINDIR)/@WIN_PREFIX@pcreposix.dll + -strip $(DESTDIR)$(BINDIR)/pcregrep@EXEEXT@ + -strip $(DESTDIR)$(BINDIR)/pcretest@EXEEXT@ + +# An auxiliary program makes the default character table source + +$(top_srcdir)/chartables.c: dftables + ./dftables >$(top_srcdir)/chartables.c + +dftables.@BUILD_OBJEXT@: $(top_srcdir)/dftables.c $(top_srcdir)/maketables.c \ + $(top_srcdir)/internal.h pcre.h config.h Makefile + $(CC_FOR_BUILD) -c $(CFLAGS_FOR_BUILD) -I. $(top_srcdir)/dftables.c + +dftables: dftables.@BUILD_OBJEXT@ + $(LINK_FOR_BUILD) -o dftables dftables.@OBJEXT@ + +install: all @ON_WINDOWS@ wininstall +@NOT_ON_WINDOWS@ $(mkinstalldirs) $(DESTDIR)$(LIBDIR) +@NOT_ON_WINDOWS@ echo "$(LIBTOOL) --mode=install $(INSTALL) libpcre.la $(DESTDIR)$(LIBDIR)/libpcre.la" +@NOT_ON_WINDOWS@ $(LIBTOOL) --mode=install $(INSTALL) libpcre.la $(DESTDIR)$(LIBDIR)/libpcre.la +@NOT_ON_WINDOWS@ echo "$(LIBTOOL) --mode=install $(INSTALL) libpcreposix.la $(DESTDIR)$(LIBDIR)/libpcreposix.la" +@NOT_ON_WINDOWS@ $(LIBTOOL) --mode=install $(INSTALL) libpcreposix.la $(DESTDIR)$(LIBDIR)/libpcreposix.la +@NOT_ON_WINDOWS@ $(LIBTOOL) --finish $(DESTDIR)$(LIBDIR) + $(mkinstalldirs) $(DESTDIR)$(INCDIR) + $(INSTALL_DATA) pcre.h $(DESTDIR)$(INCDIR)/pcre.h + $(INSTALL_DATA) $(top_srcdir)/pcreposix.h $(DESTDIR)$(INCDIR)/pcreposix.h + $(mkinstalldirs) $(DESTDIR)$(MANDIR)/man3 + $(INSTALL_DATA) $(top_srcdir)/doc/pcre.3 $(DESTDIR)$(MANDIR)/man3/pcre.3 + $(INSTALL_DATA) $(top_srcdir)/doc/pcreapi.3 $(DESTDIR)$(MANDIR)/man3/pcreapi.3 + $(INSTALL_DATA) $(top_srcdir)/doc/pcrebuild.3 $(DESTDIR)$(MANDIR)/man3/pcrebuild.3 + $(INSTALL_DATA) $(top_srcdir)/doc/pcrecallout.3 $(DESTDIR)$(MANDIR)/man3/pcrecallout.3 + $(INSTALL_DATA) $(top_srcdir)/doc/pcrecompat.3 $(DESTDIR)$(MANDIR)/man3/pcrecompat.3 + $(INSTALL_DATA) $(top_srcdir)/doc/pcrepattern.3 $(DESTDIR)$(MANDIR)/man3/pcrepattern.3 + $(INSTALL_DATA) $(top_srcdir)/doc/pcreperform.3 $(DESTDIR)$(MANDIR)/man3/pcreperform.3 + $(INSTALL_DATA) $(top_srcdir)/doc/pcreposix.3 $(DESTDIR)$(MANDIR)/man3/pcreposix.3 + $(INSTALL_DATA) $(top_srcdir)/doc/pcresample.3 $(DESTDIR)$(MANDIR)/man3/pcresample.3 + $(INSTALL_DATA) $(top_srcdir)/doc/pcre_compile.3 $(DESTDIR)$(MANDIR)/man3/pcre_compile.3 + $(INSTALL_DATA) $(top_srcdir)/doc/pcre_config.3 $(DESTDIR)$(MANDIR)/man3/pcre_config.3 + $(INSTALL_DATA) $(top_srcdir)/doc/pcre_copy_named_substring.3 $(DESTDIR)$(MANDIR)/man3/pcre_copy_named_substring.3 + $(INSTALL_DATA) $(top_srcdir)/doc/pcre_copy_substring.3 $(DESTDIR)$(MANDIR)/man3/pcre_copy_substring.3 + $(INSTALL_DATA) $(top_srcdir)/doc/pcre_exec.3 $(DESTDIR)$(MANDIR)/man3/pcre_exec.3 + $(INSTALL_DATA) $(top_srcdir)/doc/pcre_free_substring.3 $(DESTDIR)$(MANDIR)/man3/pcre_free_substring.3 + $(INSTALL_DATA) $(top_srcdir)/doc/pcre_free_substring_list.3 $(DESTDIR)$(MANDIR)/man3/pcre_free_substring_list.3 + $(INSTALL_DATA) $(top_srcdir)/doc/pcre_fullinfo.3 $(DESTDIR)$(MANDIR)/man3/pcre_fullinfo.3 + $(INSTALL_DATA) $(top_srcdir)/doc/pcre_get_named_substring.3 $(DESTDIR)$(MANDIR)/man3/pcre_get_named_substring.3 + $(INSTALL_DATA) $(top_srcdir)/doc/pcre_get_stringnumber.3 $(DESTDIR)$(MANDIR)/man3/pcre_get_stringnumber.3 + $(INSTALL_DATA) $(top_srcdir)/doc/pcre_get_substring.3 $(DESTDIR)$(MANDIR)/man3/pcre_get_substring.3 + $(INSTALL_DATA) $(top_srcdir)/doc/pcre_get_substring_list.3 $(DESTDIR)$(MANDIR)/man3/pcre_get_substring_list.3 + $(INSTALL_DATA) $(top_srcdir)/doc/pcre_info.3 $(DESTDIR)$(MANDIR)/man3/pcre_info.3 + $(INSTALL_DATA) $(top_srcdir)/doc/pcre_maketables.3 $(DESTDIR)$(MANDIR)/man3/pcre_maketables.3 + $(INSTALL_DATA) $(top_srcdir)/doc/pcre_study.3 $(DESTDIR)$(MANDIR)/man3/pcre_study.3 + $(INSTALL_DATA) $(top_srcdir)/doc/pcre_version.3 $(DESTDIR)$(MANDIR)/man3/pcre_version.3 + $(mkinstalldirs) $(DESTDIR)$(MANDIR)/man1 + $(INSTALL_DATA) $(top_srcdir)/doc/pcregrep.1 $(DESTDIR)$(MANDIR)/man1/pcregrep.1 + $(INSTALL_DATA) $(top_srcdir)/doc/pcretest.1 $(DESTDIR)$(MANDIR)/man1/pcretest.1 + $(mkinstalldirs) $(DESTDIR)$(BINDIR) + $(LIBTOOL) --mode=install $(INSTALL) pcregrep@EXEEXT@ $(DESTDIR)$(BINDIR)/pcregrep@EXEEXT@ + $(LIBTOOL) --mode=install $(INSTALL) pcretest@EXEEXT@ $(DESTDIR)$(BINDIR)/pcretest@EXEEXT@ + $(INSTALL) pcre-config $(DESTDIR)$(BINDIR)/pcre-config + +# We deliberately omit dftables and chartables.c from 'make clean'; once made +# chartables.c shouldn't change, and if people have edited the tables by hand, +# you don't want to throw them away. + +clean:; -rm -rf *.@OBJEXT@ *.lo *.a *.la .libs pcretest@EXEEXT@ pcregrep@EXEEXT@ testtry + +# But "make distclean" should get back to a virgin distribution + +distclean: clean + -rm -f chartables.c libtool pcre-config pcre.h \ + Makefile config.h config.status config.log config.cache + +check: runtest + +@WIN_PREFIX@pcre.dll : winshared + cp .libs/@WIN_PREFIX@pcre.dll . + +test: runtest + +runtest: all @ON_WINDOWS@ @WIN_PREFIX@pcre.dll + ./RunTest + +# End diff --git a/lc-continuity/mk4/continuity/pcre/NEWS b/lc-continuity/mk4/continuity/pcre/NEWS new file mode 100644 index 0000000000000000000000000000000000000000..e620b2d727a99b08f3122a9f259ac238270e85f3 --- /dev/null +++ b/lc-continuity/mk4/continuity/pcre/NEWS @@ -0,0 +1,123 @@ +News about PCRE releases +------------------------ + +Release 4.0 17-Feb-03 +--------------------- + +There have been a lot of changes for the 4.0 release, adding additional +functionality and mending bugs. Below is a list of the highlights of the new +functionality. For full details of these features, please consult the +documentation. For a complete list of changes, see the ChangeLog file. + +1. Support for Perl's \Q...\E escapes. + +2. "Possessive quantifiers" ?+, *+, ++, and {,}+ which come from Sun's Java +package. They provide some syntactic sugar for simple cases of "atomic +grouping". + +3. Support for the \G assertion. It is true when the current matching position +is at the start point of the match. + +4. A new feature that provides some of the functionality that Perl provides +with (?{...}). The facility is termed a "callout". The way it is done in PCRE +is for the caller to provide an optional function, by setting pcre_callout to +its entry point. To get the function called, the regex must include (?C) at +appropriate points. + +5. Support for recursive calls to individual subpatterns. This makes it really +easy to get totally confused. + +6. Support for named subpatterns. The Python syntax (?P...) is used to +name a group. + +7. Several extensions to UTF-8 support; it is now fairly complete. There is an +option for pcregrep to make it operate in UTF-8 mode. + +8. The single man page has been split into a number of separate man pages. +These also give rise to individual HTML pages which are put in a separate +directory. There is an index.html page that lists them all. Some hyperlinking +between the pages has been installed. + + +Release 3.5 15-Aug-01 +--------------------- + +1. The configuring system has been upgraded to use later versions of autoconf +and libtool. By default it builds both a shared and a static library if the OS +supports it. You can use --disable-shared or --disable-static on the configure +command if you want only one of them. + +2. The pcretest utility is now installed along with pcregrep because it is +useful for users (to test regexs) and by doing this, it automatically gets +relinked by libtool. The documentation has been turned into a man page, so +there are now .1, .txt, and .html versions in /doc. + +3. Upgrades to pcregrep: + (i) Added long-form option names like gnu grep. + (ii) Added --help to list all options with an explanatory phrase. + (iii) Added -r, --recursive to recurse into sub-directories. + (iv) Added -f, --file to read patterns from a file. + +4. Added --enable-newline-is-cr and --enable-newline-is-lf to the configure +script, to force use of CR or LF instead of \n in the source. On non-Unix +systems, the value can be set in config.h. + +5. The limit of 200 on non-capturing parentheses is a _nesting_ limit, not an +absolute limit. Changed the text of the error message to make this clear, and +likewise updated the man page. + +6. The limit of 99 on the number of capturing subpatterns has been removed. +The new limit is 65535, which I hope will not be a "real" limit. + + +Release 3.3 01-Aug-00 +--------------------- + +There is some support for UTF-8 character strings. This is incomplete and +experimental. The documentation describes what is and what is not implemented. +Otherwise, this is just a bug-fixing release. + + +Release 3.0 01-Feb-00 +--------------------- + +1. A "configure" script is now used to configure PCRE for Unix systems. It +builds a Makefile, a config.h file, and the pcre-config script. + +2. PCRE is built as a shared library by default. + +3. There is support for POSIX classes such as [:alpha:]. + +5. There is an experimental recursion feature. + +---------------------------------------------------------------------------- + IMPORTANT FOR THOSE UPGRADING FROM VERSIONS BEFORE 2.00 + +Please note that there has been a change in the API such that a larger +ovector is required at matching time, to provide some additional workspace. +The new man page has details. This change was necessary in order to support +some of the new functionality in Perl 5.005. + + IMPORTANT FOR THOSE UPGRADING FROM VERSION 2.00 + +Another (I hope this is the last!) change has been made to the API for the +pcre_compile() function. An additional argument has been added to make it +possible to pass over a pointer to character tables built in the current +locale by pcre_maketables(). To use the default tables, this new arguement +should be passed as NULL. + + IMPORTANT FOR THOSE UPGRADING FROM VERSION 2.05 + +Yet another (and again I hope this really is the last) change has been made +to the API for the pcre_exec() function. An additional argument has been +added to make it possible to start the match other than at the start of the +subject string. This is important if there are lookbehinds. The new man +page has the details, but you just want to convert existing programs, all +you need to do is to stick in a new fifth argument to pcre_exec(), with a +value of zero. For example, change + + pcre_exec(pattern, extra, subject, length, options, ovec, ovecsize) +to + pcre_exec(pattern, extra, subject, length, 0, options, ovec, ovecsize) + +**** diff --git a/lc-continuity/mk4/continuity/pcre/NON-UNIX-USE b/lc-continuity/mk4/continuity/pcre/NON-UNIX-USE new file mode 100644 index 0000000000000000000000000000000000000000..a000c29d4193d2c4c403f6d7f5df273c6de230d4 --- /dev/null +++ b/lc-continuity/mk4/continuity/pcre/NON-UNIX-USE @@ -0,0 +1,113 @@ +Compiling PCRE on non-Unix systems +---------------------------------- + +See below for comments on Cygwin or MinGW usage. + +If you want to compile PCRE for a non-Unix system, note that it consists +entirely of code written in Standard C, and so should compile successfully +on any machine with a Standard C compiler and library, using normal compiling +commands to do the following: + +(1) Copy or rename the file config.in as config.h, and change the macros that +define HAVE_STRERROR and HAVE_MEMMOVE to define them as 1 rather than 0. +Unfortunately, because of the way Unix autoconf works, the default setting has +to be 0. You may also want to make changes to other macros in config.h. In +particular, if you want to force a specific value for newline, you can define +the NEWLINE macro. The default is to use '\n', thereby using whatever value +your compiler gives to '\n'. + +(2) Copy or rename the file pcre.in as pcre.h, and change the macro definitions +for PCRE_MAJOR, PCRE_MINOR, and PCRE_DATE near its start to the values set in +configure.in. + +(3) Compile dftables.c as a stand-alone program, and then run it with +the standard output sent to chartables.c. This generates a set of standard +character tables. + +(4) Compile maketables.c, get.c, study.c and pcre.c and link them all +together into an object library in whichever form your system keeps such +libraries. This is the pcre library (chartables.c is included by means of an +#include directive). + +(5) Similarly, compile pcreposix.c and link it as the pcreposix library. + +(6) Compile the test program pcretest.c. This needs the functions in the +pcre and pcreposix libraries when linking. + +(7) Run pcretest on the testinput files in the testdata directory, and check +that the output matches the corresponding testoutput files. You must use the +-i option when checking testinput2. Note that the supplied files are in Unix +format, with just LF characters as line terminators. You may need to edit them +to change this if your system uses a different convention. + +If you have a system without "configure" but where you can use a Makefile, edit +Makefile.in to create Makefile, substituting suitable values for the variables +at the head of the file. + +Some help in building a Win32 DLL of PCRE in GnuWin32 environments was +contributed by Paul Sokolovsky. These environments are Mingw32 +(http://www.xraylith.wisc.edu/~khan/software/gnu-win32/) and CygWin +(http://sourceware.cygnus.com/cygwin/). Paul comments: + + For CygWin, set CFLAGS=-mno-cygwin, and do 'make dll'. You'll get + pcre.dll (containing pcreposix also), libpcre.dll.a, and dynamically + linked pgrep and pcretest. If you have /bin/sh, run RunTest (three + main test go ok, locale not supported). + +Changes to do MinGW with autoconf 2.50 were supplied by Fred Cox +, who comments as follows: + + If you are using the PCRE DLL, the normal Unix style configure && make && + make check && make install should just work[*]. If you want to statically + link against the .a file, you must define PCRE_STATIC before including + pcre.h, otherwise the pcre_malloc and pcre_free exported functions will be + declared __declspec(dllimport), with hilarious results. See the configure.in + and pcretest.c for how it is done for the static test. + + Also, there will only be a libpcre.la, not a libpcreposix.la, as you + would expect from the Unix version. The single DLL includes the pcreposix + interface. + +[*] But note that the supplied test files are in Unix format, with just LF +characters as line terminators. You will have to edit them to change to CR LF +terminators. + +A script for building PCRE using Borland's C++ compiler for use with VPASCAL +was contributed by Alexander Tokarev. It is called makevp.bat. + +These are some further comments about Win32 builds from Mark Evans. They +were contributed before Fred Cox's changes were made, so it is possible that +they may no longer be relevant. + +The documentation for Win32 builds is a bit shy. Under MSVC6 I +followed their instructions to the letter, but there were still +some things missing. + +(1) Must #define STATIC for entire project if linking statically. + (I see no reason to use DLLs for code this compact.) This of + course is a project setting in MSVC under Preprocessor. + +(2) Missing some #ifdefs relating to the function pointers + pcre_malloc and pcre_free. See my solution below. (The stubs + may not be mandatory but they made me feel better.) + +========================= +#ifdef _WIN32 +#include + +void* malloc_stub(size_t N) +{ return malloc(N); } +void free_stub(void* p) +{ free(p); } +void *(*pcre_malloc)(size_t) = &malloc_stub; +void (*pcre_free)(void *) = &free_stub; + +#else + +void *(*pcre_malloc)(size_t) = malloc; +void (*pcre_free)(void *) = free; + +#endif +========================= + +**** diff --git a/lc-continuity/mk4/continuity/pcre/README b/lc-continuity/mk4/continuity/pcre/README new file mode 100644 index 0000000000000000000000000000000000000000..6cef77c7e80199b6a346f85a20f6dad99cbe6617 --- /dev/null +++ b/lc-continuity/mk4/continuity/pcre/README @@ -0,0 +1,357 @@ +README file for PCRE (Perl-compatible regular expression library) +----------------------------------------------------------------- + +The latest release of PCRE is always available from + + ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-xxx.tar.gz + +Please read the NEWS file if you are upgrading from a previous release. + +PCRE has its own native API, but a set of "wrapper" functions that are based on +the POSIX API are also supplied in the library libpcreposix. Note that this +just provides a POSIX calling interface to PCRE: the regular expressions +themselves still follow Perl syntax and semantics. The header file +for the POSIX-style functions is called pcreposix.h. The official POSIX name is +regex.h, but I didn't want to risk possible problems with existing files of +that name by distributing it that way. To use it with an existing program that +uses the POSIX API, it will have to be renamed or pointed at by a link. + + +Contributions by users of PCRE +------------------------------ + +You can find contributions from PCRE users in the directory + + ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/Contrib + +where there is also a README file giving brief descriptions of what they are. +Several of them provide support for compiling PCRE on various flavours of +Windows systems (I myself do not use Windows). Some are complete in themselves; +others are pointers to URLs containing relevant files. + + +Building PCRE on a Unix-like system +----------------------------------- + +To build PCRE on a Unix-like system, first run the "configure" command from the +PCRE distribution directory, with your current directory set to the directory +where you want the files to be created. This command is a standard GNU +"autoconf" configuration script, for which generic instructions are supplied in +INSTALL. + +Most commonly, people build PCRE within its own distribution directory, and in +this case, on many systems, just running "./configure" is sufficient, but the +usual methods of changing standard defaults are available. For example, + +CFLAGS='-O2 -Wall' ./configure --prefix=/opt/local + +specifies that the C compiler should be run with the flags '-O2 -Wall' instead +of the default, and that "make install" should install PCRE under /opt/local +instead of the default /usr/local. + +If you want to build in a different directory, just run "configure" with that +directory as current. For example, suppose you have unpacked the PCRE source +into /source/pcre/pcre-xxx, but you want to build it in /build/pcre/pcre-xxx: + +cd /build/pcre/pcre-xxx +/source/pcre/pcre-xxx/configure + +There are some optional features that can be included or omitted from the PCRE +library. You can read more about them in the pcrebuild man page. + +. If you want to make use of the support for UTF-8 character strings in PCRE, + you must add --enable-utf8 to the "configure" command. Without it, the code + for handling UTF-8 is not included in the library. (Even when included, it + still has to be enabled by an option at run time.) + +. You can build PCRE to recognized CR or NL as the newline character, instead + of whatever your compiler uses for "\n", by adding --newline-is-cr or + --newline-is-nl to the "configure" command, respectively. Only do this if you + really understand what you are doing. On traditional Unix-like systems, the + newline character is NL. + +. When called via the POSIX interface, PCRE uses malloc() to get additional + storage for processing capturing parentheses if there are more than 10 of + them. You can increase this threshold by setting, for example, + + --with-posix-malloc-threshold=20 + + on the "configure" command. + +. PCRE has a counter which can be set to limit the amount of resources it uses. + If the limit is exceeded during a match, the match fails. The default is ten + million. You can change the default by setting, for example, + + --with-match-limit=500000 + + on the "configure" command. This is just the default; individual calls to + pcre_exec() can supply their own value. There is discussion on the pcreapi + man page. + +. The default maximum compiled pattern size is around 64K. You can increase + this by adding --with-link-size=3 to the "configure" command. You can + increase it even more by setting --with-link-size=4, but this is unlikely + ever to be necessary. If you build PCRE with an increased link size, test 2 + (and 5 if you are using UTF-8) will fail. Part of the output of these tests + is a representation of the compiled pattern, and this changes with the link + size. + +The "configure" script builds five files: + +. libtool is a script that builds shared and/or static libraries +. Makefile is built by copying Makefile.in and making substitutions. +. config.h is built by copying config.in and making substitutions. +. pcre-config is built by copying pcre-config.in and making substitutions. +. RunTest is a script for running tests + +Once "configure" has run, you can run "make". It builds two libraries called +libpcre and libpcreposix, a test program called pcretest, and the pcregrep +command. You can use "make install" to copy these, the public header files +pcre.h and pcreposix.h, and the man pages to appropriate live directories on +your system, in the normal way. + +Running "make install" also installs the command pcre-config, which can be used +to recall information about the PCRE configuration and installation. For +example, + + pcre-config --version + +prints the version number, and + + pcre-config --libs + +outputs information about where the library is installed. This command can be +included in makefiles for programs that use PCRE, saving the programmer from +having to remember too many details. + + +Cross-compiling PCRE on a Unix-like system +------------------------------------------ + +PCRE needs to compile and run an auxiliary program as part of the building +process. Obviously, if the real compilation is for some other system, it can't +use the same CC and CFLAGS values when it is doing this. For cross compilation, +therefore, you must set CC_FOR_BUILD to the local host's compiler, and you can +set flags in CFLAGS_FOR_BUILD if you need to. + + +Shared libraries on Unix-like systems +------------------------------------- + +The default distribution builds PCRE as two shared libraries and two static +libraries, as long as the operating system supports shared libraries. Shared +library support relies on the "libtool" script which is built as part of the +"configure" process. + +The libtool script is used to compile and link both shared and static +libraries. They are placed in a subdirectory called .libs when they are newly +built. The programs pcretest and pcregrep are built to use these uninstalled +libraries (by means of wrapper scripts in the case of shared libraries). When +you use "make install" to install shared libraries, pcregrep and pcretest are +automatically re-built to use the newly installed shared libraries before being +installed themselves. However, the versions left in the source directory still +use the uninstalled libraries. + +To build PCRE using static libraries only you must use --disable-shared when +configuring it. For example + +./configure --prefix=/usr/gnu --disable-shared + +Then run "make" in the usual way. Similarly, you can use --disable-static to +build only shared libraries. + + +Cross-compiling on a Unix-like system +------------------------------------- + +You can specify CC and CFLAGS in the normal way to the "configure" command, in +order to cross-compile PCRE for some other host. However, during the building +process, the dftables.c source file is compiled *and run* on the local host, in +order to generate the default character tables (the chartables.c file). It +therefore needs to be compiled with the local compiler, not the cross compiler. +You can do this by specifying HOST_CC (and if necessary HOST_CFLAGS) when +calling the "configure" command. If they are not specified, they default to the +values of CC and CFLAGS. + + +Building on non-Unix systems +---------------------------- + +For a non-Unix system, read the comments in the file NON-UNIX-USE. PCRE has +been compiled on Windows systems and on Macintoshes, but I don't know the +details because I don't use those systems. It should be straightforward to +build PCRE on any system that has a Standard C compiler, because it uses only +Standard C functions. + + +Testing PCRE +------------ + +To test PCRE on a Unix system, run the RunTest script that is created by the +configuring process. (This can also be run by "make runtest", "make check", or +"make test".) For other systems, see the instruction in NON-UNIX-USE. + +The script runs the pcretest test program (which is documented in its own man +page) on each of the testinput files (in the testdata directory) in turn, +and compares the output with the contents of the corresponding testoutput file. +A file called testtry is used to hold the output from pcretest. To run pcretest +on just one of the test files, give its number as an argument to RunTest, for +example: + + RunTest 2 + +The first file can also be fed directly into the perltest script to check that +Perl gives the same results. The only difference you should see is in the first +few lines, where the Perl version is given instead of the PCRE version. + +The second set of tests check pcre_fullinfo(), pcre_info(), pcre_study(), +pcre_copy_substring(), pcre_get_substring(), pcre_get_substring_list(), error +detection, and run-time flags that are specific to PCRE, as well as the POSIX +wrapper API. It also uses the debugging flag to check some of the internals of +pcre_compile(). + +If you build PCRE with a locale setting that is not the standard C locale, the +character tables may be different (see next paragraph). In some cases, this may +cause failures in the second set of tests. For example, in a locale where the +isprint() function yields TRUE for characters in the range 128-255, the use of +[:isascii:] inside a character class defines a different set of characters, and +this shows up in this test as a difference in the compiled code, which is being +listed for checking. Where the comparison test output contains [\x00-\x7f] the +test will contain [\x00-\xff], and similarly in some other cases. This is not a +bug in PCRE. + +The third set of tests checks pcre_maketables(), the facility for building a +set of character tables for a specific locale and using them instead of the +default tables. The tests make use of the "fr" (French) locale. Before running +the test, the script checks for the presence of this locale by running the +"locale" command. If that command fails, or if it doesn't include "fr" in the +list of available locales, the third test cannot be run, and a comment is +output to say why. If running this test produces instances of the error + + ** Failed to set locale "fr" + +in the comparison output, it means that locale is not available on your system, +despite being listed by "locale". This does not mean that PCRE is broken. + +The fourth test checks the UTF-8 support. It is not run automatically unless +PCRE is built with UTF-8 support. To do this you must set --enable-utf8 when +running "configure". This file can be also fed directly to the perltest script, +provided you are running Perl 5.8 or higher. (For Perl 5.6, a small patch, +commented in the script, can be be used.) + +The fifth and final file tests error handling with UTF-8 encoding, and internal +UTF-8 features of PCRE that are not relevant to Perl. + + +Character tables +---------------- + +PCRE uses four tables for manipulating and identifying characters. The final +argument of the pcre_compile() function is a pointer to a block of memory +containing the concatenated tables. A call to pcre_maketables() can be used to +generate a set of tables in the current locale. If the final argument for +pcre_compile() is passed as NULL, a set of default tables that is built into +the binary is used. + +The source file called chartables.c contains the default set of tables. This is +not supplied in the distribution, but is built by the program dftables +(compiled from dftables.c), which uses the ANSI C character handling functions +such as isalnum(), isalpha(), isupper(), islower(), etc. to build the table +sources. This means that the default C locale which is set for your system will +control the contents of these default tables. You can change the default tables +by editing chartables.c and then re-building PCRE. If you do this, you should +probably also edit Makefile to ensure that the file doesn't ever get +re-generated. + +The first two 256-byte tables provide lower casing and case flipping functions, +respectively. The next table consists of three 32-byte bit maps which identify +digits, "word" characters, and white space, respectively. These are used when +building 32-byte bit maps that represent character classes. + +The final 256-byte table has bits indicating various character types, as +follows: + + 1 white space character + 2 letter + 4 decimal digit + 8 hexadecimal digit + 16 alphanumeric or '_' + 128 regular expression metacharacter or binary zero + +You should not alter the set of characters that contain the 128 bit, as that +will cause PCRE to malfunction. + + +Manifest +-------- + +The distribution should contain the following files: + +(A) The actual source files of the PCRE library functions and their + headers: + + dftables.c auxiliary program for building chartables.c + get.c ) + maketables.c ) + study.c ) source of + pcre.c ) the functions + pcreposix.c ) + printint.c ) + pcre.in "source" for the header for the external API; pcre.h + is built from this by "configure" + pcreposix.h header for the external POSIX wrapper API + internal.h header for internal use + config.in template for config.h, which is built by configure + +(B) Auxiliary files: + + AUTHORS information about the author of PCRE + ChangeLog log of changes to the code + INSTALL generic installation instructions + LICENCE conditions for the use of PCRE + COPYING the same, using GNU's standard name + Makefile.in template for Unix Makefile, which is built by configure + NEWS important changes in this release + NON-UNIX-USE notes on building PCRE on non-Unix systems + README this file + RunTest.in template for a Unix shell script for running tests + config.guess ) files used by libtool, + config.sub ) used only when building a shared library + configure a configuring shell script (built by autoconf) + configure.in the autoconf input used to build configure + doc/Tech.Notes notes on the encoding + doc/*.3 man page sources for the PCRE functions + doc/*.1 man page sources for pcregrep and pcretest + doc/html/* HTML documentation + doc/pcre.txt plain text version of the man pages + doc/pcretest.txt plain text documentation of test program + doc/perltest.txt plain text documentation of Perl test program + install-sh a shell script for installing files + ltmain.sh file used to build a libtool script + pcretest.c comprehensive test program + pcredemo.c simple demonstration of coding calls to PCRE + perltest Perl test program + pcregrep.c source of a grep utility that uses PCRE + pcre-config.in source of script which retains PCRE information + testdata/testinput1 test data, compatible with Perl + testdata/testinput2 test data for error messages and non-Perl things + testdata/testinput3 test data for locale-specific tests + testdata/testinput4 test data for UTF-8 tests compatible with Perl + testdata/testinput5 test data for other UTF-8 tests + testdata/testoutput1 test results corresponding to testinput1 + testdata/testoutput2 test results corresponding to testinput2 + testdata/testoutput3 test results corresponding to testinput3 + testdata/testoutput4 test results corresponding to testinput4 + testdata/testoutput5 test results corresponding to testinput5 + +(C) Auxiliary files for Win32 DLL + + dll.mk + pcre.def + +(D) Auxiliary file for VPASCAL + + makevp.bat + +Philip Hazel +February 2003 diff --git a/lc-continuity/mk4/continuity/pcre/RunTest.in b/lc-continuity/mk4/continuity/pcre/RunTest.in new file mode 100644 index 0000000000000000000000000000000000000000..dd5a02fb604f1389f4503b31660b5da377cd1f4b --- /dev/null +++ b/lc-continuity/mk4/continuity/pcre/RunTest.in @@ -0,0 +1,135 @@ +#! /bin/sh + +# This file is generated by configure from RunTest.in. Make any changes +# to that file. + +# Run PCRE tests + +cf=diff +testdata=@top_srcdir@/testdata + +# Select which tests to run; if no selection, run all + +do1=no +do2=no +do3=no +do4=no +do5=no + +while [ $# -gt 0 ] ; do + case $1 in + 1) do1=yes;; + 2) do2=yes;; + 3) do3=yes;; + 4) do4=yes;; + 5) do5=yes;; + *) echo "Unknown test number $1"; exit 1;; + esac + shift +done + +if [ "@UTF8@" = "" ] ; then + if [ $do4 = yes ] ; then + echo "Can't run test 4 because UFT8 support is not configured" + exit 1 + fi + if [ $do5 = yes ] ; then + echo "Can't run test 5 because UFT8 support is not configured" + exit 1 + fi +fi + +if [ $do1 = no -a $do2 = no -a $do3 = no -a $do4 = no -a\ + $do5 = no ] ; then + do1=yes + do2=yes + do3=yes + if [ "@UTF8@" != "" ] ; then do4=yes; fi + if [ "@UTF8@" != "" ] ; then do5=yes; fi +fi + +# Primary test, Perl-compatible + +if [ $do1 = yes ] ; then + echo "Testing main functionality (Perl compatible)" + ./pcretest $testdata/testinput1 testtry + if [ $? = 0 ] ; then + $cf testtry $testdata/testoutput1 + if [ $? != 0 ] ; then exit 1; fi + echo " " + else exit 1 + fi +fi + +# PCRE tests that are not Perl-compatible - API & error tests, mostly + +if [ $do2 = yes ] ; then + echo "Testing API and error handling (not Perl compatible)" + ./pcretest -i $testdata/testinput2 testtry + if [ $? = 0 ] ; then + $cf testtry $testdata/testoutput2 + if [ $? != 0 ] ; then exit 1; fi + else exit 1 + fi +fi + +if [ $do1 = yes -a $do2 = yes ] ; then + echo " " + echo "The two main tests ran OK" + echo " " +fi + +# Locale-specific tests, provided the "fr" locale is available + +if [ $do3 = yes ] ; then + locale -a | grep '^fr$' >/dev/null + if [ $? -eq 0 ] ; then + echo "Testing locale-specific features (using 'fr' locale)" + ./pcretest $testdata/testinput3 testtry + if [ $? = 0 ] ; then + $cf testtry $testdata/testoutput3 + if [ $? != 0 ] ; then + echo " " + echo "Locale test did not run entirely successfully." + echo "This usually means that there is a problem with the locale" + echo "settings rather than a bug in PCRE." + else + echo "Locale test ran OK" + fi + echo " " + else exit 1 + fi + else + echo "Cannot test locale-specific features - 'fr' locale not found," + echo "or the \"locale\" command is not available to check for it." + echo " " + fi +fi + +# Additional tests for UTF8 support + +if [ $do4 = yes ] ; then + echo "Testing UTF-8 support (Perl compatible)" + ./pcretest $testdata/testinput4 testtry + if [ $? = 0 ] ; then + $cf testtry $testdata/testoutput4 + if [ $? != 0 ] ; then exit 1; fi + else exit 1 + fi + echo "UTF8 test ran OK" + echo " " +fi + +if [ $do5 = yes ] ; then + echo "Testing API and internals for UTF-8 support (not Perl compatible)" + ./pcretest $testdata/testinput5 testtry + if [ $? = 0 ] ; then + $cf testtry $testdata/testoutput5 + if [ $? != 0 ] ; then exit 1; fi + else exit 1 + fi + echo "UTF8 internals test ran OK" + echo " " +fi + +# End diff --git a/lc-continuity/mk4/continuity/pcre/config.guess b/lc-continuity/mk4/continuity/pcre/config.guess new file mode 100644 index 0000000000000000000000000000000000000000..9b1384be4b12624beff8bf1a08b3eec9b0b7b5fe --- /dev/null +++ b/lc-continuity/mk4/continuity/pcre/config.guess @@ -0,0 +1,1400 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002 Free Software Foundation, Inc. + +timestamp='2002-11-30' + +# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 to . Submit a context +# diff and a properly formatted 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. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit build system type. + +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 +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 0 ;; + --version | -v ) + echo "$version" ; exit 0 ;; + --help | --h* | -h ) + echo "$usage"; exit 0 ;; + -- ) # 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' 1 2 15 + +# 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. + +# This shell variable is my proudest work .. or something. --bje + +set_cc_for_build='tmpdir=${TMPDIR-/tmp}/config-guess-$$ ; +(old=`umask` && umask 077 && mkdir $tmpdir && umask $old && unset old) + || (echo "$me: cannot create $tmpdir" >&2 && exit 1) ; +dummy=$tmpdir/dummy ; +files="$dummy.c $dummy.o $dummy.rel $dummy" ; +trap '"'"'rm -f $files; rmdir $tmpdir; exit 1'"'"' 1 2 15 ; +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 ; + rm -f $files ; + 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 ; +unset files' + +# 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 ;; + *) 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 __ELF__ >/dev/null + 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 0 ;; + amiga:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + arc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + hp300:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mac68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + macppc:OpenBSD:*:*) + echo powerpc-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme88k:OpenBSD:*:*) + echo m88k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvmeppc:OpenBSD:*:*) + echo powerpc-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + pmax:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sgi:OpenBSD:*:*) + echo mipseb-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sun3:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + wgrisc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + *:OpenBSD:*:*) + echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + alpha:OSF1:*:*) + if test $UNAME_RELEASE = "V4.0"; then + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + fi + # 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. + eval $set_cc_for_build + cat <$dummy.s + .data +\$Lformat: + .byte 37,100,45,37,120,10,0 # "%d-%x\n" + + .text + .globl main + .align 4 + .ent main +main: + .frame \$30,16,\$26,0 + ldgp \$29,0(\$27) + .prologue 1 + .long 0x47e03d80 # implver \$0 + lda \$2,-1 + .long 0x47e20c21 # amask \$2,\$1 + lda \$16,\$Lformat + mov \$0,\$17 + not \$1,\$18 + jsr \$26,printf + ldgp \$29,0(\$26) + mov 0,\$16 + jsr \$26,exit + .end main +EOF + $CC_FOR_BUILD -o $dummy $dummy.s 2>/dev/null + if test "$?" = 0 ; then + case `$dummy` in + 0-0) + UNAME_MACHINE="alpha" + ;; + 1-0) + UNAME_MACHINE="alphaev5" + ;; + 1-1) + UNAME_MACHINE="alphaev56" + ;; + 1-101) + UNAME_MACHINE="alphapca56" + ;; + 2-303) + UNAME_MACHINE="alphaev6" + ;; + 2-307) + UNAME_MACHINE="alphaev67" + ;; + 2-1307) + UNAME_MACHINE="alphaev68" + ;; + 3-1307) + UNAME_MACHINE="alphaev7" + ;; + esac + fi + rm -f $dummy.s $dummy && rmdir $tmpdir + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit 0 ;; + 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 0 ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit 0 ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit 0;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit 0 ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit 0 ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit 0 ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit 0;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit 0;; + 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 0 ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit 0 ;; + DRS?6000:UNIX_SV:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7 && exit 0 ;; + esac ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + i86pc:SunOS:5.*:*) + echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + 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 0 ;; + 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 0 ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit 0 ;; + 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 0 ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit 0 ;; + # 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 0 ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit 0 ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit 0 ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit 0 ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit 0 ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit 0 ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit 0 ;; + 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 \ + && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ + && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0 + rm -f $dummy.c $dummy && rmdir $tmpdir + echo mips-mips-riscos${UNAME_RELEASE} + exit 0 ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit 0 ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit 0 ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit 0 ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit 0 ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit 0 ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit 0 ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit 0 ;; + 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 0 ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit 0 ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit 0 ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit 0 ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit 0 ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit 0 ;; + ????????: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 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit 0 ;; + 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 0 ;; + *: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 + $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0 + rm -f $dummy.c $dummy && rmdir $tmpdir + echo rs6000-ibm-aix3.2.5 + 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 0 ;; + *:AIX:*:[45]) + 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 0 ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit 0 ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit 0 ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit 0 ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit 0 ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit 0 ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit 0 ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit 0 ;; + 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` + if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi + rm -f $dummy.c $dummy && rmdir $tmpdir + fi ;; + esac + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit 0 ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit 0 ;; + 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 && $dummy && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0 + rm -f $dummy.c $dummy && rmdir $tmpdir + echo unknown-hitachi-hiuxwe2 + exit 0 ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit 0 ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit 0 ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit 0 ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit 0 ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit 0 ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit 0 ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit 0 ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit 0 ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit 0 ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit 0 ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit 0 ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + 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 0 ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*T3D:*:*:*) + echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + 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 0 ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit 0 ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:FreeBSD:*:*) + # Determine whether the default compiler uses glibc. + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + #if __GLIBC__ >= 2 + LIBC=gnu + #else + LIBC= + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` + rm -f $dummy.c && rmdir $tmpdir + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC} + exit 0 ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit 0 ;; + i*:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit 0 ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit 0 ;; + x86:Interix*:3*) + echo i586-pc-interix3 + exit 0 ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit 0 ;; + 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 0 ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit 0 ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit 0 ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + *:GNU:*:*) + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit 0 ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit 0 ;; + arm*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + mips:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips + #undef mipsel + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mipsel + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` + rm -f $dummy.c && rmdir $tmpdir + test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0 + ;; + mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips64 + #undef mips64el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mips64el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips64 + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` + rm -f $dummy.c && rmdir $tmpdir + test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0 + ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit 0 ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit 0 ;; + 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 ld.so.1 >/dev/null + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit 0 ;; + 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 0 ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit 0 ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit 0 ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit 0 ;; + i*86:Linux:*:*) + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + # Set LC_ALL=C to ensure ld outputs messages in English. + ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ + | sed -ne '/supported targets:/!d + s/[ ][ ]*/ /g + s/.*supported targets: *// + s/ .*// + p'` + case "$ld_supported_targets" in + elf32-i386) + TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" + ;; + a.out-i386-linux) + echo "${UNAME_MACHINE}-pc-linux-gnuaout" + exit 0 ;; + coff-i386) + echo "${UNAME_MACHINE}-pc-linux-gnucoff" + exit 0 ;; + "") + # Either a pre-BFD a.out linker (linux-gnuoldld) or + # one that does not give us useful --help. + echo "${UNAME_MACHINE}-pc-linux-gnuoldld" + exit 0 ;; + esac + # Determine whether the default compiler is a.out or elf + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + #ifdef __ELF__ + # ifdef __GLIBC__ + # if __GLIBC__ >= 2 + LIBC=gnu + # else + LIBC=gnulibc1 + # endif + # else + LIBC=gnulibc1 + # endif + #else + #ifdef __INTEL_COMPILER + LIBC=gnu + #else + LIBC=gnuaout + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` + rm -f $dummy.c && rmdir $tmpdir + test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0 + test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 + ;; + 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 0 ;; + 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 0 ;; + 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 0 ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit 0 ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit 0 ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit 0 ;; + 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 0 ;; + i*86:*:5:[78]*) + 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 0 ;; + 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 0 ;; + 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 i386. + echo i386-pc-msdosdjgpp + exit 0 ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit 0 ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit 0 ;; + 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 0 ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit 0 ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit 0 ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit 0 ;; + M68*:*:R3V[567]*:*) + test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; + 3[34]??:*: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) + 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 0 + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4 && exit 0 ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit 0 ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit 0 ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + *: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 0 ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit 0 ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit 0 ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit 0 ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit 0 ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit 0 ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit 0 ;; + 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 0 ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit 0 ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit 0 ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit 0 ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit 0 ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit 0 ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit 0 ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + *:Darwin:*:*) + echo `uname -p`-apple-darwin${UNAME_RELEASE} + exit 0 ;; + *: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 0 ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit 0 ;; + NSR-[DGKLNPTVW]:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit 0 ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit 0 ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit 0 ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit 0 ;; + *: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 0 ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit 0 ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit 0 ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit 0 ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit 0 ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit 0 ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit 0 ;; +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"); 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 && $dummy && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0 +rm -f $dummy.c $dummy && rmdir $tmpdir + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } + +# 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 0 ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + c34*) + echo c34-convex-bsd + exit 0 ;; + c38*) + echo c38-convex-bsd + exit 0 ;; + c4*) + echo c4-convex-bsd + exit 0 ;; + 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: diff --git a/lc-continuity/mk4/continuity/pcre/config.in b/lc-continuity/mk4/continuity/pcre/config.in new file mode 100644 index 0000000000000000000000000000000000000000..62a594e5f335b8b6d2df8a97966875a3db6717ce --- /dev/null +++ b/lc-continuity/mk4/continuity/pcre/config.in @@ -0,0 +1,70 @@ + +/* On Unix systems config.in is converted by configure into config.h. PCRE is +written in Standard C, but there are a few non-standard things it can cope +with, allowing it to run on SunOS4 and other "close to standard" systems. + +On a non-Unix system you should just copy this file into config.h, and set up +the macros the way you need them. You should normally change the definitions of +HAVE_STRERROR and HAVE_MEMMOVE to 1. Unfortunately, because of the way autoconf +works, these cannot be made the defaults. If your system has bcopy() and not +memmove(), change the definition of HAVE_BCOPY instead of HAVE_MEMMOVE. If your +system has neither bcopy() nor memmove(), leave them both as 0; an emulation +function will be used. */ + +/* Define to empty if the keyword does not work. */ + +#undef const + +/* Define to `unsigned' if doesn't define size_t. */ + +#undef size_t + +/* The following two definitions are mainly for the benefit of SunOS4, which +doesn't have the strerror() or memmove() functions that should be present in +all Standard C libraries. The macros HAVE_STRERROR and HAVE_MEMMOVE should +normally be defined with the value 1 for other systems, but unfortunately we +can't make this the default because "configure" files generated by autoconf +will only change 0 to 1; they won't change 1 to 0 if the functions are not +found. */ + +#define HAVE_STRERROR 0 +#define HAVE_MEMMOVE 0 + +/* There are some non-Unix systems that don't even have bcopy(). If this macro +is false, an emulation is used. If HAVE_MEMMOVE is set to 1, the value of +HAVE_BCOPY is not relevant. */ + +#define HAVE_BCOPY 0 + +/* The value of NEWLINE determines the newline character. The default is to +leave it up to the compiler, but some sites want to force a particular value. +On Unix systems, "configure" can be used to override this default. */ + +#ifndef NEWLINE +#define NEWLINE '\n' +#endif + +/* The value of LINK_SIZE determines the number of bytes used to store +links as offsets within the compiled regex. The default is 2, which allows for +compiled patterns up to 64K long. This covers the vast majority of cases. +However, PCRE can also be compiled to use 3 or 4 bytes instead. This allows for +longer patterns in extreme cases. On Unix systems, "configure" can be used to +override this default. */ + +#ifndef LINK_SIZE +#define LINK_SIZE 2 +#endif + +/* The value of MATCH_LIMIT determines the default number of times the match() +function can be called during a single execution of pcre_exec(). (There is a +runtime method of setting a different limit.) The limit exists in order to +catch runaway regular expressions that take for ever to determine that they do +not match. The default is set very large so that it does not accidentally catch +legitimate cases. On Unix systems, "configure" can be used to override this +default default. */ + +#ifndef MATCH_LIMIT +#define MATCH_LIMIT 10000000 +#endif + +/* End */ diff --git a/lc-continuity/mk4/continuity/pcre/config.sub b/lc-continuity/mk4/continuity/pcre/config.sub new file mode 100644 index 0000000000000000000000000000000000000000..f0675aa6b781c1f3557e5fc2dcb319becfddd60c --- /dev/null +++ b/lc-continuity/mk4/continuity/pcre/config.sub @@ -0,0 +1,1469 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002 Free Software Foundation, Inc. + +timestamp='2002-11-30' + +# 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., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, 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 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. + +# 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 +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 0 ;; + --version | -v ) + echo "$version" ; exit 0 ;; + --help | --h* | -h ) + echo "$usage"; exit 0 ;; + -- ) # 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 0;; + + * ) + 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* | freebsd*-gnu* | netbsd*-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) + os= + basic_machine=$1 + ;; + -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 + ;; + -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/'` + ;; + -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] \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ + | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | ip2k \ + | m32r | m68000 | m68k | m88k | mcore \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64vr | mips64vrel \ + | mips64orion | mips64orionel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mipsisa32 | mipsisa32el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | ns16k | ns32k \ + | openrisc | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | sh | sh[1234] | sh3e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \ + | strongarm \ + | tahoe | thumb | tic80 | tron \ + | v850 | v850e \ + | we32k \ + | x86 | xscale | xstormy16 | xtensa \ + | z8k) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + + # 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-* \ + | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* \ + | clipper-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* \ + | m32r-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | mcore-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39 | mipstx39el \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* \ + | sh-* | sh[1234]-* | sh3e-* | sh[34]eb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \ + | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* | tic30-* | tic4x-* | tic54x-* | tic80-* | tron-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \ + | xtensa-* \ + | ymp-* \ + | z8k-*) + ;; + # 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 + ;; + 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 + ;; + 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 + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + 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 + ;; + crds | unos) + basic_machine=m68k-crds + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + 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 + ;; + 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 + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + 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 + ;; + mmix*) + basic_machine=mmix-knuth + os=-mmixware + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + 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 + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + or32 | or32-*) + basic_machine=or32-unknown + os=-coff + ;; + 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 + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2) + basic_machine=i686-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-*) + basic_machine=i686-`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 + ;; + 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 + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + 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 + ;; + t3d) + basic_machine=alpha-cray + os=-unicos + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tic4x | c4x*) + basic_machine=tic4x-unknown + os=-coff + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + 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 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-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 + ;; + 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 + ;; + sh3 | sh4 | sh3eb | sh4eb | sh[1234]le | sh3ele) + basic_machine=sh-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparc | sparcv9 | sparcv9b) + 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. + -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* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ + | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -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*) + # 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* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -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 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -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 + ;; + -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 + ;; + -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 + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + # 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 + ;; + 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 + ;; + *-ibm) + os=-aix + ;; + *-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 + ;; + -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 + ;; + -ptx*) + vendor=sequent + ;; + -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 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/lc-continuity/mk4/continuity/pcre/configure b/lc-continuity/mk4/continuity/pcre/configure new file mode 100755 index 0000000000000000000000000000000000000000..51ac584a56504d2b3a9569316170638d126c2f74 --- /dev/null +++ b/lc-continuity/mk4/continuity/pcre/configure @@ -0,0 +1,8903 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.57. +# +# Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi + +# Support unset when possible. +if (FOO=FOO; unset FOO) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -n "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; 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 + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# 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 + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + 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 + + ;; + 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 + { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2 + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # 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 sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="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="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + + +# Find the correct PATH separator. Usually this is `:', but +# DJGPP uses `;' like DOS. +if test "X${PATH_SEPARATOR+set}" != Xset; then + UNAME=${UNAME-`uname 2>/dev/null`} + case X$UNAME in + *-DOS) lt_cv_sys_path_separator=';' ;; + *) lt_cv_sys_path_separator=':' ;; + esac +fi + + +# Check that we are running under the correct shell. +SHELL=${CONFIG_SHELL-/bin/sh} + +case X$ECHO in +X*--fallback-echo) + # Remove one level of quotation (which was required for Make). + ECHO=`echo "$ECHO" | sed 's,\\\\\$\\$0,'$0','` + ;; +esac + +echo=${ECHO-echo} +if test "X$1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X$1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then + # Yippee, $echo works! + : +else + # Restart under the correct shell. + exec $SHELL "$0" --no-reexec ${1+"$@"} +fi + +if test "X$1" = X--fallback-echo; then + # used as fallback echo + shift + cat </dev/null && + echo_test_string="`eval $cmd`" && + (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null + then + break + fi + done +fi + +if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + : +else + # The Solaris, AIX, and Digital Unix default echo programs unquote + # backslashes. This makes it impossible to quote backslashes using + # echo "$something" | sed 's/\\/\\\\/g' + # + # So, first we look for a working echo in the user's PATH. + + IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" + for dir in $PATH /usr/ucb; do + if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && + test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + echo="$dir/echo" + break + fi + done + IFS="$save_ifs" + + if test "X$echo" = Xecho; then + # We didn't find a better echo, so look for alternatives. + if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # This shell has a builtin print -r that does the trick. + echo='print -r' + elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && + test "X$CONFIG_SHELL" != X/bin/ksh; then + # If we have ksh, try running configure again with it. + ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} + export ORIGINAL_CONFIG_SHELL + CONFIG_SHELL=/bin/ksh + export CONFIG_SHELL + exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"} + else + # Try using printf. + echo='printf %s\n' + if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # Cool, printf works + : + elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL + export CONFIG_SHELL + SHELL="$CONFIG_SHELL" + export SHELL + echo="$CONFIG_SHELL $0 --fallback-echo" + elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + echo="$CONFIG_SHELL $0 --fallback-echo" + else + # maybe with a smaller string... + prev=: + + for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do + if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null + then + break + fi + prev="$cmd" + done + + if test "$prev" != 'sed 50q "$0"'; then + echo_test_string=`eval $prev` + export echo_test_string + exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"} + else + # Oops. We lost completely, so just stick with echo. + echo=echo + fi + fi + fi + fi +fi +fi + +# Copy echo and quote the copy suitably for passing to libtool from +# the Makefile, instead of quoting the original, which is used later. +ECHO=$echo +if test "X$ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then + ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo" +fi + + + +# Name of the host. +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +exec 6>&1 + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_config_libobj_dir=. +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} + +# Maximum number of lines to put in a shell here document. +# This variable seems obsolete. It should probably be removed, and +# only ac_max_sed_lines should be used. +: ${ac_max_here_lines=38} + +# Identity of this package. +PACKAGE_NAME= +PACKAGE_TARNAME= +PACKAGE_VERSION= +PACKAGE_STRING= +PACKAGE_BUGREPORT= + +ac_unique_file="dftables.c" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#if HAVE_SYS_TYPES_H +# include +#endif +#if HAVE_SYS_STAT_H +# include +#endif +#if STDC_HEADERS +# include +# include +#else +# if HAVE_STDLIB_H +# include +# endif +#endif +#if HAVE_STRING_H +# if !STDC_HEADERS && HAVE_MEMORY_H +# include +# endif +# include +#endif +#if HAVE_STRINGS_H +# include +#endif +#if HAVE_INTTYPES_H +# include +#else +# if HAVE_STDINT_H +# include +# endif +#endif +#if HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA build build_cpu build_vendor build_os host host_cpu host_vendor host_os LN_S ECHO RANLIB ac_ct_RANLIB STRIP ac_ct_STRIP CPP EGREP LIBTOOL BUILD_EXEEXT BUILD_OBJEXT CC_FOR_BUILD CFLAGS_FOR_BUILD HAVE_MEMMOVE HAVE_STRERROR LINK_SIZE MATCH_LIMIT NEWLINE PCRE_MAJOR PCRE_MINOR PCRE_DATE PCRE_VERSION PCRE_LIB_VERSION PCRE_POSIXLIB_VERSION POSIX_MALLOC_THRESHOLD UTF8 WIN_PREFIX ON_WINDOWS NOT_ON_WINDOWS POSIX_OBJ POSIX_LOBJ POSIX_LIB LIBOBJS LTLIBOBJS' +ac_subst_files='' + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +# 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. +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +ac_prev= +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 + + ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_option in + + -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 | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + eval "enable_$ac_feature=no" ;; + + -enable-* | --enable-*) + ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "enable_$ac_feature='$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 ;; + + -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 ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + 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 ;; + + -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_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package| sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "with_$ac_package='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package | sed 's/-/_/g'` + eval "with_$ac_package=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 ;; + + -*) { echo "$as_me: error: unrecognized option: $ac_option +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 + { (exit 1); exit 1; }; } + ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` + eval "$ac_envvar='$ac_optarg'" + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + 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'` + { echo "$as_me: error: missing argument to $ac_option" >&2 + { (exit 1); exit 1; }; } +fi + +# Be sure to have absolute paths. +for ac_var in exec_prefix prefix +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* | NONE | '' ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# Be sure to have absolute paths. +for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ + localstatedir libdir includedir oldincludedir infodir mandir +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +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 + echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 + 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 + + +# 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 its parent. + ac_confdir=`(dirname "$0") 2>/dev/null || +$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$0" : 'X\(//\)[^/]' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$0" | + 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 + if test "$ac_srcdir_defaulted" = yes; then + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 + { (exit 1); exit 1; }; } + else + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 + { (exit 1); exit 1; }; } + fi +fi +(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || + { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 + { (exit 1); exit 1; }; } +srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` +ac_env_build_alias_set=${build_alias+set} +ac_env_build_alias_value=$build_alias +ac_cv_env_build_alias_set=${build_alias+set} +ac_cv_env_build_alias_value=$build_alias +ac_env_host_alias_set=${host_alias+set} +ac_env_host_alias_value=$host_alias +ac_cv_env_host_alias_set=${host_alias+set} +ac_cv_env_host_alias_value=$host_alias +ac_env_target_alias_set=${target_alias+set} +ac_env_target_alias_value=$target_alias +ac_cv_env_target_alias_set=${target_alias+set} +ac_cv_env_target_alias_value=$target_alias +ac_env_CC_set=${CC+set} +ac_env_CC_value=$CC +ac_cv_env_CC_set=${CC+set} +ac_cv_env_CC_value=$CC +ac_env_CFLAGS_set=${CFLAGS+set} +ac_env_CFLAGS_value=$CFLAGS +ac_cv_env_CFLAGS_set=${CFLAGS+set} +ac_cv_env_CFLAGS_value=$CFLAGS +ac_env_LDFLAGS_set=${LDFLAGS+set} +ac_env_LDFLAGS_value=$LDFLAGS +ac_cv_env_LDFLAGS_set=${LDFLAGS+set} +ac_cv_env_LDFLAGS_value=$LDFLAGS +ac_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_env_CPPFLAGS_value=$CPPFLAGS +ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_cv_env_CPPFLAGS_value=$CPPFLAGS +ac_env_CPP_set=${CPP+set} +ac_env_CPP_value=$CPP +ac_cv_env_CPP_set=${CPP+set} +ac_cv_env_CPP_value=$CPP + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # The list generated by autoconf has been trimmed to remove many + # options that are totally irrelevant to PCRE (e.g. relating to X), + # or are not supported by its Makefile. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures this package 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 \`..'] + +_ACEOF + + cat <<_ACEOF +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] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --mandir=DIR man documentation [PREFIX/man] +_ACEOF + + cat <<\_ACEOF + +_ACEOF +fi + +if test -n "$ac_init_help"; then + + cat <<\_ACEOF + +Optional Features: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-shared build shared libraries default=yes + --enable-static build static libraries default=yes + --enable-fast-install optimize for fast installation default=yes + --disable-libtool-lock avoid locking (might break parallel builds) + --enable-utf8 enable UTF8 support + --enable-newline-is-cr use CR as the newline character + --enable-newline-is-lf use LF as the newline character + +Optional Packages: + --with-gnu-ld assume the C compiler uses GNU ld default=no + --with-pic try to use only PIC/non-PIC objects default=use both + --with-posix-malloc-threshold=5 threshold for POSIX malloc usage + --with-link-size=2 internal link size (2, 3, or 4 allowed) + --with-match-limit=10000000 default limit on internal looping) + +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 + CPPFLAGS 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. + +_ACEOF +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + ac_popdir=`pwd` + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d $ac_dir || continue + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac +# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be +# absolute. +ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd` +ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd` +ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd` +ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` + + cd $ac_dir + # Check for guested configure; otherwise get Cygnus style 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 + elif test -f $ac_srcdir/configure.ac || + test -f $ac_srcdir/configure.in; then + echo + $ac_configure --help + else + echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi + cd $ac_popdir + done +fi + +test -n "$ac_init_help" && exit 0 +if $ac_init_version; then + cat <<\_ACEOF + +Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002 +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 0 +fi +exec 5>config.log +cat >&5 <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by $as_me, which was +generated by GNU Autoconf 2.57. Invocation command line was + + $ $0 $@ + +_ACEOF +{ +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` +hostinfo = `(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=. + echo "PATH: $as_dir" +done + +} >&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_sep= +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=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; + 2) + ac_configure_args1="$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 + ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" + # Get rid of the leading space. + ac_sep=" " + ;; + esac + done +done +$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } +$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export 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: Be sure not to use single quotes in there, as some shells, +# such as our DU 5.0 friend, will then `close' the trap. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + cat <<\_ASBOX +## ---------------- ## +## Cache variables. ## +## ---------------- ## +_ASBOX + echo + # The following way of writing the cache mishandles newlines in values, +{ + (set) 2>&1 | + case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in + *ac_space=\ *) + sed -n \ + "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" + ;; + *) + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} + echo + + cat <<\_ASBOX +## ----------------- ## +## Output variables. ## +## ----------------- ## +_ASBOX + echo + for ac_var in $ac_subst_vars + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + + if test -n "$ac_subst_files"; then + cat <<\_ASBOX +## ------------- ## +## Output files. ## +## ------------- ## +_ASBOX + echo + for ac_var in $ac_subst_files + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + fi + + if test -s confdefs.h; then + cat <<\_ASBOX +## ----------- ## +## confdefs.h. ## +## ----------- ## +_ASBOX + echo + sed "/^$/d" confdefs.h | sort + echo + fi + test "$ac_signal" != 0 && + echo "$as_me: caught signal $ac_signal" + echo "$as_me: exit $exit_status" + } >&5 + rm -f core core.* *.core && + rm -rf conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status + ' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo >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 + + +# Let the site file select an alternate cache file if it wants to. +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 +echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" + 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. + if test -f "$cache_file"; then + { echo "$as_me:$LINENO: loading cache $cache_file" >&5 +echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . $cache_file;; + *) . ./$cache_file;; + esac + fi +else + { echo "$as_me:$LINENO: creating cache $cache_file" >&5 +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 `(set) 2>&1 | + sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; 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,) + { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 +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 + { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 +echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 +echo "$as_me: former value: $ac_old_val" >&2;} + { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 +echo "$as_me: current value: $ac_new_val" >&2;} + ac_cache_corrupted=: + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=$ac_var=`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. + *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 +echo "$as_me: error: changes in the environment can compromise the build" >&2;} + { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 +echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + + + + + + + + + + + + + + + + + + + + + ac_config_headers="$ac_config_headers config.h:config.in" + + + +PCRE_MAJOR=4 +PCRE_MINOR=3 +PCRE_DATE=21-May-2003 +PCRE_VERSION=${PCRE_MAJOR}.${PCRE_MINOR} + + +POSIX_MALLOC_THRESHOLD=-DPOSIX_MALLOC_THRESHOLD=10 + + +PCRE_LIB_VERSION=0:1:0 +PCRE_POSIXLIB_VERSION=0:0:0 + + +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 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&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_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}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 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&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_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +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 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&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_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&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_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +else + CC="$ac_cv_prog_CC" +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 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&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_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" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +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 + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl + 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 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&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_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&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_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$ac_ct_CC" && break +done + + CC=$ac_ct_CC +fi + +fi + + +test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&5 +echo "$as_me: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + +# Provide some information about the compiler. +echo "$as_me:$LINENO:" \ + "checking for C compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 + (eval $ac_compiler --version &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 + (eval $ac_compiler -v &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 + (eval $ac_compiler -V &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out 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. +echo "$as_me:$LINENO: checking for C compiler default output" >&5 +echo $ECHO_N "checking for C compiler default output... $ECHO_C" >&6 +ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` +if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 + (eval $ac_link_default) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Find the output, starting from the most likely. This scheme is +# not robust to junk in `.', hence go to wildcards (a.*) only as a last +# resort. + +# Be careful to initialize this variable, since it used to be cached. +# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. +ac_cv_exeext= +# b.out is created by i960 compilers. +for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) + ;; + conftest.$ac_ext ) + # This is the source file. + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + # FIXME: I believe we export ac_cv_exeext for Libtool, + # but it would be cool to find out if it's true. Does anybody + # maintain Libtool? --akim. + export ac_cv_exeext + break;; + * ) + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: C compiler cannot create executables +See \`config.log' for more details." >&5 +echo "$as_me: error: C compiler cannot create executables +See \`config.log' for more details." >&2;} + { (exit 77); exit 77; }; } +fi + +ac_exeext=$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_file" >&5 +echo "${ECHO_T}$ac_file" >&6 + +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether the C compiler works" >&5 +echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6 +# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 +# If not cross compiling, check that we can run a simple program. +if test "$cross_compiling" != yes; then + if { ac_try='./$ac_file' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { echo "$as_me:$LINENO: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + fi + fi +fi +echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +rm -f a.out a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 +echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6 +echo "$as_me:$LINENO: result: $cross_compiling" >&5 +echo "${ECHO_T}$cross_compiling" >&6 + +echo "$as_me:$LINENO: checking for suffix of executables" >&5 +echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6 +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; 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 | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + export ac_cv_exeext + break;; + * ) break;; + esac +done +else + { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 +echo "${ECHO_T}$ac_cv_exeext" >&6 + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +echo "$as_me:$LINENO: checking for suffix of object files" >&5 +echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6 +if test "${ac_cv_objext+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 +echo "${ECHO_T}$ac_cv_objext" >&6 +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6 +if test "${ac_cv_c_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_compiler_gnu=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6 +GCC=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +CFLAGS="-g" +echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 +echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_prog_cc_g=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 +echo "${ECHO_T}$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 +echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5 +echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_prog_cc_stdc=no +ac_save_CC=$CC +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include +/* 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; +} +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 +# Don't try gcc -ansi; that turns off useful extensions and +# breaks some systems' header files. +# AIX -qlanglvl=ansi +# Ultrix and OSF/1 -std1 +# HP-UX 10.20 and later -Ae +# HP-UX older versions -Aa -D_HPUX_SOURCE +# SVR4 -Xc -D__EXTENSIONS__ +for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_stdc=$ac_arg +break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.$ac_objext +done +rm -f conftest.$ac_ext conftest.$ac_objext +CC=$ac_save_CC + +fi + +case "x$ac_cv_prog_cc_stdc" in + x|xno) + echo "$as_me:$LINENO: result: none needed" >&5 +echo "${ECHO_T}none needed" >&6 ;; + *) + echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6 + CC="$CC $ac_cv_prog_cc_stdc" ;; +esac + +# Some people use a C++ compiler to compile C. Since we use `exit', +# in C++ we need to declare it. In case someone uses the same compiler +# for both compiling C and C++ we need to have the C++ compiler decide +# the declaration of exit, since it's the most demanding environment. +cat >conftest.$ac_ext <<_ACEOF +#ifndef __cplusplus + choke me +#endif +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + for ac_declaration in \ + ''\ + '#include ' \ + 'extern "C" void std::exit (int) throw (); using std::exit;' \ + 'extern "C" void std::exit (int); using std::exit;' \ + 'extern "C" void exit (int) throw ();' \ + 'extern "C" void exit (int);' \ + 'void exit (int);' +do + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +$ac_declaration +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +continue +fi +rm -f conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.$ac_objext conftest.$ac_ext +done +rm -f conftest* +if test -n "$ac_declaration"; then + echo '#ifdef __cplusplus' >>confdefs.h + echo $ac_declaration >>confdefs.h + echo '#endif' >>confdefs.h +fi + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.$ac_objext conftest.$ac_ext +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_aux_dir= +for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f $ac_dir/shtool; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5 +echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;} + { (exit 1); exit 1; }; } +fi +ac_config_guess="$SHELL $ac_aux_dir/config.guess" +ac_config_sub="$SHELL $ac_aux_dir/config.sub" +ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure. + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 +echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6 +if test -z "$INSTALL"; then +if test "${ac_cv_path_install+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in + ./ | .// | /cC/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + done + done + ;; +esac +done + + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL=$ac_install_sh + fi +fi +echo "$as_me:$LINENO: result: $INSTALL" >&5 +echo "${ECHO_T}$INSTALL" >&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + + +# Check whether --enable-shared or --disable-shared was given. +if test "${enable_shared+set}" = set; then + enableval="$enable_shared" + p=${PACKAGE-default} +case $enableval in +yes) enable_shared=yes ;; +no) enable_shared=no ;; +*) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," + for pkg in $enableval; do + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$ac_save_ifs" + ;; +esac +else + enable_shared=yes +fi; +# Check whether --enable-static or --disable-static was given. +if test "${enable_static+set}" = set; then + enableval="$enable_static" + p=${PACKAGE-default} +case $enableval in +yes) enable_static=yes ;; +no) enable_static=no ;; +*) + enable_static=no + # Look at the argument we got. We use all the common list separators. + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," + for pkg in $enableval; do + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$ac_save_ifs" + ;; +esac +else + enable_static=yes +fi; +# Check whether --enable-fast-install or --disable-fast-install was given. +if test "${enable_fast_install+set}" = set; then + enableval="$enable_fast_install" + p=${PACKAGE-default} +case $enableval in +yes) enable_fast_install=yes ;; +no) enable_fast_install=no ;; +*) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," + for pkg in $enableval; do + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$ac_save_ifs" + ;; +esac +else + enable_fast_install=yes +fi; +# Make sure we can run config.sub. +$ac_config_sub sun4 >/dev/null 2>&1 || + { { echo "$as_me:$LINENO: error: cannot run $ac_config_sub" >&5 +echo "$as_me: error: cannot run $ac_config_sub" >&2;} + { (exit 1); exit 1; }; } + +echo "$as_me:$LINENO: checking build system type" >&5 +echo $ECHO_N "checking build system type... $ECHO_C" >&6 +if test "${ac_cv_build+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_build_alias=$build_alias +test -z "$ac_cv_build_alias" && + ac_cv_build_alias=`$ac_config_guess` +test -z "$ac_cv_build_alias" && + { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5 +echo "$as_me: error: cannot guess build type; you must specify one" >&2;} + { (exit 1); exit 1; }; } +ac_cv_build=`$ac_config_sub $ac_cv_build_alias` || + { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_build_alias failed" >&5 +echo "$as_me: error: $ac_config_sub $ac_cv_build_alias failed" >&2;} + { (exit 1); exit 1; }; } + +fi +echo "$as_me:$LINENO: result: $ac_cv_build" >&5 +echo "${ECHO_T}$ac_cv_build" >&6 +build=$ac_cv_build +build_cpu=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +build_vendor=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +build_os=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` + + +echo "$as_me:$LINENO: checking host system type" >&5 +echo $ECHO_N "checking host system type... $ECHO_C" >&6 +if test "${ac_cv_host+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_host_alias=$host_alias +test -z "$ac_cv_host_alias" && + ac_cv_host_alias=$ac_cv_build_alias +ac_cv_host=`$ac_config_sub $ac_cv_host_alias` || + { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_host_alias failed" >&5 +echo "$as_me: error: $ac_config_sub $ac_cv_host_alias failed" >&2;} + { (exit 1); exit 1; }; } + +fi +echo "$as_me:$LINENO: result: $ac_cv_host" >&5 +echo "${ECHO_T}$ac_cv_host" >&6 +host=$ac_cv_host +host_cpu=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` + + + +# Check whether --with-gnu-ld or --without-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then + withval="$with_gnu_ld" + test "$withval" = no || with_gnu_ld=yes +else + with_gnu_ld=no +fi; +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + echo "$as_me:$LINENO: checking for ld used by GCC" >&5 +echo $ECHO_N "checking for ld used by GCC... $ECHO_C" >&6 + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | [A-Za-z]:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the path of ld + ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + echo "$as_me:$LINENO: checking for GNU ld" >&5 +echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6 +else + echo "$as_me:$LINENO: checking for non-GNU ld" >&5 +echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6 +fi +if test "${lt_cv_path_LD+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -z "$LD"; then + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some GNU ld's only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + if "$lt_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then + test "$with_gnu_ld" != no && break + else + test "$with_gnu_ld" != yes && break + fi + fi + done + IFS="$ac_save_ifs" +else + lt_cv_path_LD="$LD" # Let the user override the test with a path. +fi +fi + +LD="$lt_cv_path_LD" +if test -n "$LD"; then + echo "$as_me:$LINENO: result: $LD" >&5 +echo "${ECHO_T}$LD" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi +test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5 +echo "$as_me: error: no acceptable ld found in \$PATH" >&2;} + { (exit 1); exit 1; }; } +echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5 +echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6 +if test "${lt_cv_prog_gnu_ld+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # I'd rather use --version here, but apparently some GNU ld's only accept -v. +if $LD -v 2>&1 &5; then + lt_cv_prog_gnu_ld=yes +else + lt_cv_prog_gnu_ld=no +fi +fi +echo "$as_me:$LINENO: result: $lt_cv_prog_gnu_ld" >&5 +echo "${ECHO_T}$lt_cv_prog_gnu_ld" >&6 +with_gnu_ld=$lt_cv_prog_gnu_ld + + +echo "$as_me:$LINENO: checking for $LD option to reload object files" >&5 +echo $ECHO_N "checking for $LD option to reload object files... $ECHO_C" >&6 +if test "${lt_cv_ld_reload_flag+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_ld_reload_flag='-r' +fi +echo "$as_me:$LINENO: result: $lt_cv_ld_reload_flag" >&5 +echo "${ECHO_T}$lt_cv_ld_reload_flag" >&6 +reload_flag=$lt_cv_ld_reload_flag +test -n "$reload_flag" && reload_flag=" $reload_flag" + +echo "$as_me:$LINENO: checking for BSD-compatible nm" >&5 +echo $ECHO_N "checking for BSD-compatible nm... $ECHO_C" >&6 +if test "${lt_cv_path_NM+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}" + for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do + test -z "$ac_dir" && ac_dir=. + tmp_nm=$ac_dir/${ac_tool_prefix}nm + if test -f $tmp_nm || test -f $tmp_nm$ac_exeext ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + if ($tmp_nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep '(/dev/null|Invalid file or object type)' >/dev/null; then + lt_cv_path_NM="$tmp_nm -B" + break + elif ($tmp_nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then + lt_cv_path_NM="$tmp_nm -p" + break + else + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + fi + fi + done + IFS="$ac_save_ifs" + test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm +fi +fi + +NM="$lt_cv_path_NM" +echo "$as_me:$LINENO: result: $NM" >&5 +echo "${ECHO_T}$NM" >&6 + +echo "$as_me:$LINENO: checking whether ln -s works" >&5 +echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6 +LN_S=$as_ln_s +if test "$LN_S" = "ln -s"; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +else + echo "$as_me:$LINENO: result: no, using $LN_S" >&5 +echo "${ECHO_T}no, using $LN_S" >&6 +fi + +echo "$as_me:$LINENO: checking how to recognise dependant libraries" >&5 +echo $ECHO_N "checking how to recognise dependant libraries... $ECHO_C" >&6 +if test "${lt_cv_deplibs_check_method+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# `unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# ['file_magic [regex]'] -- check by looking for files in library path +# which responds to the $file_magic_cmd with a given egrep regex. +# If you have `file' or equivalent on your system and you're not sure +# whether `pass_all' will *always* work, you probably want this one. + +case $host_os in +aix4* | aix5*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi4*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin* | mingw* | pw32*) + lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method='file_magic Mach-O dynamically linked shared library' + lt_cv_file_magic_cmd='/usr/bin/file -L' + case "$host_os" in + rhapsody* | darwin1.012) + lt_cv_file_magic_test_file=`echo /System/Library/Frameworks/System.framework/Versions/*/System | head -1` + ;; + *) # Darwin 1.3 on + lt_cv_file_magic_test_file='/usr/lib/libSystem.dylib' + ;; + esac + ;; + +freebsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD)/i[3-9]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20*|hpux11*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + +irix5* | irix6*) + case $host_os in + irix5*) + # this will be overridden with pass_all, but let us keep it just in case + lt_cv_deplibs_check_method="file_magic ELF 32-bit MSB dynamic lib MIPS - version 1" + ;; + *) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + # this will be overridden with pass_all, but let us keep it just in case + lt_cv_deplibs_check_method="file_magic ELF ${libmagic} MSB mips-[1234] dynamic lib MIPS - version 1" + ;; + esac + lt_cv_file_magic_test_file=`echo /lib${libsuff}/libc.so*` + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be Linux ELF. +linux-gnu*) + case $host_cpu in + alpha* | i*86 | powerpc* | sparc* | ia64* ) + lt_cv_deplibs_check_method=pass_all ;; + *) + # glibc up to 2.1.1 does not perform some relocations on ARM + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' ;; + esac + lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so` + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[^/\.]+\.so\.[0-9]+\.[0-9]+$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/\.]+\.so$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +osf3* | osf4* | osf5*) + # this will be overridden with pass_all, but let us keep it just in case + lt_cv_deplibs_check_method='file_magic COFF format alpha shared library' + lt_cv_file_magic_test_file=/shlib/libc.so + lt_cv_deplibs_check_method=pass_all + ;; + +sco3.2v5*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + lt_cv_file_magic_test_file=/lib/libc.so + ;; + +sysv5uw[78]* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + esac + ;; +esac + +fi +echo "$as_me:$LINENO: result: $lt_cv_deplibs_check_method" >&5 +echo "${ECHO_T}$lt_cv_deplibs_check_method" >&6 +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method + + + + + + + + +# Check for command to grab the raw symbol name followed by C symbol from nm. +echo "$as_me:$LINENO: checking command to parse $NM output" >&5 +echo $ECHO_N "checking command to parse $NM output... $ECHO_C" >&6 +if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[BCDEGRST]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Transform the above into a raw symbol and a C symbol. +symxfrm='\1 \2\3 \3' + +# Transform an extracted symbol line into a proper C declaration +lt_cv_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern char \1;/p'" + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[BCDT]' + ;; +cygwin* | mingw* | pw32*) + symcode='[ABCDGISTW]' + ;; +hpux*) # Its linker distinguishes data from code symbols + lt_cv_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern char \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + ;; +irix*) + symcode='[BCDEGRST]' + ;; +solaris* | sysv5*) + symcode='[BDT]' + ;; +sysv4) + symcode='[DFNSTU]' + ;; +esac + +# Handle CRLF in mingw tool chain +opt_cr= +case $host_os in +mingw*) + opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then + symcode='[ABCDGISTW]' +fi + +# Try without a prefix undercore, then with it. +for ac_symprfx in "" "_"; do + + # Write the raw and C identifiers. +lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*\($ac_symprfx\)$sympat$opt_cr$/$symxfrm/p'" + + # Check to see that the pipe works correctly. + pipe_works=no + rm -f conftest* + cat > conftest.$ac_ext <&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Now try to grab the symbols. + nlist=conftest.nm + if { (eval echo "$as_me:$LINENO: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\"") >&5 + (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if egrep ' nm_test_var$' "$nlist" >/dev/null; then + if egrep ' nm_test_func$' "$nlist" >/dev/null; then + cat < conftest.$ac_ext +#ifdef __cplusplus +extern "C" { +#endif + +EOF + # Now generate the symbol file. + eval "$lt_cv_global_symbol_to_cdecl"' < "$nlist" >> conftest.$ac_ext' + + cat <> conftest.$ac_ext +#if defined (__STDC__) && __STDC__ +# define lt_ptr_t void * +#else +# define lt_ptr_t char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + lt_ptr_t address; +} +lt_preloaded_symbols[] = +{ +EOF + sed "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" >> conftest.$ac_ext + cat <<\EOF >> conftest.$ac_ext + {0, (lt_ptr_t) 0} +}; + +#ifdef __cplusplus +} +#endif +EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + save_LIBS="$LIBS" + save_CFLAGS="$CFLAGS" + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$no_builtin_flag" + if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s conftest; then + pipe_works=yes + fi + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" + else + echo "cannot find nm_test_func in $nlist" >&5 + fi + else + echo "cannot find nm_test_var in $nlist" >&5 + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 + fi + else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + fi + rm -f conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done + +fi + +global_symbol_pipe="$lt_cv_sys_global_symbol_pipe" +if test -z "$lt_cv_sys_global_symbol_pipe"; then + global_symbol_to_cdecl= +else + global_symbol_to_cdecl="$lt_cv_global_symbol_to_cdecl" +fi +if test -z "$global_symbol_pipe$global_symbol_to_cdecl"; then + echo "$as_me:$LINENO: result: failed" >&5 +echo "${ECHO_T}failed" >&6 +else + echo "$as_me:$LINENO: result: ok" >&5 +echo "${ECHO_T}ok" >&6 +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 +echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 +echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if test "${ac_cv_prog_CPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&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 >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f 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 +echo "$as_me:$LINENO: result: $CPP" >&5 +echo "${ECHO_T}$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 >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +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 + + +echo "$as_me:$LINENO: checking for egrep" >&5 +echo $ECHO_N "checking for egrep... $ECHO_C" >&6 +if test "${ac_cv_prog_egrep+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if echo a | (grep -E '(a|b)') >/dev/null 2>&1 + then ac_cv_prog_egrep='grep -E' + else ac_cv_prog_egrep='egrep' + fi +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5 +echo "${ECHO_T}$ac_cv_prog_egrep" >&6 + EGREP=$ac_cv_prog_egrep + + +echo "$as_me:$LINENO: checking for ANSI C header files" >&5 +echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 +if test "${ac_cv_header_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_stdc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_header_stdc=no +fi +rm -f 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 >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* 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 >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* 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 >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#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)) + exit(2); + exit (0); +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_header_stdc=no +fi +rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 +echo "${ECHO_T}$ac_cv_header_stdc" >&6 +if test $ac_cv_header_stdc = yes; then + +cat >>confdefs.h <<\_ACEOF +#define STDC_HEADERS 1 +_ACEOF + +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=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_Header=no" +fi +rm -f conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + +for ac_header in dlfcn.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc in + yes:no ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------ ## +## Report this to bug-autoconf@gnu.org. ## +## ------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; + no:yes ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------ ## +## Report this to bug-autoconf@gnu.org. ## +## ------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + + +# Only perform the check for file, if the check method requires it +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + echo "$as_me:$LINENO: checking for ${ac_tool_prefix}file" >&5 +echo $ECHO_N "checking for ${ac_tool_prefix}file... $ECHO_C" >&6 +if test "${lt_cv_path_MAGIC_CMD+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $MAGIC_CMD in + /*) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; + ?:/*) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a dos path. + ;; + *) + ac_save_MAGIC_CMD="$MAGIC_CMD" + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="/usr/bin:$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/${ac_tool_prefix}file; then + lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`" + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + egrep "$file_magic_regex" > /dev/null; then + : + else + cat <&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +EOF + fi ;; + esac + fi + break + fi + done + IFS="$ac_save_ifs" + MAGIC_CMD="$ac_save_MAGIC_CMD" + ;; +esac +fi + +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5 +echo "${ECHO_T}$MAGIC_CMD" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + echo "$as_me:$LINENO: checking for file" >&5 +echo $ECHO_N "checking for file... $ECHO_C" >&6 +if test "${lt_cv_path_MAGIC_CMD+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $MAGIC_CMD in + /*) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; + ?:/*) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a dos path. + ;; + *) + ac_save_MAGIC_CMD="$MAGIC_CMD" + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="/usr/bin:$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/file; then + lt_cv_path_MAGIC_CMD="$ac_dir/file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`" + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + egrep "$file_magic_regex" > /dev/null; then + : + else + cat <&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +EOF + fi ;; + esac + fi + break + fi + done + IFS="$ac_save_ifs" + MAGIC_CMD="$ac_save_MAGIC_CMD" + ;; +esac +fi + +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5 +echo "${ECHO_T}$MAGIC_CMD" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + else + MAGIC_CMD=: + fi +fi + + fi + ;; +esac + +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 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&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_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + echo "$as_me:$LINENO: result: $RANLIB" >&5 +echo "${ECHO_T}$RANLIB" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}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 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&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_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":" +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 +echo "${ECHO_T}$ac_ct_RANLIB" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + RANLIB=$ac_ct_RANLIB +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_STRIP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # 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_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + echo "$as_me:$LINENO: result: $STRIP" >&5 +echo "${ECHO_T}$STRIP" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # 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_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + test -z "$ac_cv_prog_ac_ct_STRIP" && ac_cv_prog_ac_ct_STRIP=":" +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5 +echo "${ECHO_T}$ac_ct_STRIP" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + STRIP=$ac_ct_STRIP +else + STRIP="$ac_cv_prog_STRIP" +fi + + +enable_dlopen=no +enable_win32_dll=no + +# Check whether --enable-libtool-lock or --disable-libtool-lock was given. +if test "${enable_libtool_lock+set}" = set; then + enableval="$enable_libtool_lock" + +fi; +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +*-*-irix6*) + # Find out which ABI we are using. + echo '#line 4012 "configure"' > conftest.$ac_ext + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + echo "$as_me:$LINENO: checking whether the C compiler needs -belf" >&5 +echo $ECHO_N "checking whether the C compiler needs -belf... $ECHO_C" >&6 +if test "${lt_cv_cc_needs_belf+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + + 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 + + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + lt_cv_cc_needs_belf=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +lt_cv_cc_needs_belf=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext + 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 + +fi +echo "$as_me:$LINENO: result: $lt_cv_cc_needs_belf" >&5 +echo "${ECHO_T}$lt_cv_cc_needs_belf" >&6 + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; + + +esac + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='sed -e s/^X//' +sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Constants: +rm="rm -f" + +# Global variables: +default_ofile=libtool +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except M$VC, +# which needs '.lib'). +libext=a +ltmain="$ac_aux_dir/ltmain.sh" +ofile="$default_ofile" +with_gnu_ld="$lt_cv_prog_gnu_ld" +need_locks="$enable_libtool_lock" + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$AR" && AR=ar +test -z "$AR_FLAGS" && AR_FLAGS=cru +test -z "$AS" && AS=as +test -z "$CC" && CC=cc +test -z "$DLLTOOL" && DLLTOOL=dlltool +test -z "$LD" && LD=ld +test -z "$LN_S" && LN_S="ln -s" +test -z "$MAGIC_CMD" && MAGIC_CMD=file +test -z "$NM" && NM=nm +test -z "$OBJDUMP" && OBJDUMP=objdump +test -z "$RANLIB" && RANLIB=: +test -z "$STRIP" && STRIP=: +test -z "$ac_objext" && ac_objext=o + +if test x"$host" != x"$build"; then + ac_tool_prefix=${host_alias}- +else + ac_tool_prefix= +fi + +# Transform linux* to *-*-linux-gnu*, to support old configure scripts. +case $host_os in +linux-gnu*) ;; +linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'` +esac + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" + old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds" +fi + +# Allow CC to be a program name with arguments. +set dummy $CC +compiler="$2" + +## FIXME: this should be a separate macro +## +echo "$as_me:$LINENO: checking for objdir" >&5 +echo $ECHO_N "checking for objdir... $ECHO_C" >&6 +rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + objdir=_libs +fi +rmdir .libs 2>/dev/null +echo "$as_me:$LINENO: result: $objdir" >&5 +echo "${ECHO_T}$objdir" >&6 +## +## END FIXME + + +## FIXME: this should be a separate macro +## + +# Check whether --with-pic or --without-pic was given. +if test "${with_pic+set}" = set; then + withval="$with_pic" + pic_mode="$withval" +else + pic_mode=default +fi; +test -z "$pic_mode" && pic_mode=default + +# We assume here that the value for lt_cv_prog_cc_pic will not be cached +# in isolation, and that seeing it set (from the cache) indicates that +# the associated values are set (in the cache) correctly too. +echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 +echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 +if test "${lt_cv_prog_cc_pic+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_prog_cc_pic= + lt_cv_prog_cc_shlib= + lt_cv_prog_cc_wl= + lt_cv_prog_cc_static= + lt_cv_prog_cc_no_builtin= + lt_cv_prog_cc_can_build_shared=$can_build_shared + + if test "$GCC" = yes; then + lt_cv_prog_cc_wl='-Wl,' + lt_cv_prog_cc_static='-static' + + case $host_os in + aix*) + # Below there is a dirty hack to force normal static linking with -ldl + # The problem is because libdl dynamically linked with both libc and + # libC (AIX C++ library), which obviously doesn't included in libraries + # list by gcc. This cause undefined symbols with -static flags. + # This hack allows C programs to be linked with "-static -ldl", but + # we not sure about C++ programs. + lt_cv_prog_cc_static="$lt_cv_prog_cc_static ${lt_cv_prog_cc_wl}-lC" + ;; + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + lt_cv_prog_cc_pic='-m68020 -resident32 -malways-restore-a4' + ;; + beos* | irix5* | irix6* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_cv_prog_cc_pic='-fno-common' + ;; + cygwin* | mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_cv_prog_cc_pic='-DDLL_EXPORT' + ;; + sysv4*MP*) + if test -d /usr/nec; then + lt_cv_prog_cc_pic=-Kconform_pic + fi + ;; + *) + lt_cv_prog_cc_pic='-fPIC' + ;; + esac + else + # PORTME Check for PIC flags for the system compiler. + case $host_os in + aix3* | aix4* | aix5*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_cv_prog_cc_static='-Bstatic' + lt_cv_prog_cc_wl='-Wl,' + else + lt_cv_prog_cc_static='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + hpux9* | hpux10* | hpux11*) + # Is there a better lt_cv_prog_cc_static that works with the bundled CC? + lt_cv_prog_cc_wl='-Wl,' + lt_cv_prog_cc_static="${lt_cv_prog_cc_wl}-a ${lt_cv_prog_cc_wl}archive" + lt_cv_prog_cc_pic='+Z' + ;; + + irix5* | irix6*) + lt_cv_prog_cc_wl='-Wl,' + lt_cv_prog_cc_static='-non_shared' + # PIC (with -KPIC) is the default. + ;; + + cygwin* | mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_cv_prog_cc_pic='-DDLL_EXPORT' + ;; + + newsos6) + lt_cv_prog_cc_pic='-KPIC' + lt_cv_prog_cc_static='-Bstatic' + ;; + + osf3* | osf4* | osf5*) + # All OSF/1 code is PIC. + lt_cv_prog_cc_wl='-Wl,' + lt_cv_prog_cc_static='-non_shared' + ;; + + sco3.2v5*) + lt_cv_prog_cc_pic='-Kpic' + lt_cv_prog_cc_static='-dn' + lt_cv_prog_cc_shlib='-belf' + ;; + + solaris*) + lt_cv_prog_cc_pic='-KPIC' + lt_cv_prog_cc_static='-Bstatic' + lt_cv_prog_cc_wl='-Wl,' + ;; + + sunos4*) + lt_cv_prog_cc_pic='-PIC' + lt_cv_prog_cc_static='-Bstatic' + lt_cv_prog_cc_wl='-Qoption ld ' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + lt_cv_prog_cc_pic='-KPIC' + lt_cv_prog_cc_static='-Bstatic' + if test "x$host_vendor" = xsni; then + lt_cv_prog_cc_wl='-LD' + else + lt_cv_prog_cc_wl='-Wl,' + fi + ;; + + uts4*) + lt_cv_prog_cc_pic='-pic' + lt_cv_prog_cc_static='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + lt_cv_prog_cc_pic='-Kconform_pic' + lt_cv_prog_cc_static='-Bstatic' + fi + ;; + + *) + lt_cv_prog_cc_can_build_shared=no + ;; + esac + fi + +fi + +if test -z "$lt_cv_prog_cc_pic"; then + echo "$as_me:$LINENO: result: none" >&5 +echo "${ECHO_T}none" >&6 +else + echo "$as_me:$LINENO: result: $lt_cv_prog_cc_pic" >&5 +echo "${ECHO_T}$lt_cv_prog_cc_pic" >&6 + + # Check to make sure the pic_flag actually works. + echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_cv_prog_cc_pic works" >&5 +echo $ECHO_N "checking if $compiler PIC flag $lt_cv_prog_cc_pic works... $ECHO_C" >&6 + if test "${lt_cv_prog_cc_pic_works+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $lt_cv_prog_cc_pic -DPIC" + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + case $host_os in + hpux9* | hpux10* | hpux11*) + # On HP-UX, both CC and GCC only warn that PIC is supported... then + # they create non-PIC objects. So, if there were any warnings, we + # assume that PIC is not supported. + if test -s conftest.err; then + lt_cv_prog_cc_pic_works=no + else + lt_cv_prog_cc_pic_works=yes + fi + ;; + *) + lt_cv_prog_cc_pic_works=yes + ;; + esac + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + lt_cv_prog_cc_pic_works=no + +fi +rm -f conftest.$ac_objext conftest.$ac_ext + CFLAGS="$save_CFLAGS" + +fi + + + if test "X$lt_cv_prog_cc_pic_works" = Xno; then + lt_cv_prog_cc_pic= + lt_cv_prog_cc_can_build_shared=no + else + lt_cv_prog_cc_pic=" $lt_cv_prog_cc_pic" + fi + + echo "$as_me:$LINENO: result: $lt_cv_prog_cc_pic_works" >&5 +echo "${ECHO_T}$lt_cv_prog_cc_pic_works" >&6 +fi +## +## END FIXME + +# Check for any special shared library compilation flags. +if test -n "$lt_cv_prog_cc_shlib"; then + { echo "$as_me:$LINENO: WARNING: \`$CC' requires \`$lt_cv_prog_cc_shlib' to build shared libraries" >&5 +echo "$as_me: WARNING: \`$CC' requires \`$lt_cv_prog_cc_shlib' to build shared libraries" >&2;} + if echo "$old_CC $old_CFLAGS " | egrep -e "[ ]$lt_cv_prog_cc_shlib[ ]" >/dev/null; then : + else + { echo "$as_me:$LINENO: WARNING: add \`$lt_cv_prog_cc_shlib' to the CC or CFLAGS env variable and reconfigure" >&5 +echo "$as_me: WARNING: add \`$lt_cv_prog_cc_shlib' to the CC or CFLAGS env variable and reconfigure" >&2;} + lt_cv_prog_cc_can_build_shared=no + fi +fi + +## FIXME: this should be a separate macro +## +echo "$as_me:$LINENO: checking if $compiler static flag $lt_cv_prog_cc_static works" >&5 +echo $ECHO_N "checking if $compiler static flag $lt_cv_prog_cc_static works... $ECHO_C" >&6 +if test "${lt_cv_prog_cc_static_works+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_prog_cc_static_works=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_cv_prog_cc_static" + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + lt_cv_prog_cc_static_works=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext + LDFLAGS="$save_LDFLAGS" + +fi + + +# Belt *and* braces to stop my trousers falling down: +test "X$lt_cv_prog_cc_static_works" = Xno && lt_cv_prog_cc_static= +echo "$as_me:$LINENO: result: $lt_cv_prog_cc_static_works" >&5 +echo "${ECHO_T}$lt_cv_prog_cc_static_works" >&6 + +pic_flag="$lt_cv_prog_cc_pic" +special_shlib_compile_flags="$lt_cv_prog_cc_shlib" +wl="$lt_cv_prog_cc_wl" +link_static_flag="$lt_cv_prog_cc_static" +no_builtin_flag="$lt_cv_prog_cc_no_builtin" +can_build_shared="$lt_cv_prog_cc_can_build_shared" +## +## END FIXME + + +## FIXME: this should be a separate macro +## +# Check to see if options -o and -c are simultaneously supported by compiler +echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 +echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6 +if test "${lt_cv_compiler_c_o+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + +$rm -r conftest 2>/dev/null +mkdir conftest +cd conftest +echo "int some_variable = 0;" > conftest.$ac_ext +mkdir out +# According to Tom Tromey, Ian Lance Taylor reported there are C compilers +# that will create temporary files in the current directory regardless of +# the output directory. Thus, making CWD read-only will cause this test +# to fail, enabling locking or at least warning the user not to do parallel +# builds. +chmod -w . +save_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS -o out/conftest2.$ac_objext" +compiler_c_o=no +if { (eval echo configure:4552: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.$ac_objext; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s out/conftest.err; then + lt_cv_compiler_c_o=no + else + lt_cv_compiler_c_o=yes + fi +else + # Append any errors to the config.log. + cat out/conftest.err 1>&5 + lt_cv_compiler_c_o=no +fi +CFLAGS="$save_CFLAGS" +chmod u+w . +$rm conftest* out/* +rmdir out +cd .. +rmdir conftest +$rm -r conftest 2>/dev/null + +fi + +compiler_c_o=$lt_cv_compiler_c_o +echo "$as_me:$LINENO: result: $compiler_c_o" >&5 +echo "${ECHO_T}$compiler_c_o" >&6 + +if test x"$compiler_c_o" = x"yes"; then + # Check to see if we can write to a .lo + echo "$as_me:$LINENO: checking if $compiler supports -c -o file.lo" >&5 +echo $ECHO_N "checking if $compiler supports -c -o file.lo... $ECHO_C" >&6 + if test "${lt_cv_compiler_o_lo+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + lt_cv_compiler_o_lo=no + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -c -o conftest.lo" + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +int some_variable = 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + lt_cv_compiler_o_lo=no + else + lt_cv_compiler_o_lo=yes + fi + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.$ac_objext conftest.$ac_ext + CFLAGS="$save_CFLAGS" + +fi + + compiler_o_lo=$lt_cv_compiler_o_lo + echo "$as_me:$LINENO: result: $compiler_c_lo" >&5 +echo "${ECHO_T}$compiler_c_lo" >&6 +else + compiler_o_lo=no +fi +## +## END FIXME + +## FIXME: this should be a separate macro +## +# Check to see if we can do hard links to lock some files if needed +hard_links="nottested" +if test "$compiler_c_o" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 +echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6 + hard_links=yes + $rm conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + echo "$as_me:$LINENO: result: $hard_links" >&5 +echo "${ECHO_T}$hard_links" >&6 + if test "$hard_links" = no; then + { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 +echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi +## +## END FIXME + +## FIXME: this should be a separate macro +## +if test "$GCC" = yes; then + # Check to see if options -fno-rtti -fno-exceptions are supported by compiler + echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 +echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6 + echo "int some_variable = 0;" > conftest.$ac_ext + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -fno-rtti -fno-exceptions -c conftest.$ac_ext" + compiler_rtti_exceptions=no + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +int some_variable = 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + compiler_rtti_exceptions=no + else + compiler_rtti_exceptions=yes + fi + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.$ac_objext conftest.$ac_ext + CFLAGS="$save_CFLAGS" + echo "$as_me:$LINENO: result: $compiler_rtti_exceptions" >&5 +echo "${ECHO_T}$compiler_rtti_exceptions" >&6 + + if test "$compiler_rtti_exceptions" = "yes"; then + no_builtin_flag=' -fno-builtin -fno-rtti -fno-exceptions' + else + no_builtin_flag=' -fno-builtin' + fi +fi +## +## END FIXME + +## FIXME: this should be a separate macro +## +# See if the linker supports building shared libraries. +echo "$as_me:$LINENO: checking whether the linker ($LD) supports shared libraries" >&5 +echo $ECHO_N "checking whether the linker ($LD) supports shared libraries... $ECHO_C" >&6 + +allow_undefined_flag= +no_undefined_flag= +need_lib_prefix=unknown +need_version=unknown +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +archive_cmds= +archive_expsym_cmds= +old_archive_from_new_cmds= +old_archive_from_expsyms_cmds= +export_dynamic_flag_spec= +whole_archive_flag_spec= +thread_safe_flag_spec= +hardcode_into_libs=no +hardcode_libdir_flag_spec= +hardcode_libdir_separator= +hardcode_direct=no +hardcode_minus_L=no +hardcode_shlibpath_var=unsupported +runpath_var= +link_all_deplibs=unknown +always_export_symbols=no +export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | sed '\''s/.* //'\'' | sort | uniq > $export_symbols' +# include_expsyms should be a list of space-separated symbols to be *always* +# included in the symbol list +include_expsyms= +# exclude_expsyms can be an egrep regular expression of symbols to exclude +# it will be wrapped by ` (' and `)$', so one must not match beginning or +# end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', +# as well as any symbol that contains `d'. +exclude_expsyms="_GLOBAL_OFFSET_TABLE_" +# Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out +# platforms (ab)use it in PIC code, but their linkers get confused if +# the symbol is explicitly referenced. Since portable code cannot +# rely on this symbol name, it's probably fine to never include it in +# preloaded symbol tables. +extract_expsyms_cmds= + +case $host_os in +cygwin* | mingw* | pw32* ) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + +esac + +ld_shlibs=yes +if test "$with_gnu_ld" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # See if GNU ld supports shared libraries. + case $host_os in + aix3* | aix4* | aix5*) + # On AIX, the GNU linker is very broken + # Note:Check GNU linker on AIX 5-IA64 when/if it becomes available. + ld_shlibs=no + cat <&2 + +*** Warning: the GNU linker, at least up to release 2.9.1, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to modify your PATH +*** so that a non-GNU linker is found, and then restart. + +EOF + ;; + + amigaos*) + archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + + # Samuel A. Falvo II reports + # that the semantics of dynamic libraries on AmigaOS, at least up + # to version 4, is to share data among multiple programs linked + # with the same dynamic library. Since this doesn't match the + # behavior of shared libraries on other platforms, we can use + # them. + ld_shlibs=no + ;; + + beos*) + if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + ld_shlibs=no + fi + ;; + + cygwin* | mingw* | pw32*) + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + allow_undefined_flag=unsupported + always_export_symbols=yes + + extract_expsyms_cmds='test -f $output_objdir/impgen.c || \ + sed -e "/^# \/\* impgen\.c starts here \*\//,/^# \/\* impgen.c ends here \*\// { s/^# //;s/^# *$//; p; }" -e d < $''0 > $output_objdir/impgen.c~ + test -f $output_objdir/impgen.exe || (cd $output_objdir && \ + if test "x$HOST_CC" != "x" ; then $HOST_CC -o impgen impgen.c ; \ + else $CC -o impgen impgen.c ; fi)~ + $output_objdir/impgen $dir/$soroot > $output_objdir/$soname-def' + + old_archive_from_expsyms_cmds='$DLLTOOL --as=$AS --dllname $soname --def $output_objdir/$soname-def --output-lib $output_objdir/$newlib' + + # cygwin and mingw dlls have different entry points and sets of symbols + # to exclude. + # FIXME: what about values for MSVC? + dll_entry=__cygwin_dll_entry@12 + dll_exclude_symbols=DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12~ + case $host_os in + mingw*) + # mingw values + dll_entry=_DllMainCRTStartup@12 + dll_exclude_symbols=DllMain@12,DllMainCRTStartup@12,DllEntryPoint@12~ + ;; + esac + + # mingw and cygwin differ, and it's simplest to just exclude the union + # of the two symbol sets. + dll_exclude_symbols=DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12,DllMainCRTStartup@12,DllEntryPoint@12 + + # recent cygwin and mingw systems supply a stub DllMain which the user + # can override, but on older systems we have to supply one (in ltdll.c) + if test "x$lt_cv_need_dllmain" = "xyes"; then + ltdll_obj='$output_objdir/$soname-ltdll.'"$ac_objext " + ltdll_cmds='test -f $output_objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < [$]0 > $output_objdir/$soname-ltdll.c~ + test -f $output_objdir/$soname-ltdll.$ac_objext || (cd $output_objdir && $CC -c $soname-ltdll.c)~' + else + ltdll_obj= + ltdll_cmds= + fi + + # Extract the symbol export list from an `--export-all' def file, + # then regenerate the def file from the symbol export list, so that + # the compiled dll only exports the symbol export list. + # Be careful not to strip the DATA tag left be newer dlltools. + export_symbols_cmds="$ltdll_cmds"' + $DLLTOOL --export-all --exclude-symbols '$dll_exclude_symbols' --output-def $output_objdir/$soname-def '$ltdll_obj'$libobjs $convenience~ + sed -e "1,/EXPORTS/d" -e "s/ @ [0-9]*//" -e "s/ *;.*$//" < $output_objdir/$soname-def > $export_symbols' + + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is. + # If DATA tags from a recent dlltool are present, honour them! + archive_expsym_cmds='if test "x`head -1 $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname-def; + else + echo EXPORTS > $output_objdir/$soname-def; + _lt_hint=1; + cat $export_symbols | while read symbol; do + set dummy \$symbol; + case \$# in + 2) echo " \$2 @ \$_lt_hint ; " >> $output_objdir/$soname-def;; + *) echo " \$2 @ \$_lt_hint \$3 ; " >> $output_objdir/$soname-def;; + esac; + _lt_hint=`expr 1 + \$_lt_hint`; + done; + fi~ + '"$ltdll_cmds"' + $CC -Wl,--base-file,$output_objdir/$soname-base '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags~ + $DLLTOOL --as=$AS --dllname $soname --exclude-symbols '$dll_exclude_symbols' --def $output_objdir/$soname-def --base-file $output_objdir/$soname-base --output-exp $output_objdir/$soname-exp~ + $CC -Wl,--base-file,$output_objdir/$soname-base $output_objdir/$soname-exp '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags~ + $DLLTOOL --as=$AS --dllname $soname --exclude-symbols '$dll_exclude_symbols' --def $output_objdir/$soname-def --base-file $output_objdir/$soname-base --output-exp $output_objdir/$soname-exp --output-lib $output_objdir/$libname.dll.a~ + $CC $output_objdir/$soname-exp '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags' + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + archive_cmds='$CC -shared -nodefaultlibs $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared -nodefaultlibs $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris* | sysv5*) + if $LD -v 2>&1 | egrep 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + cat <&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +EOF + elif $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + + sunos4*) + archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + *) + if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + + if test "$ld_shlibs" = yes; then + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec='${wl}--export-dynamic' + case $host_os in + cygwin* | mingw* | pw32*) + # dlltool doesn't understand --whole-archive et. al. + whole_archive_flag_spec= + ;; + *) + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | egrep 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec= + fi + ;; + esac + fi +else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + allow_undefined_flag=unsupported + always_export_symbols=yes + archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test "$GCC" = yes && test -z "$link_static_flag"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + + aix4* | aix5*) + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds='' + hardcode_libdir_separator=':' + if test "$GCC" = yes; then + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + hardcode_direct=yes + else + # We have old collect2 + hardcode_direct=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' + hardcode_libdir_separator= + fi + shared_flag='-shared' + else + if test "$host_cpu" = ia64; then + shared_flag='-G' + else + shared_flag='${wl}-bM:SRE' + fi + hardcode_direct=yes + fi + + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # Test if we are trying to use run time linking, or normal AIX style linking. + # If -brtl is somewhere in LDFLAGS, we need to do run time linking. + aix_use_runtimelinking=no + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl" ); then + aix_use_runtimelinking=yes + break + fi + done + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + # It seems that -bexpall can do strange things, so it is better to + # generate a list of symbols to export. + always_export_symbols=yes + if test "$aix_use_runtimelinking" = yes; then + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:/usr/lib:/lib' + allow_undefined_flag=' -Wl,-G' + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' + allow_undefined_flag="-znodefs" + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname ${wl}-h$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" + else + hardcode_libdir_flag_spec='${wl}-bnolibpath ${wl}-blibpath:$libdir:/usr/lib:/lib' + # Warning - without using the other run time loading flags, -berok will + # link without error, but may produce a broken library. + allow_undefined_flag='${wl}-berok" + # This is a bit strange, but is similar to how AIX traditionally builds + # it's shared libraries. + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols"' ~$AR -crlo $objdir/$libname$release.a $objdir/$soname' + fi + fi + ;; + + amigaos*) + archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + # see comment about different semantics on the GNU ld section + ld_shlibs=no + ;; + + cygwin* | mingw* | pw32*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | sed -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_from_new_cmds='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds='lib /OUT:$oldlib$oldobjs$old_deplibs' + fix_srcfile_path='`cygpath -w "$srcfile"`' + ;; + + darwin* | rhapsody*) + # This patch put in by hand by PH (22-May-2003) for Darwin 1.3. + case "$host_os" in + rhapsody* | darwin1.[[012]]) + allow_undefined_flag='-undefined suppress' + ;; + *) # Darwin 1.3 on + allow_undefined_flag='-flat_namespace -undefined suppress' + ;; + esac + # End of hand-inserted patch + + # FIXME: Relying on posixy $() will cause problems for + # cross-compilation, but unfortunately the echo tests do not + # yet detect zsh echo's removal of \ escapes. + archive_cmds='$CC $(test .$module = .yes && echo -bundle || echo -dynamiclib) $allow_undefined_flag -o $lib $libobjs $deplibs$linkopts -install_name $rpath/$soname $(test -n "$verstring" -a x$verstring != x0.0 && echo $verstring)' + # We need to add '_' to the symbols in $export_symbols first + #archive_expsym_cmds="$archive_cmds"' && strip -s $export_symbols' + hardcode_direct=yes + hardcode_shlibpath_var=no + whole_archive_flag_spec='-all_load $convenience' + ;; + + freebsd1*) + ld_shlibs=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd*) + archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + hpux9* | hpux10* | hpux11*) + case $host_os in + hpux9*) archive_cmds='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' ;; + *) archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' ;; + esac + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + hardcode_minus_L=yes # Not in the search PATH, but as the default + # location of the library. + export_dynamic_flag_spec='${wl}-E' + ;; + + irix5* | irix6*) + if test "$GCC" = yes; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + fi + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + link_all_deplibs=yes + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + newsos6) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' + hardcode_direct=yes + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_shlibpath_var=no + ;; + + openbsd*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + fi + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds='for i in `cat $export_symbols`; do printf "-exported_symbol " >> $lib.exp; echo "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ + $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib~$rm $lib.exp' + + #Both c and cxx compiler support -rpath directly + hardcode_libdir_flag_spec='-rpath $libdir' + fi + hardcode_libdir_separator=: + ;; + + sco3.2v5*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ;; + + solaris*) + no_undefined_flag=' -z defs' + # $CC -shared without GNU ld will not create a library from C++ + # object files and a static libstdc++, better avoid it by now + archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_shlibpath_var=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) # Supported since Solaris 2.6 (maybe 2.5.1?) + whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;; + esac + link_all_deplibs=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + sysv4) + if test "x$host_vendor" = xsno; then + archive_cmds='$LD -G -Bsymbolic -h $soname -o $lib $libobjs $deplibs $linkopts' + hardcode_direct=yes # is this really true??? + else + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=no #Motorola manual says yes, but my tests say they lie + fi + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var=no + ;; + + sysv4.3*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + export_dynamic_flag_spec='-Bexport' + ;; + + sysv5*) + no_undefined_flag=' -z text' + # $CC -shared without GNU ld will not create a library from C++ + # object files and a static libstdc++, better avoid it by now + archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' + hardcode_libdir_flag_spec= + hardcode_shlibpath_var=no + runpath_var='LD_RUN_PATH' + ;; + + uts4*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + dgux*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs=yes + fi + ;; + + sysv4.2uw2*) + archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_minus_L=no + hardcode_shlibpath_var=no + hardcode_runpath_var=yes + runpath_var=LD_RUN_PATH + ;; + + sysv5uw7* | unixware7*) + no_undefined_flag='${wl}-z ${wl}text' + if test "$GCC" = yes; then + archive_cmds='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var=no + ;; + + *) + ld_shlibs=no + ;; + esac +fi +echo "$as_me:$LINENO: result: $ld_shlibs" >&5 +echo "${ECHO_T}$ld_shlibs" >&6 +test "$ld_shlibs" = no && can_build_shared=no +## +## END FIXME + +## FIXME: this should be a separate macro +## +# Check hardcoding attributes. +echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 +echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6 +hardcode_action= +if test -n "$hardcode_libdir_flag_spec" || \ + test -n "$runpath_var"; then + + # We can hardcode non-existant directories. + if test "$hardcode_direct" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$hardcode_shlibpath_var" != no && + test "$hardcode_minus_L" != no; then + # Linking always hardcodes the temporary library directory. + hardcode_action=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action=unsupported +fi +echo "$as_me:$LINENO: result: $hardcode_action" >&5 +echo "${ECHO_T}$hardcode_action" >&6 +## +## END FIXME + +## FIXME: this should be a separate macro +## +striplib= +old_striplib= +echo "$as_me:$LINENO: checking whether stripping libraries is possible" >&5 +echo $ECHO_N "checking whether stripping libraries is possible... $ECHO_C" >&6 +if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi +## +## END FIXME + +reload_cmds='$LD$reload_flag -o $output$reload_objs' +test -z "$deplibs_check_method" && deplibs_check_method=unknown + +## FIXME: this should be a separate macro +## +# PORTME Fill in your ld.so characteristics +echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 +echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6 +library_names_spec= +libname_spec='lib$name' +soname_spec= +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}.so$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}.so$major' + ;; + +aix4* | aix5*) + version_type=linux + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}.so$major ${libname}${release}.so$versuffix $libname.so' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so instead of + # lib.a to let people know that these are not typical AIX shared libraries. + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}.so$major' + fi + shlibpath_var=LIBPATH + deplibs_check_method=pass_all + fi + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "(cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a)"; (cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a) || exit 1; done' + ;; + +beos*) + library_names_spec='${libname}.so' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi4*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + soname_spec='${libname}${release}.so$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + export_dynamic_flag_spec=-rdynamic + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32*) + version_type=windows + need_version=no + need_lib_prefix=no + case $GCC,$host_os in + yes,cygwin*) + library_names_spec='$libname.dll.a' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll' + postinstall_cmds='dlpath=`bash 2>&1 -c '\''. $dir/${file}i;echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog .libs/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`bash 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $rm \$dlpath' + ;; + yes,mingw*) + library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll' + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | sed -e "s/^libraries://" -e "s/;/ /g"` + ;; + yes,pw32*) + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | sed -e 's/./-/g'`${versuffix}.dll' + ;; + *) + library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + # FIXME: Relying on posixy $() will cause problems for + # cross-compilation, but unfortunately the echo tests do not + # yet detect zsh echo's removal of \ escapes. + library_names_spec='${libname}${release}${versuffix}.$(test .$module = .yes && echo so || echo dylib) ${libname}${release}${major}.$(test .$module = .yes && echo so || echo dylib) ${libname}.$(test .$module = .yes && echo so || echo dylib)' + soname_spec='${libname}${release}${major}.$(test .$module = .yes && echo so || echo dylib)' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +freebsd*) + objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}.so$versuffix $libname.so$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + *) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so${major} ${libname}.so' + soname_spec='${libname}${release}.so$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + dynamic_linker="$host_os dld.sl" + version_type=sunos + need_lib_prefix=no + need_version=no + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}.sl$versuffix ${libname}${release}.sl$major $libname.sl' + soname_spec='${libname}${release}.sl$major' + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +irix5* | irix6*) + version_type=irix + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}.so$major' + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so $libname.so' + case $host_os in + irix5*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 ") libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 ") libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux-gnuoldld* | linux-gnuaout* | linux-gnucoff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux-gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + soname_spec='${libname}${release}.so$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so ${libname}.so' + soname_spec='${libname}${release}.so$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +openbsd*) + version_type=sunos + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + need_version=no + fi + library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + ;; + +os2*) + libname_spec='$name' + need_lib_prefix=no + library_names_spec='$libname.dll $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_version=no + soname_spec='${libname}${release}.so' + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +sco3.2v5*) + version_type=osf + soname_spec='${libname}${release}.so$major' + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + shlibpath_var=LD_LIBRARY_PATH + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + soname_spec='${libname}${release}.so$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + version_type=linux + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + soname_spec='${libname}${release}.so$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + soname_spec='${libname}${release}.so$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + soname_spec='${libname}${release}.so$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname.so.$versuffix $libname.so.$major $libname.so' + soname_spec='$libname.so.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +*) + dynamic_linker=no + ;; +esac +echo "$as_me:$LINENO: result: $dynamic_linker" >&5 +echo "${ECHO_T}$dynamic_linker" >&6 +test "$dynamic_linker" = no && can_build_shared=no +## +## END FIXME + +## FIXME: this should be a separate macro +## +# Report the final consequences. +echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5 +echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6 +echo "$as_me:$LINENO: result: $can_build_shared" >&5 +echo "${ECHO_T}$can_build_shared" >&6 +## +## END FIXME + +if test "$hardcode_action" = relink; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + cygwin* | mingw* | pw32*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + *) + echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 +echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6 +if test "${ac_cv_lib_dl_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char dlopen (); +int +main () +{ +dlopen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dl_dlopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_dl_dlopen=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 +echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6 +if test $ac_cv_lib_dl_dlopen = yes; then + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + echo "$as_me:$LINENO: checking for dlopen" >&5 +echo $ECHO_N "checking for dlopen... $ECHO_C" >&6 +if test "${ac_cv_func_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char dlopen (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ +#ifdef __STDC__ +# include +#else +# include +#endif +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char dlopen (); +/* 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_dlopen) || defined (__stub___dlopen) +choke me +#else +char (*f) () = dlopen; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != dlopen; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_dlopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_dlopen=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_dlopen" >&5 +echo "${ECHO_T}$ac_cv_func_dlopen" >&6 +if test $ac_cv_func_dlopen = yes; then + lt_cv_dlopen="dlopen" +else + echo "$as_me:$LINENO: checking for shl_load" >&5 +echo $ECHO_N "checking for shl_load... $ECHO_C" >&6 +if test "${ac_cv_func_shl_load+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char shl_load (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ +#ifdef __STDC__ +# include +#else +# include +#endif +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char shl_load (); +/* 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_shl_load) || defined (__stub___shl_load) +choke me +#else +char (*f) () = shl_load; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != shl_load; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_shl_load=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_shl_load=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5 +echo "${ECHO_T}$ac_cv_func_shl_load" >&6 +if test $ac_cv_func_shl_load = yes; then + lt_cv_dlopen="shl_load" +else + echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5 +echo $ECHO_N "checking for dlopen in -lsvld... $ECHO_C" >&6 +if test "${ac_cv_lib_svld_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsvld $LIBS" +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char dlopen (); +int +main () +{ +dlopen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_svld_dlopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_svld_dlopen=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5 +echo "${ECHO_T}$ac_cv_lib_svld_dlopen" >&6 +if test $ac_cv_lib_svld_dlopen = yes; then + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" +else + echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5 +echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6 +if test "${ac_cv_lib_dld_shl_load+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char shl_load (); +int +main () +{ +shl_load (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dld_shl_load=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_dld_shl_load=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5 +echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6 +if test $ac_cv_lib_dld_shl_load = yes; then + lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld" +fi + + +fi + + +fi + + +fi + + +fi + + ;; + esac + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + else + enable_dlopen=no + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + echo "$as_me:$LINENO: checking whether a program can dlopen itself" >&5 +echo $ECHO_N "checking whether a program can dlopen itself... $ECHO_C" >&6 +if test "${lt_cv_dlopen_self+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$cross_compiling" = yes; then : + lt_cv_dlopen_self=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext < +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +#ifdef __cplusplus +extern "C" void exit (int); +#endif + +void fnord() { int i=42;} +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + /* dlclose (self); */ + } + + exit (status); +} +EOF + if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; + x$lt_unknown|x*) lt_cv_dlopen_self=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self=no + fi +fi +rm -fr conftest* + + +fi +echo "$as_me:$LINENO: result: $lt_cv_dlopen_self" >&5 +echo "${ECHO_T}$lt_cv_dlopen_self" >&6 + + if test "x$lt_cv_dlopen_self" = xyes; then + LDFLAGS="$LDFLAGS $link_static_flag" + echo "$as_me:$LINENO: checking whether a statically linked program can dlopen itself" >&5 +echo $ECHO_N "checking whether a statically linked program can dlopen itself... $ECHO_C" >&6 +if test "${lt_cv_dlopen_self_static+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$cross_compiling" = yes; then : + lt_cv_dlopen_self_static=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext < +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +#ifdef __cplusplus +extern "C" void exit (int); +#endif + +void fnord() { int i=42;} +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + /* dlclose (self); */ + } + + exit (status); +} +EOF + if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_unknown|x*) lt_cv_dlopen_self_static=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self_static=no + fi +fi +rm -fr conftest* + + +fi +echo "$as_me:$LINENO: result: $lt_cv_dlopen_self_static" >&5 +echo "${ECHO_T}$lt_cv_dlopen_self_static" >&6 + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi + + +## FIXME: this should be a separate macro +## +if test "$enable_shared" = yes && test "$GCC" = yes; then + case $archive_cmds in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 +echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6 + if test "${lt_cv_archive_cmds_need_lc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + $rm conftest* + echo 'static int dummy;' > conftest.$ac_ext + + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_cv_prog_cc_wl + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + save_allow_undefined_flag=$allow_undefined_flag + allow_undefined_flag= + if { (eval echo "$as_me:$LINENO: \"$archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 + (eval $archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + then + lt_cv_archive_cmds_need_lc=no + else + lt_cv_archive_cmds_need_lc=yes + fi + allow_undefined_flag=$save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi +fi + + echo "$as_me:$LINENO: result: $lt_cv_archive_cmds_need_lc" >&5 +echo "${ECHO_T}$lt_cv_archive_cmds_need_lc" >&6 + ;; + esac +fi +need_lc=${lt_cv_archive_cmds_need_lc-yes} +## +## END FIXME + +## FIXME: this should be a separate macro +## +# The second clause should only fire when bootstrapping the +# libtool distribution, otherwise you forgot to ship ltmain.sh +# with your package, and you will get complaints that there are +# no rules to generate ltmain.sh. +if test -f "$ltmain"; then + : +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + test -f Makefile && make "$ltmain" +fi + +if test -f "$ltmain"; then + trap "$rm \"${ofile}T\"; exit 1" 1 2 15 + $rm -f "${ofile}T" + + echo creating $ofile + + # Now quote all the things that may contain metacharacters while being + # careful not to overquote the AC_SUBSTed values. We take copies of the + # variables and quote the copies for generation of the libtool script. + for var in echo old_CC old_CFLAGS \ + AR AR_FLAGS CC LD LN_S NM SHELL \ + reload_flag reload_cmds wl \ + pic_flag link_static_flag no_builtin_flag export_dynamic_flag_spec \ + thread_safe_flag_spec whole_archive_flag_spec libname_spec \ + library_names_spec soname_spec \ + RANLIB old_archive_cmds old_archive_from_new_cmds old_postinstall_cmds \ + old_postuninstall_cmds archive_cmds archive_expsym_cmds postinstall_cmds \ + postuninstall_cmds extract_expsyms_cmds old_archive_from_expsyms_cmds \ + old_striplib striplib file_magic_cmd export_symbols_cmds \ + deplibs_check_method allow_undefined_flag no_undefined_flag \ + finish_cmds finish_eval global_symbol_pipe global_symbol_to_cdecl \ + hardcode_libdir_flag_spec hardcode_libdir_separator \ + sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ + compiler_c_o compiler_o_lo need_locks exclude_expsyms include_expsyms; do + + case $var in + reload_cmds | old_archive_cmds | old_archive_from_new_cmds | \ + old_postinstall_cmds | old_postuninstall_cmds | \ + export_symbols_cmds | archive_cmds | archive_expsym_cmds | \ + extract_expsyms_cmds | old_archive_from_expsyms_cmds | \ + postinstall_cmds | postuninstall_cmds | \ + finish_cmds | sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) + # Double-quote double-evaled strings. + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" + ;; + *) + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" + ;; + esac + done + + cat <<__EOF__ > "${ofile}T" +#! $SHELL + +# `$echo "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +# Copyright (C) 1996-2000 Free Software Foundation, Inc. +# Originally by Gordon Matzigkeit , 1996 +# +# This program 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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. + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="sed -e s/^X//" + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +if test "X\${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi + +# ### BEGIN LIBTOOL CONFIG + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$need_lc + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# The default C compiler. +CC=$lt_CC + +# Is the compiler the GNU C compiler? +with_gcc=$GCC + +# The linker used to build libraries. +LD=$lt_LD + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A symbol stripping program +STRIP=$STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_wl + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_pic_flag +pic_mode=$pic_mode + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_compiler_c_o + +# Can we write directly to a .lo ? +compiler_o_lo=$lt_compiler_o_lo + +# Must we lock files when doing compilation ? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_link_static_flag + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_no_builtin_flag + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_thread_safe_flag_spec + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_old_archive_cmds +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds + +# Commands used to build and install a shared archive. +archive_cmds=$lt_archive_cmds +archive_expsym_cmds=$lt_archive_expsym_cmds +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_global_symbol_pipe + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl=$lt_global_symbol_to_cdecl + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator + +# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$hardcode_direct + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$hardcode_minus_L + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path="$fix_srcfile_path" + +# Set to yes if exported symbols are required. +always_export_symbols=$always_export_symbols + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms + +# ### END LIBTOOL CONFIG + +__EOF__ + + case $host_os in + aix3*) + cat <<\EOF >> "${ofile}T" + +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +EOF + ;; + esac + + case $host_os in + cygwin* | mingw* | pw32* | os2*) + cat <<'EOF' >> "${ofile}T" + # This is a source program that is used to create dlls on Windows + # Don't remove nor modify the starting and closing comments +# /* ltdll.c starts here */ +# #define WIN32_LEAN_AND_MEAN +# #include +# #undef WIN32_LEAN_AND_MEAN +# #include +# +# #ifndef __CYGWIN__ +# # ifdef __CYGWIN32__ +# # define __CYGWIN__ __CYGWIN32__ +# # endif +# #endif +# +# #ifdef __cplusplus +# extern "C" { +# #endif +# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved); +# #ifdef __cplusplus +# } +# #endif +# +# #ifdef __CYGWIN__ +# #include +# DECLARE_CYGWIN_DLL( DllMain ); +# #endif +# HINSTANCE __hDllInstance_base; +# +# BOOL APIENTRY +# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved) +# { +# __hDllInstance_base = hInst; +# return TRUE; +# } +# /* ltdll.c ends here */ + # This is a source program that is used to create import libraries + # on Windows for dlls which lack them. Don't remove nor modify the + # starting and closing comments +# /* impgen.c starts here */ +# /* Copyright (C) 1999-2000 Free Software Foundation, Inc. +# +# This file is part of GNU libtool. +# +# This program 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# */ +# +# #include /* for printf() */ +# #include /* for open(), lseek(), read() */ +# #include /* for O_RDONLY, O_BINARY */ +# #include /* for strdup() */ +# +# /* O_BINARY isn't required (or even defined sometimes) under Unix */ +# #ifndef O_BINARY +# #define O_BINARY 0 +# #endif +# +# static unsigned int +# pe_get16 (fd, offset) +# int fd; +# int offset; +# { +# unsigned char b[2]; +# lseek (fd, offset, SEEK_SET); +# read (fd, b, 2); +# return b[0] + (b[1]<<8); +# } +# +# static unsigned int +# pe_get32 (fd, offset) +# int fd; +# int offset; +# { +# unsigned char b[4]; +# lseek (fd, offset, SEEK_SET); +# read (fd, b, 4); +# return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24); +# } +# +# static unsigned int +# pe_as32 (ptr) +# void *ptr; +# { +# unsigned char *b = ptr; +# return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24); +# } +# +# int +# main (argc, argv) +# int argc; +# char *argv[]; +# { +# int dll; +# unsigned long pe_header_offset, opthdr_ofs, num_entries, i; +# unsigned long export_rva, export_size, nsections, secptr, expptr; +# unsigned long name_rvas, nexp; +# unsigned char *expdata, *erva; +# char *filename, *dll_name; +# +# filename = argv[1]; +# +# dll = open(filename, O_RDONLY|O_BINARY); +# if (dll < 1) +# return 1; +# +# dll_name = filename; +# +# for (i=0; filename[i]; i++) +# if (filename[i] == '/' || filename[i] == '\\' || filename[i] == ':') +# dll_name = filename + i +1; +# +# pe_header_offset = pe_get32 (dll, 0x3c); +# opthdr_ofs = pe_header_offset + 4 + 20; +# num_entries = pe_get32 (dll, opthdr_ofs + 92); +# +# if (num_entries < 1) /* no exports */ +# return 1; +# +# export_rva = pe_get32 (dll, opthdr_ofs + 96); +# export_size = pe_get32 (dll, opthdr_ofs + 100); +# nsections = pe_get16 (dll, pe_header_offset + 4 +2); +# secptr = (pe_header_offset + 4 + 20 + +# pe_get16 (dll, pe_header_offset + 4 + 16)); +# +# expptr = 0; +# for (i = 0; i < nsections; i++) +# { +# char sname[8]; +# unsigned long secptr1 = secptr + 40 * i; +# unsigned long vaddr = pe_get32 (dll, secptr1 + 12); +# unsigned long vsize = pe_get32 (dll, secptr1 + 16); +# unsigned long fptr = pe_get32 (dll, secptr1 + 20); +# lseek(dll, secptr1, SEEK_SET); +# read(dll, sname, 8); +# if (vaddr <= export_rva && vaddr+vsize > export_rva) +# { +# expptr = fptr + (export_rva - vaddr); +# if (export_rva + export_size > vaddr + vsize) +# export_size = vsize - (export_rva - vaddr); +# break; +# } +# } +# +# expdata = (unsigned char*)malloc(export_size); +# lseek (dll, expptr, SEEK_SET); +# read (dll, expdata, export_size); +# erva = expdata - export_rva; +# +# nexp = pe_as32 (expdata+24); +# name_rvas = pe_as32 (expdata+32); +# +# printf ("EXPORTS\n"); +# for (i = 0; i> "${ofile}T" || (rm -f "${ofile}T"; exit 1) + + mv -f "${ofile}T" "$ofile" || \ + (rm -f "$ofile" && cp "${ofile}T" "$ofile" && rm -f "${ofile}T") + chmod +x "$ofile" +fi +## +## END FIXME + + + + + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' + +# Prevent multiple expansion + + + + +CC_FOR_BUILD=${CC_FOR_BUILD:-'$(CC)'} +CFLAGS_FOR_BUILD=${CFLAGS_FOR_BUILD:-'$(CFLAGS)'} +BUILD_EXEEXT=${BUILD_EXEEXT:-'$(EXEEXT)'} +BUILD_OBJEXT=${BUILD_OBJEXT:-'$(OBJEXT)'} + + +echo "$as_me:$LINENO: checking for ANSI C header files" >&5 +echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 +if test "${ac_cv_header_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_stdc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_header_stdc=no +fi +rm -f 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 >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* 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 >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* 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 >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#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)) + exit(2); + exit (0); +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_header_stdc=no +fi +rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 +echo "${ECHO_T}$ac_cv_header_stdc" >&6 +if test $ac_cv_header_stdc = yes; then + +cat >>confdefs.h <<\_ACEOF +#define STDC_HEADERS 1 +_ACEOF + +fi + + +for ac_header in limits.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc in + yes:no ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------ ## +## Report this to bug-autoconf@gnu.org. ## +## ------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; + no:yes ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------ ## +## Report this to bug-autoconf@gnu.org. ## +## ------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + +echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5 +echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6 +if test "${ac_cv_c_const+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +/* FIXME: Include the comments suggested by Paul. */ +#ifndef __cplusplus + /* Ultrix mips cc rejects this. */ + typedef int charset[2]; + const charset x; + /* SunOS 4.1.1 cc rejects this. */ + char const *const *ccp; + char **p; + /* NEC SVR4.0.2 mips cc rejects this. */ + struct point {int x, y;}; + static struct point const zero = {0,0}; + /* AIX XL C 1.02.0.0 rejects this. + It does not let you subtract one const X* pointer from another in + an arm of an if-expression whose if-part is not a constant + expression */ + const char *g = "string"; + ccp = &g + (g ? g-g : 0); + /* HPUX 7.0 cc rejects these. */ + ++ccp; + p = (char**) ccp; + ccp = (char const *const *) p; + { /* SCO 3.2v4 cc rejects this. */ + char *t; + char const *s = 0 ? (char *) 0 : (char const *) 0; + + *t++ = 0; + } + { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ + int x[] = {25, 17}; + const int *foo = &x[0]; + ++foo; + } + { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ + typedef const int *iptr; + iptr p = 0; + ++p; + } + { /* AIX XL C 1.02.0.0 rejects this saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; }; + struct s *b; b->j = 5; + } + { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; + } +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_const=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_c_const=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5 +echo "${ECHO_T}$ac_cv_c_const" >&6 +if test $ac_cv_c_const = no; then + +cat >>confdefs.h <<\_ACEOF +#define const +_ACEOF + +fi + +echo "$as_me:$LINENO: checking for size_t" >&5 +echo $ECHO_N "checking for size_t... $ECHO_C" >&6 +if test "${ac_cv_type_size_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +if ((size_t *) 0) + return 0; +if (sizeof (size_t)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_size_t=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_type_size_t=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_type_size_t" >&5 +echo "${ECHO_T}$ac_cv_type_size_t" >&6 +if test $ac_cv_type_size_t = yes; then + : +else + +cat >>confdefs.h <<_ACEOF +#define size_t unsigned +_ACEOF + +fi + + + + + + +for ac_func in bcopy memmove strerror +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 +if eval "test \"\${$as_ac_var+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ +#ifdef __STDC__ +# include +#else +# include +#endif +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func (); +/* 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_$ac_func) || defined (__stub___$ac_func) +choke me +#else +char (*f) () = $ac_func; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != $ac_func; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_var=no" +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + +# Check whether --enable-utf8 or --disable-utf8 was given. +if test "${enable_utf8+set}" = set; then + enableval="$enable_utf8" + if test "$enableval" = "yes"; then + UTF8=-DSUPPORT_UTF8 +fi + +fi; + + +# Check whether --enable-newline-is-cr or --disable-newline-is-cr was given. +if test "${enable_newline_is_cr+set}" = set; then + enableval="$enable_newline_is_cr" + if test "$enableval" = "yes"; then + NEWLINE=-DNEWLINE=13 +fi + +fi; + + +# Check whether --enable-newline-is-lf or --disable-newline-is-lf was given. +if test "${enable_newline_is_lf+set}" = set; then + enableval="$enable_newline_is_lf" + if test "$enableval" = "yes"; then + NEWLINE=-DNEWLINE=10 +fi + +fi; + + + + +# Check whether --with-posix-malloc-threshold or --without-posix-malloc-threshold was given. +if test "${with_posix_malloc_threshold+set}" = set; then + withval="$with_posix_malloc_threshold" + POSIX_MALLOC_THRESHOLD=-DPOSIX_MALLOC_THRESHOLD=$withval + +fi; + + + +# Check whether --with-link-size or --without-link-size was given. +if test "${with_link_size+set}" = set; then + withval="$with_link_size" + LINK_SIZE=-DLINK_SIZE=$withval + +fi; + + + +# Check whether --with-match-limit or --without-match-limit was given. +if test "${with_match_limit+set}" = set; then + withval="$with_match_limit" + MATCH_LIMIT=-DMATCH_LIMIT=$withval + +fi; + + + + + + + + + + + + + + + + + + + + + + + + +case $host_os in +mingw* ) + POSIX_OBJ=pcreposix.o + POSIX_LOBJ=pcreposix.lo + POSIX_LIB= + ON_WINDOWS= + NOT_ON_WINDOWS="#" + WIN_PREFIX= + ;; +cygwin* ) + ON_WINDOWS= + POSIX_OBJ=pcreposix.o + POSIX_LOBJ=pcreposix.lo + POSIX_LIB= + WIN_PREFIX=cyg + NOT_ON_WINDOWS="#" + ;; +* ) + ON_WINDOWS="#" + NOT_ON_WINDOWS= + POSIX_OBJ= + POSIX_LOBJ= + POSIX_LIB=libpcreposix.la + WIN_PREFIX= + ;; +esac + + + + + + + +if test "x$enable_shared" = "xno" ; then + cat >>confdefs.h <<\_ACEOF +#define PCRE_STATIC 1 +_ACEOF + +fi + + ac_config_files="$ac_config_files Makefile pcre.h:pcre.in pcre-config:pcre-config.in RunTest:RunTest.in" + ac_config_commands="$ac_config_commands default" +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, don't put newlines in cache variables' values. +# 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. +{ + (set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *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 \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} | + sed ' + t clear + : clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + : end' >>confcache +if diff $cache_file confcache >/dev/null 2>&1; then :; else + if test -w $cache_file; then + test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" + cat confcache >$cache_file + else + echo "not updating unwritable cache $cache_file" + 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}' + +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ 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[ ]*=/{ +s/:*\$(srcdir):*/:/; +s/:*\${srcdir}:*/:/; +s/:*@srcdir@:*/:/; +s/^\([^=]*=[ ]*\):*/\1/; +s/:*$//; +s/^[^=]*=[ ]*$//; +}' +fi + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_i=`echo "$ac_i" | + sed 's/\$U\././;s/\.o$//;s/\.obj$//'` + # 2. Add them. + ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" + ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + +: ${CONFIG_STATUS=./config.status} +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 +echo "$as_me: creating $CONFIG_STATUS" >&6;} +cat >$CONFIG_STATUS <<_ACEOF +#! $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} +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi + +# Support unset when possible. +if (FOO=FOO; unset FOO) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -n "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; 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 + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# 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 + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + 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 + + ;; + 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 + { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 +echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 +echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;} + { (exit 1); exit 1; }; } + + # 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 sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="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="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + +exec 6>&1 + +# Open the log real soon, to keep \$[0] and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. Logging --version etc. is OK. +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX +} >&5 +cat >&5 <<_CSEOF + +This file was extended by $as_me, which was +generated by GNU Autoconf 2.57. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +_CSEOF +echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 +echo >&5 +_ACEOF + +# Files that config.status was made for. +if test -n "$ac_config_files"; then + echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_headers"; then + echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_links"; then + echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_commands"; then + echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS +fi + +cat >>$CONFIG_STATUS <<\_ACEOF + +ac_cs_usage="\ +\`$as_me' instantiates files from templates according to the +current configuration. + +Usage: $0 [OPTIONS] [FILE]... + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet 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 + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration commands: +$config_commands + +Report bugs to ." +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +ac_cs_version="\\ +config.status +configured by $0, generated by GNU Autoconf 2.57, + with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" + +Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001 +Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." +srcdir=$srcdir +INSTALL="$INSTALL" +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If no file are specified by the user, then we need to provide default +# value. By we need to know if files were specified by the user. +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=$1 + ac_optarg=$2 + ac_shift=shift + ;; + *) # This is not an option, so the user has probably given explicit + # arguments. + ac_option=$1 + ac_need_defaults=false;; + esac + + case $ac_option in + # Handling of the options. +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --vers* | -V ) + echo "$ac_cs_version"; exit 0 ;; + --he | --h) + # Conflict between --help and --header + { { echo "$as_me:$LINENO: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; };; + --help | --hel | -h ) + echo "$ac_cs_usage"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + CONFIG_FILES="$CONFIG_FILES $ac_optarg" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" + ac_need_defaults=false;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; } ;; + + *) ac_config_targets="$ac_config_targets $1" ;; + + 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 +if \$ac_cs_recheck; then + echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 + exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion +fi + +_ACEOF + + + + + +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_config_target in $ac_config_targets +do + case "$ac_config_target" in + # Handling of arguments. + "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "pcre.h" ) CONFIG_FILES="$CONFIG_FILES pcre.h:pcre.in" ;; + "pcre-config" ) CONFIG_FILES="$CONFIG_FILES pcre-config:pcre-config.in" ;; + "RunTest" ) CONFIG_FILES="$CONFIG_FILES RunTest:RunTest.in" ;; + "default" ) CONFIG_COMMANDS="$CONFIG_COMMANDS default" ;; + "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h:config.in" ;; + *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 +echo "$as_me: error: invalid argument: $ac_config_target" >&2;} + { (exit 1); exit 1; }; };; + 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 + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason to put it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Create a temporary directory, and hook for its removal unless debugging. +$debug || +{ + trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 + trap '{ (exit 1); exit 1; }' 1 2 13 15 +} + +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=./confstat$$-$RANDOM + (umask 077 && mkdir $tmp) +} || +{ + echo "$me: cannot create a temporary directory in ." >&2 + { (exit 1); exit 1; } +} + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF + +# +# CONFIG_FILES section. +# + +# No need to generate the scripts if there are no CONFIG_FILES. +# This happens for instance when ./config.status config.h +if test -n "\$CONFIG_FILES"; then + # Protect against being on the right side of a sed subst in config.status. + sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g; + s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF +s,@SHELL@,$SHELL,;t t +s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t +s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t +s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t +s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t +s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t +s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t +s,@exec_prefix@,$exec_prefix,;t t +s,@prefix@,$prefix,;t t +s,@program_transform_name@,$program_transform_name,;t t +s,@bindir@,$bindir,;t t +s,@sbindir@,$sbindir,;t t +s,@libexecdir@,$libexecdir,;t t +s,@datadir@,$datadir,;t t +s,@sysconfdir@,$sysconfdir,;t t +s,@sharedstatedir@,$sharedstatedir,;t t +s,@localstatedir@,$localstatedir,;t t +s,@libdir@,$libdir,;t t +s,@includedir@,$includedir,;t t +s,@oldincludedir@,$oldincludedir,;t t +s,@infodir@,$infodir,;t t +s,@mandir@,$mandir,;t t +s,@build_alias@,$build_alias,;t t +s,@host_alias@,$host_alias,;t t +s,@target_alias@,$target_alias,;t t +s,@DEFS@,$DEFS,;t t +s,@ECHO_C@,$ECHO_C,;t t +s,@ECHO_N@,$ECHO_N,;t t +s,@ECHO_T@,$ECHO_T,;t t +s,@LIBS@,$LIBS,;t t +s,@CC@,$CC,;t t +s,@CFLAGS@,$CFLAGS,;t t +s,@LDFLAGS@,$LDFLAGS,;t t +s,@CPPFLAGS@,$CPPFLAGS,;t t +s,@ac_ct_CC@,$ac_ct_CC,;t t +s,@EXEEXT@,$EXEEXT,;t t +s,@OBJEXT@,$OBJEXT,;t t +s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t +s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t +s,@INSTALL_DATA@,$INSTALL_DATA,;t t +s,@build@,$build,;t t +s,@build_cpu@,$build_cpu,;t t +s,@build_vendor@,$build_vendor,;t t +s,@build_os@,$build_os,;t t +s,@host@,$host,;t t +s,@host_cpu@,$host_cpu,;t t +s,@host_vendor@,$host_vendor,;t t +s,@host_os@,$host_os,;t t +s,@LN_S@,$LN_S,;t t +s,@ECHO@,$ECHO,;t t +s,@RANLIB@,$RANLIB,;t t +s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t +s,@STRIP@,$STRIP,;t t +s,@ac_ct_STRIP@,$ac_ct_STRIP,;t t +s,@CPP@,$CPP,;t t +s,@EGREP@,$EGREP,;t t +s,@LIBTOOL@,$LIBTOOL,;t t +s,@BUILD_EXEEXT@,$BUILD_EXEEXT,;t t +s,@BUILD_OBJEXT@,$BUILD_OBJEXT,;t t +s,@CC_FOR_BUILD@,$CC_FOR_BUILD,;t t +s,@CFLAGS_FOR_BUILD@,$CFLAGS_FOR_BUILD,;t t +s,@HAVE_MEMMOVE@,$HAVE_MEMMOVE,;t t +s,@HAVE_STRERROR@,$HAVE_STRERROR,;t t +s,@LINK_SIZE@,$LINK_SIZE,;t t +s,@MATCH_LIMIT@,$MATCH_LIMIT,;t t +s,@NEWLINE@,$NEWLINE,;t t +s,@PCRE_MAJOR@,$PCRE_MAJOR,;t t +s,@PCRE_MINOR@,$PCRE_MINOR,;t t +s,@PCRE_DATE@,$PCRE_DATE,;t t +s,@PCRE_VERSION@,$PCRE_VERSION,;t t +s,@PCRE_LIB_VERSION@,$PCRE_LIB_VERSION,;t t +s,@PCRE_POSIXLIB_VERSION@,$PCRE_POSIXLIB_VERSION,;t t +s,@POSIX_MALLOC_THRESHOLD@,$POSIX_MALLOC_THRESHOLD,;t t +s,@UTF8@,$UTF8,;t t +s,@WIN_PREFIX@,$WIN_PREFIX,;t t +s,@ON_WINDOWS@,$ON_WINDOWS,;t t +s,@NOT_ON_WINDOWS@,$NOT_ON_WINDOWS,;t t +s,@POSIX_OBJ@,$POSIX_OBJ,;t t +s,@POSIX_LOBJ@,$POSIX_LOBJ,;t t +s,@POSIX_LIB@,$POSIX_LIB,;t t +s,@LIBOBJS@,$LIBOBJS,;t t +s,@LTLIBOBJS@,$LTLIBOBJS,;t t +CEOF + +_ACEOF + + cat >>$CONFIG_STATUS <<\_ACEOF + # Split the substitutions into bite-sized pieces for seds with + # small command number limits, like on Digital OSF/1 and HP-UX. + ac_max_sed_lines=48 + ac_sed_frag=1 # Number of current file. + ac_beg=1 # First line for current file. + ac_end=$ac_max_sed_lines # Line after last line for current file. + ac_more_lines=: + ac_sed_cmds= + while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + else + sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + fi + if test ! -s $tmp/subs.frag; then + ac_more_lines=false + else + # The purpose of the label and of the branching condition is to + # speed up the sed processing (if there are no `@' at all, there + # is no need to browse any of the substitutions). + # These are the two extra sed commands mentioned above. + (echo ':t + /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" + else + ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" + fi + ac_sed_frag=`expr $ac_sed_frag + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_lines` + fi + done + if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat + fi +fi # test -n "$CONFIG_FILES" + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; + esac + + # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. + ac_dir=`(dirname "$ac_file") 2>/dev/null || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac +# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be +# absolute. +ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd` +ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd` +ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd` +ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` + + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_builddir$INSTALL ;; + esac + + if test x"$ac_file" != x-; then + { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + rm -f "$ac_file" + fi + # 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. */ + if test x"$ac_file" = x-; then + configure_input= + else + configure_input="$ac_file. " + fi + configure_input=$configure_input"Generated from `echo $ac_file_in | + sed 's,.*/,,'` by configure." + + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + echo $f;; + *) # Relative + if test -f "$f"; then + # Build tree + echo $f + elif test -f "$srcdir/$f"; then + # Source tree + echo $srcdir/$f + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF + sed "$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s,@configure_input@,$configure_input,;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,@top_builddir@,$ac_top_builddir,;t t +s,@abs_top_builddir@,$ac_abs_top_builddir,;t t +s,@INSTALL@,$ac_INSTALL,;t t +" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out + rm -f $tmp/stdin + if test x"$ac_file" != x-; then + mv $tmp/out $ac_file + else + cat $tmp/out + rm -f $tmp/out + fi + +done +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + +# +# CONFIG_HEADER section. +# + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='[ ].*$,\1#\2' +ac_dC=' ' +ac_dD=',;t' +# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='$,\1#\2define\3' +ac_uC=' ' +ac_uD=',;t' + +for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; + esac + + test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + echo $f;; + *) # Relative + if test -f "$f"; then + # Build tree + echo $f + elif test -f "$srcdir/$f"; then + # Source tree + echo $srcdir/$f + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } + # Remove the trailing spaces. + sed 's/[ ]*$//' $ac_file_inputs >$tmp/in + +_ACEOF + +# Transform confdefs.h into two sed scripts, `conftest.defines' and +# `conftest.undefs', that substitutes the proper values into +# config.h.in to produce config.h. The first handles `#define' +# templates, and the second `#undef' templates. +# And first: Protect against being on the right side of a sed subst in +# config.status. Protect against being in an unquoted here document +# in config.status. +rm -f conftest.defines conftest.undefs +# Using a here document instead of a string reduces the quoting nightmare. +# Putting comments in sed scripts is not portable. +# +# `end' is used to avoid that the second main sed command (meant for +# 0-ary CPP macros) applies to n-ary macro definitions. +# See the Autoconf documentation for `clear'. +cat >confdef2sed.sed <<\_ACEOF +s/[\\&,]/\\&/g +s,[\\$`],\\&,g +t clear +: clear +s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp +t end +s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp +: end +_ACEOF +# If some macros were called several times there might be several times +# the same #defines, which is useless. Nevertheless, we may not want to +# sort them, since we want the *last* AC-DEFINE to be honored. +uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines +sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs +rm -f confdef2sed.sed + +# This sed command replaces #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +cat >>conftest.undefs <<\_ACEOF +s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */, +_ACEOF + +# Break up conftest.defines because some shells have a limit on the size +# of here documents, and old seds have small limits too (100 cmds). +echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS +echo ' if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS +echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS +echo ' :' >>$CONFIG_STATUS +rm -f conftest.tail +while grep . conftest.defines >/dev/null +do + # Write a limited-size here document to $tmp/defines.sed. + echo ' cat >$tmp/defines.sed <>$CONFIG_STATUS + # Speed up: don't consider the non `#define' lines. + echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS + # Work around the forget-to-reset-the-flag bug. + echo 't clr' >>$CONFIG_STATUS + echo ': clr' >>$CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS + echo 'CEOF + sed -f $tmp/defines.sed $tmp/in >$tmp/out + rm -f $tmp/in + mv $tmp/out $tmp/in +' >>$CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail + rm -f conftest.defines + mv conftest.tail conftest.defines +done +rm -f conftest.defines +echo ' fi # grep' >>$CONFIG_STATUS +echo >>$CONFIG_STATUS + +# Break up conftest.undefs because some shells have a limit on the size +# of here documents, and old seds have small limits too (100 cmds). +echo ' # Handle all the #undef templates' >>$CONFIG_STATUS +rm -f conftest.tail +while grep . conftest.undefs >/dev/null +do + # Write a limited-size here document to $tmp/undefs.sed. + echo ' cat >$tmp/undefs.sed <>$CONFIG_STATUS + # Speed up: don't consider the non `#undef' + echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS + # Work around the forget-to-reset-the-flag bug. + echo 't clr' >>$CONFIG_STATUS + echo ': clr' >>$CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS + echo 'CEOF + sed -f $tmp/undefs.sed $tmp/in >$tmp/out + rm -f $tmp/in + mv $tmp/out $tmp/in +' >>$CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail + rm -f conftest.undefs + mv conftest.tail conftest.undefs +done +rm -f conftest.undefs + +cat >>$CONFIG_STATUS <<\_ACEOF + # 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. */ + if test x"$ac_file" = x-; then + echo "/* Generated by configure. */" >$tmp/config.h + else + echo "/* $ac_file. Generated by configure. */" >$tmp/config.h + fi + cat $tmp/in >>$tmp/config.h + rm -f $tmp/in + if test x"$ac_file" != x-; then + if diff $ac_file $tmp/config.h >/dev/null 2>&1; then + { echo "$as_me:$LINENO: $ac_file is unchanged" >&5 +echo "$as_me: $ac_file is unchanged" >&6;} + else + ac_dir=`(dirname "$ac_file") 2>/dev/null || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + rm -f $ac_file + mv $tmp/config.h $ac_file + fi + else + cat $tmp/config.h + rm -f $tmp/config.h + fi +done +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + +# +# CONFIG_COMMANDS section. +# +for ac_file in : $CONFIG_COMMANDS; do test "x$ac_file" = x: && continue + ac_dest=`echo "$ac_file" | sed 's,:.*,,'` + ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_dir=`(dirname "$ac_dest") 2>/dev/null || +$as_expr X"$ac_dest" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_dest" : 'X\(//\)[^/]' \| \ + X"$ac_dest" : 'X\(//\)$' \| \ + X"$ac_dest" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_dest" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac +# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be +# absolute. +ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd` +ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd` +ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd` +ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` + + + { echo "$as_me:$LINENO: executing $ac_dest commands" >&5 +echo "$as_me: executing $ac_dest commands" >&6;} + case $ac_dest in + default ) chmod a+x RunTest pcre-config ;; + esac +done +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF + +{ (exit 0); exit 0; } +_ACEOF +chmod +x $CONFIG_STATUS +ac_clean_files=$ac_clean_files_save + + +# 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 || { (exit 1); exit 1; } +fi + diff --git a/lc-continuity/mk4/continuity/pcre/configure.in b/lc-continuity/mk4/continuity/pcre/configure.in new file mode 100644 index 0000000000000000000000000000000000000000..5394f4f1ed6142f6de167d7c4366fd2bd7b41d0d --- /dev/null +++ b/lc-continuity/mk4/continuity/pcre/configure.in @@ -0,0 +1,189 @@ +dnl Process this file with autoconf to produce a configure script. + +dnl This is required at the start; the name is the name of a file +dnl it should be seeing, to verify it is in the same directory. + +AC_INIT(dftables.c) + +dnl A safety precaution + +AC_PREREQ(2.57) + +dnl Arrange to build config.h from config.in. Note that pcre.h is +dnl built differently, as it is just a "substitution" file. +dnl Manual says this macro should come right after AC_INIT. +AC_CONFIG_HEADER(config.h:config.in) + +dnl Provide the current PCRE version information. Do not use numbers +dnl with leading zeros for the minor version, as they end up in a C +dnl macro, and may be treated as octal constants. Stick to single +dnl digits for minor numbers less than 10. There are unlikely to be +dnl that many releases anyway. + +PCRE_MAJOR=4 +PCRE_MINOR=3 +PCRE_DATE=21-May-2003 +PCRE_VERSION=${PCRE_MAJOR}.${PCRE_MINOR} + +dnl Default values for miscellaneous macros + +POSIX_MALLOC_THRESHOLD=-DPOSIX_MALLOC_THRESHOLD=10 + +dnl Provide versioning information for libtool shared libraries that +dnl are built by default on Unix systems. + +PCRE_LIB_VERSION=0:1:0 +PCRE_POSIXLIB_VERSION=0:0:0 + +dnl Checks for programs. + +AC_PROG_CC +AC_PROG_INSTALL +AC_LIBTOOL_WIN32_DLL +AC_PROG_LIBTOOL + +dnl We need to find a compiler for compiling a program to run on the local host +dnl while building. It needs to be different from CC when cross-compiling. +dnl There is a macro called AC_PROG_CC_FOR_BUILD in the GNU archive for +dnl figuring this out automatically. Unfortunately, it does not work with the +dnl latest versions of autoconf. So for the moment, we just default to the +dnl same values as the "main" compiler. People who are corss-compiling will +dnl just have to adjust the Makefile by hand or set these values when they +dnl run "configure". + +CC_FOR_BUILD=${CC_FOR_BUILD:-'$(CC)'} +CFLAGS_FOR_BUILD=${CFLAGS_FOR_BUILD:-'$(CFLAGS)'} +BUILD_EXEEXT=${BUILD_EXEEXT:-'$(EXEEXT)'} +BUILD_OBJEXT=${BUILD_OBJEXT:-'$(OBJEXT)'} + +dnl Checks for header files. + +AC_HEADER_STDC +AC_CHECK_HEADERS(limits.h) + +dnl Checks for typedefs, structures, and compiler characteristics. + +AC_C_CONST +AC_TYPE_SIZE_T + +dnl Checks for library functions. + +AC_CHECK_FUNCS(bcopy memmove strerror) + +dnl Handle --enable-utf8 + +AC_ARG_ENABLE(utf8, +[ --enable-utf8 enable UTF8 support], +if test "$enableval" = "yes"; then + UTF8=-DSUPPORT_UTF8 +fi +) + +dnl Handle --enable-newline-is-cr + +AC_ARG_ENABLE(newline-is-cr, +[ --enable-newline-is-cr use CR as the newline character], +if test "$enableval" = "yes"; then + NEWLINE=-DNEWLINE=13 +fi +) + +dnl Handle --enable-newline-is-lf + +AC_ARG_ENABLE(newline-is-lf, +[ --enable-newline-is-lf use LF as the newline character], +if test "$enableval" = "yes"; then + NEWLINE=-DNEWLINE=10 +fi +) + +dnl There doesn't seem to be a straightforward way of having parameters +dnl that set values, other than fudging the --with thing. So that's what +dnl I've done. + +dnl Handle --with-posix-malloc-threshold=n + +AC_ARG_WITH(posix-malloc-threshold, +[ --with-posix-malloc-threshold=5 threshold for POSIX malloc usage], + POSIX_MALLOC_THRESHOLD=-DPOSIX_MALLOC_THRESHOLD=$withval +) + +dnl Handle --with-link-size=n + +AC_ARG_WITH(link-size, +[ --with-link-size=2 internal link size (2, 3, or 4 allowed)], + LINK_SIZE=-DLINK_SIZE=$withval +) + +dnl Handle --with-match_limit=n + +AC_ARG_WITH(match-limit, +[ --with-match-limit=10000000 default limit on internal looping)], + MATCH_LIMIT=-DMATCH_LIMIT=$withval +) + +dnl Now arrange to build libtool + +AC_PROG_LIBTOOL + +dnl "Export" these variables + +AC_SUBST(BUILD_EXEEXT) +AC_SUBST(BUILD_OBJEXT) +AC_SUBST(CC_FOR_BUILD) +AC_SUBST(CFLAGS_FOR_BUILD) +AC_SUBST(HAVE_MEMMOVE) +AC_SUBST(HAVE_STRERROR) +AC_SUBST(LINK_SIZE) +AC_SUBST(MATCH_LIMIT) +AC_SUBST(NEWLINE) +AC_SUBST(PCRE_MAJOR) +AC_SUBST(PCRE_MINOR) +AC_SUBST(PCRE_DATE) +AC_SUBST(PCRE_VERSION) +AC_SUBST(PCRE_LIB_VERSION) +AC_SUBST(PCRE_POSIXLIB_VERSION) +AC_SUBST(POSIX_MALLOC_THRESHOLD) +AC_SUBST(UTF8) + +dnl Stuff to make Win32 work better + +case $host_os in +mingw* ) + POSIX_OBJ=pcreposix.o + POSIX_LOBJ=pcreposix.lo + POSIX_LIB= + ON_WINDOWS= + NOT_ON_WINDOWS="#" + WIN_PREFIX= + ;; +cygwin* ) + ON_WINDOWS= + POSIX_OBJ=pcreposix.o + POSIX_LOBJ=pcreposix.lo + POSIX_LIB= + WIN_PREFIX=cyg + NOT_ON_WINDOWS="#" + ;; +* ) + ON_WINDOWS="#" + NOT_ON_WINDOWS= + POSIX_OBJ= + POSIX_LOBJ= + POSIX_LIB=libpcreposix.la + WIN_PREFIX= + ;; +esac +AC_SUBST(WIN_PREFIX) +AC_SUBST(ON_WINDOWS) +AC_SUBST(NOT_ON_WINDOWS) +AC_SUBST(POSIX_OBJ) +AC_SUBST(POSIX_LOBJ) +AC_SUBST(POSIX_LIB) + +if test "x$enable_shared" = "xno" ; then + AC_DEFINE(PCRE_STATIC,1) +fi + +dnl This must be last; it determines what files are written as well as config.h +AC_OUTPUT(Makefile pcre.h:pcre.in pcre-config:pcre-config.in RunTest:RunTest.in,[chmod a+x RunTest pcre-config]) diff --git a/lc-continuity/mk4/continuity/pcre/dftables.c b/lc-continuity/mk4/continuity/pcre/dftables.c new file mode 100644 index 0000000000000000000000000000000000000000..9aa7b77e2792e1a2495d46614261996404cf140d --- /dev/null +++ b/lc-continuity/mk4/continuity/pcre/dftables.c @@ -0,0 +1,152 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* +PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + +Written by: Philip Hazel + + Copyright (c) 1997-2001 University of Cambridge + +----------------------------------------------------------------------------- +Permission is granted to anyone to use this software for any purpose on any +computer system, and to redistribute it freely, subject to the following +restrictions: + +1. This software 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. + +2. The origin of this software must not be misrepresented, either by + explicit claim or by omission. + +3. Altered versions must be plainly marked as such, and must not be + misrepresented as being the original software. + +4. If PCRE is embedded in any software that is released under the GNU + General Purpose Licence (GPL), then the terms of that licence shall + supersede any condition above with which it is incompatible. +----------------------------------------------------------------------------- + +See the file Tech.Notes for some information on the internals. +*/ + + +/* This is a support program to generate the file chartables.c, containing +character tables of various kinds. They are built according to the default C +locale and used as the default tables by PCRE. Now that pcre_maketables is +a function visible to the outside world, we make use of its code from here in +order to be consistent. */ + +#include +#include +#include + +#include "internal.h" + +#define DFTABLES /* maketables.c notices this */ +#include "maketables.c" + + +int main(void) +{ +int i; +const unsigned char *tables = pcre_maketables(); + +/* There are two printf() calls here, because gcc in pedantic mode complains +about the very long string otherwise. */ + +printf( + "/*************************************************\n" + "* Perl-Compatible Regular Expressions *\n" + "*************************************************/\n\n" + "/* This file is automatically written by the dftables auxiliary \n" + "program. If you edit it by hand, you might like to edit the Makefile to \n" + "prevent its ever being regenerated.\n\n"); +printf( + "This file is #included in the compilation of pcre.c to build the default\n" + "character tables which are used when no tables are passed to the compile\n" + "function. */\n\n" + "static unsigned char pcre_default_tables[] = {\n\n" + "/* This table is a lower casing table. */\n\n"); + +printf(" "); +for (i = 0; i < 256; i++) + { + if ((i & 7) == 0 && i != 0) printf("\n "); + printf("%3d", *tables++); + if (i != 255) printf(","); + } +printf(",\n\n"); + +printf("/* This table is a case flipping table. */\n\n"); + +printf(" "); +for (i = 0; i < 256; i++) + { + if ((i & 7) == 0 && i != 0) printf("\n "); + printf("%3d", *tables++); + if (i != 255) printf(","); + } +printf(",\n\n"); + +printf( + "/* This table contains bit maps for various character classes.\n" + "Each map is 32 bytes long and the bits run from the least\n" + "significant end of each byte. The classes that have their own\n" + "maps are: space, xdigit, digit, upper, lower, word, graph\n" + "print, punct, and cntrl. Other classes are built from combinations. */\n\n"); + +printf(" "); +for (i = 0; i < cbit_length; i++) + { + if ((i & 7) == 0 && i != 0) + { + if ((i & 31) == 0) printf("\n"); + printf("\n "); + } + printf("0x%02x", *tables++); + if (i != cbit_length - 1) printf(","); + } +printf(",\n\n"); + +printf( + "/* This table identifies various classes of character by individual bits:\n" + " 0x%02x white space character\n" + " 0x%02x letter\n" + " 0x%02x decimal digit\n" + " 0x%02x hexadecimal digit\n" + " 0x%02x alphanumeric or '_'\n" + " 0x%02x regular expression metacharacter or binary zero\n*/\n\n", + ctype_space, ctype_letter, ctype_digit, ctype_xdigit, ctype_word, + ctype_meta); + +printf(" "); +for (i = 0; i < 256; i++) + { + if ((i & 7) == 0 && i != 0) + { + printf(" /* "); + if (isprint(i-8)) printf(" %c -", i-8); + else printf("%3d-", i-8); + if (isprint(i-1)) printf(" %c ", i-1); + else printf("%3d", i-1); + printf(" */\n "); + } + printf("0x%02x", *tables++); + if (i != 255) printf(","); + } + +printf("};/* "); +if (isprint(i-8)) printf(" %c -", i-8); + else printf("%3d-", i-8); +if (isprint(i-1)) printf(" %c ", i-1); + else printf("%3d", i-1); +printf(" */\n\n/* End of chartables.c */\n"); + +return 0; +} + +/* End of dftables.c */ diff --git a/lc-continuity/mk4/continuity/pcre/get.c b/lc-continuity/mk4/continuity/pcre/get.c new file mode 100644 index 0000000000000000000000000000000000000000..a20473cf24e94e0f8a978be47a0206a29690ea27 --- /dev/null +++ b/lc-continuity/mk4/continuity/pcre/get.c @@ -0,0 +1,349 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* +This is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. See +the file Tech.Notes for some information on the internals. + +Written by: Philip Hazel + + Copyright (c) 1997-2003 University of Cambridge + +----------------------------------------------------------------------------- +Permission is granted to anyone to use this software for any purpose on any +computer system, and to redistribute it freely, subject to the following +restrictions: + +1. This software 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. + +2. The origin of this software must not be misrepresented, either by + explicit claim or by omission. + +3. Altered versions must be plainly marked as such, and must not be + misrepresented as being the original software. + +4. If PCRE is embedded in any software that is released under the GNU + General Purpose Licence (GPL), then the terms of that licence shall + supersede any condition above with which it is incompatible. +----------------------------------------------------------------------------- +*/ + +/* This module contains some convenience functions for extracting substrings +from the subject string after a regex match has succeeded. The original idea +for these functions came from Scott Wimer . */ + + +/* Include the internals header, which itself includes Standard C headers plus +the external pcre header. */ + +#include "internal.h" + + +/************************************************* +* Find number for named string * +*************************************************/ + +/* This function is used by the two extraction functions below, as well +as being generally available. + +Arguments: + code the compiled regex + stringname the name whose number is required + +Returns: the number of the named parentheses, or a negative number + (PCRE_ERROR_NOSUBSTRING) if not found +*/ + +int +pcre_get_stringnumber(const pcre *code, const char *stringname) +{ +int rc; +int entrysize; +int top, bot; +uschar *nametable; + +if ((rc = pcre_fullinfo(code, NULL, PCRE_INFO_NAMECOUNT, &top)) != 0) + return rc; +if (top <= 0) return PCRE_ERROR_NOSUBSTRING; + +if ((rc = pcre_fullinfo(code, NULL, PCRE_INFO_NAMEENTRYSIZE, &entrysize)) != 0) + return rc; +if ((rc = pcre_fullinfo(code, NULL, PCRE_INFO_NAMETABLE, &nametable)) != 0) + return rc; + +bot = 0; +while (top > bot) + { + int mid = (top + bot) / 2; + uschar *entry = nametable + entrysize*mid; + int c = strcmp(stringname, (char *)(entry + 2)); + if (c == 0) return (entry[0] << 8) + entry[1]; + if (c > 0) bot = mid + 1; else top = mid; + } + +return PCRE_ERROR_NOSUBSTRING; +} + + + +/************************************************* +* Copy captured string to given buffer * +*************************************************/ + +/* This function copies a single captured substring into a given buffer. +Note that we use memcpy() rather than strncpy() in case there are binary zeros +in the string. + +Arguments: + subject the subject string that was matched + ovector pointer to the offsets table + stringcount the number of substrings that were captured + (i.e. the yield of the pcre_exec call, unless + that was zero, in which case it should be 1/3 + of the offset table size) + stringnumber the number of the required substring + buffer where to put the substring + size the size of the buffer + +Returns: if successful: + the length of the copied string, not including the zero + that is put on the end; can be zero + if not successful: + PCRE_ERROR_NOMEMORY (-6) buffer too small + PCRE_ERROR_NOSUBSTRING (-7) no such captured substring +*/ + +int +pcre_copy_substring(const char *subject, int *ovector, int stringcount, + int stringnumber, char *buffer, int size) +{ +int yield; +if (stringnumber < 0 || stringnumber >= stringcount) + return PCRE_ERROR_NOSUBSTRING; +stringnumber *= 2; +yield = ovector[stringnumber+1] - ovector[stringnumber]; +if (size < yield + 1) return PCRE_ERROR_NOMEMORY; +memcpy(buffer, subject + ovector[stringnumber], yield); +buffer[yield] = 0; +return yield; +} + + + +/************************************************* +* Copy named captured string to given buffer * +*************************************************/ + +/* This function copies a single captured substring into a given buffer, +identifying it by name. + +Arguments: + code the compiled regex + subject the subject string that was matched + ovector pointer to the offsets table + stringcount the number of substrings that were captured + (i.e. the yield of the pcre_exec call, unless + that was zero, in which case it should be 1/3 + of the offset table size) + stringname the name of the required substring + buffer where to put the substring + size the size of the buffer + +Returns: if successful: + the length of the copied string, not including the zero + that is put on the end; can be zero + if not successful: + PCRE_ERROR_NOMEMORY (-6) buffer too small + PCRE_ERROR_NOSUBSTRING (-7) no such captured substring +*/ + +int +pcre_copy_named_substring(const pcre *code, const char *subject, int *ovector, + int stringcount, const char *stringname, char *buffer, int size) +{ +int n = pcre_get_stringnumber(code, stringname); +if (n <= 0) return n; +return pcre_copy_substring(subject, ovector, stringcount, n, buffer, size); +} + + + +/************************************************* +* Copy all captured strings to new store * +*************************************************/ + +/* This function gets one chunk of store and builds a list of pointers and all +of the captured substrings in it. A NULL pointer is put on the end of the list. + +Arguments: + subject the subject string that was matched + ovector pointer to the offsets table + stringcount the number of substrings that were captured + (i.e. the yield of the pcre_exec call, unless + that was zero, in which case it should be 1/3 + of the offset table size) + listptr set to point to the list of pointers + +Returns: if successful: 0 + if not successful: + PCRE_ERROR_NOMEMORY (-6) failed to get store +*/ + +int +pcre_get_substring_list(const char *subject, int *ovector, int stringcount, + const char ***listptr) +{ +int i; +int size = sizeof(char *); +int double_count = stringcount * 2; +char **stringlist; +char *p; + +for (i = 0; i < double_count; i += 2) + size += sizeof(char *) + ovector[i+1] - ovector[i] + 1; + +stringlist = (char **)(pcre_malloc)(size); +if (stringlist == NULL) return PCRE_ERROR_NOMEMORY; + +*listptr = (const char **)stringlist; +p = (char *)(stringlist + stringcount + 1); + +for (i = 0; i < double_count; i += 2) + { + int len = ovector[i+1] - ovector[i]; + memcpy(p, subject + ovector[i], len); + *stringlist++ = p; + p += len; + *p++ = 0; + } + +*stringlist = NULL; +return 0; +} + + + +/************************************************* +* Free store obtained by get_substring_list * +*************************************************/ + +/* This function exists for the benefit of people calling PCRE from non-C +programs that can call its functions, but not free() or (pcre_free)() directly. + +Argument: the result of a previous pcre_get_substring_list() +Returns: nothing +*/ + +void +pcre_free_substring_list(const char **pointer) +{ +(pcre_free)((void *)pointer); +} + + + +/************************************************* +* Copy captured string to new store * +*************************************************/ + +/* This function copies a single captured substring into a piece of new +store + +Arguments: + subject the subject string that was matched + ovector pointer to the offsets table + stringcount the number of substrings that were captured + (i.e. the yield of the pcre_exec call, unless + that was zero, in which case it should be 1/3 + of the offset table size) + stringnumber the number of the required substring + stringptr where to put a pointer to the substring + +Returns: if successful: + the length of the string, not including the zero that + is put on the end; can be zero + if not successful: + PCRE_ERROR_NOMEMORY (-6) failed to get store + PCRE_ERROR_NOSUBSTRING (-7) substring not present +*/ + +int +pcre_get_substring(const char *subject, int *ovector, int stringcount, + int stringnumber, const char **stringptr) +{ +int yield; +char *substring; +if (stringnumber < 0 || stringnumber >= stringcount) + return PCRE_ERROR_NOSUBSTRING; +stringnumber *= 2; +yield = ovector[stringnumber+1] - ovector[stringnumber]; +substring = (char *)(pcre_malloc)(yield + 1); +if (substring == NULL) return PCRE_ERROR_NOMEMORY; +memcpy(substring, subject + ovector[stringnumber], yield); +substring[yield] = 0; +*stringptr = substring; +return yield; +} + + + +/************************************************* +* Copy named captured string to new store * +*************************************************/ + +/* This function copies a single captured substring, identified by name, into +new store. + +Arguments: + code the compiled regex + subject the subject string that was matched + ovector pointer to the offsets table + stringcount the number of substrings that were captured + (i.e. the yield of the pcre_exec call, unless + that was zero, in which case it should be 1/3 + of the offset table size) + stringname the name of the required substring + stringptr where to put the pointer + +Returns: if successful: + the length of the copied string, not including the zero + that is put on the end; can be zero + if not successful: + PCRE_ERROR_NOMEMORY (-6) couldn't get memory + PCRE_ERROR_NOSUBSTRING (-7) no such captured substring +*/ + +int +pcre_get_named_substring(const pcre *code, const char *subject, int *ovector, + int stringcount, const char *stringname, const char **stringptr) +{ +int n = pcre_get_stringnumber(code, stringname); +if (n <= 0) return n; +return pcre_get_substring(subject, ovector, stringcount, n, stringptr); +} + + + + +/************************************************* +* Free store obtained by get_substring * +*************************************************/ + +/* This function exists for the benefit of people calling PCRE from non-C +programs that can call its functions, but not free() or (pcre_free)() directly. + +Argument: the result of a previous pcre_get_substring() +Returns: nothing +*/ + +void +pcre_free_substring(const char *pointer) +{ +(pcre_free)((void *)pointer); +} + +/* End of get.c */ diff --git a/lc-continuity/mk4/continuity/pcre/install-sh b/lc-continuity/mk4/continuity/pcre/install-sh new file mode 100644 index 0000000000000000000000000000000000000000..e9de23842dcd44d2953129c866b1ad25f7e1f1d9 --- /dev/null +++ b/lc-continuity/mk4/continuity/pcre/install-sh @@ -0,0 +1,251 @@ +#!/bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5 (mit/util/scripts/install.sh). +# +# Copyright 1991 by the Massachusetts Institute of Technology +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation, and that the name of M.I.T. not be used in advertising or +# publicity pertaining to distribution of the software without specific, +# written prior permission. M.I.T. makes no representations about the +# suitability of this software for any purpose. It is provided "as is" +# without express or implied warranty. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +transformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +else + true +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d $dst ]; then + instcmd=: + chmodcmd="" + else + instcmd=mkdir + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f $src -o -d $src ] + then + true + else + echo "install: $src does not exist" + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "install: no destination specified" + exit 1 + else + true + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d $dst ] + then + dst="$dst"/`basename $src` + else + true + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' +' +IFS="${IFS-${defaultIFS}}" + +oIFS="${IFS}" +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS="${oIFS}" + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp="${pathcomp}${1}" + shift + + if [ ! -d "${pathcomp}" ] ; + then + $mkdirprog "${pathcomp}" + else + true + fi + + pathcomp="${pathcomp}/" +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd $dst && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename $dst` + else + dstfile=`basename $dst $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename $dst` + else + true + fi + +# Make a temp file name in the proper directory. + + dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + + $doit $instcmd $src $dsttmp && + + trap "rm -f ${dsttmp}" 0 && + +# and set any options; do chmod last to preserve setuid bits + +# If any of these fail, we abort the whole thing. If we want to +# ignore errors from any of these, just make sure not to ignore +# errors from the above "$doit $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && + +# Now rename the file to the real destination. + + $doit $rmcmd -f $dstdir/$dstfile && + $doit $mvcmd $dsttmp $dstdir/$dstfile + +fi && + + +exit 0 diff --git a/lc-continuity/mk4/continuity/pcre/internal.h b/lc-continuity/mk4/continuity/pcre/internal.h new file mode 100644 index 0000000000000000000000000000000000000000..973e7eecdf998cc88a6c85d1ee6fa68f6cb6ee59 --- /dev/null +++ b/lc-continuity/mk4/continuity/pcre/internal.h @@ -0,0 +1,662 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + + +/* This is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. See +the file Tech.Notes for some information on the internals. + +Written by: Philip Hazel + + Copyright (c) 1997-2003 University of Cambridge + +----------------------------------------------------------------------------- +Permission is granted to anyone to use this software for any purpose on any +computer system, and to redistribute it freely, subject to the following +restrictions: + +1. This software 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. + +2. The origin of this software must not be misrepresented, either by + explicit claim or by omission. + +3. Altered versions must be plainly marked as such, and must not be + misrepresented as being the original software. + +4. If PCRE is embedded in any software that is released under the GNU + General Purpose Licence (GPL), then the terms of that licence shall + supersede any condition above with which it is incompatible. +----------------------------------------------------------------------------- +*/ + +/* This header contains definitions that are shared between the different +modules, but which are not relevant to the outside. */ + +/* Get the definitions provided by running "configure" */ + +#include "config.h" + +/* When compiling for use with the Virtual Pascal compiler, these functions +need to have their names changed. PCRE must be compiled with the -DVPCOMPAT +option on the command line. */ + +#ifdef VPCOMPAT +#define strncmp(s1,s2,m) _strncmp(s1,s2,m) +#define memcpy(d,s,n) _memcpy(d,s,n) +#define memmove(d,s,n) _memmove(d,s,n) +#define memset(s,c,n) _memset(s,c,n) +#else /* VPCOMPAT */ + +/* To cope with SunOS4 and other systems that lack memmove() but have bcopy(), +define a macro for memmove() if HAVE_MEMMOVE is false, provided that HAVE_BCOPY +is set. Otherwise, include an emulating function for those systems that have +neither (there some non-Unix environments where this is the case). This assumes +that all calls to memmove are moving strings upwards in store, which is the +case in PCRE. */ + +#if ! HAVE_MEMMOVE +#undef memmove /* some systems may have a macro */ +#if HAVE_BCOPY +#define memmove(a, b, c) bcopy(b, a, c) +#else /* HAVE_BCOPY */ +void * +pcre_memmove(unsigned char *dest, const unsigned char *src, size_t n) +{ +int i; +dest += n; +src += n; +for (i = 0; i < n; ++i) *(--dest) = *(--src); +} +#define memmove(a, b, c) pcre_memmove(a, b, c) +#endif /* not HAVE_BCOPY */ +#endif /* not HAVE_MEMMOVE */ +#endif /* not VPCOMPAT */ + + +/* PCRE keeps offsets in its compiled code as 2-byte quantities by default. +These are used, for example, to link from the start of a subpattern to its +alternatives and its end. The use of 2 bytes per offset limits the size of the +compiled regex to around 64K, which is big enough for almost everybody. +However, I received a request for an even bigger limit. For this reason, and +also to make the code easier to maintain, the storing and loading of offsets +from the byte string is now handled by the macros that are defined here. + +The macros are controlled by the value of LINK_SIZE. This defaults to 2 in +the config.h file, but can be overridden by using -D on the command line. This +is automated on Unix systems via the "configure" command. */ + +#if LINK_SIZE == 2 + +#define PUT(a,n,d) \ + (a[n] = (d) >> 8), \ + (a[(n)+1] = (d) & 255) + +#define GET(a,n) \ + (((a)[n] << 8) | (a)[(n)+1]) + +#define MAX_PATTERN_SIZE (1 << 16) + + +#elif LINK_SIZE == 3 + +#define PUT(a,n,d) \ + (a[n] = (d) >> 16), \ + (a[(n)+1] = (d) >> 8), \ + (a[(n)+2] = (d) & 255) + +#define GET(a,n) \ + (((a)[n] << 16) | ((a)[(n)+1] << 8) | (a)[(n)+2]) + +#define MAX_PATTERN_SIZE (1 << 24) + + +#elif LINK_SIZE == 4 + +#define PUT(a,n,d) \ + (a[n] = (d) >> 24), \ + (a[(n)+1] = (d) >> 16), \ + (a[(n)+2] = (d) >> 8), \ + (a[(n)+3] = (d) & 255) + +#define GET(a,n) \ + (((a)[n] << 24) | ((a)[(n)+1] << 16) | ((a)[(n)+2] << 8) | (a)[(n)+3]) + +#define MAX_PATTERN_SIZE (1 << 30) /* Keep it positive */ + + +#else +#error LINK_SIZE must be either 2, 3, or 4 +#endif + + +/* Convenience macro defined in terms of the others */ + +#define PUTINC(a,n,d) PUT(a,n,d), a += LINK_SIZE + + +/* PCRE uses some other 2-byte quantities that do not change when the size of +offsets changes. There are used for repeat counts and for other things such as +capturing parenthesis numbers in back references. */ + +#define PUT2(a,n,d) \ + a[n] = (d) >> 8; \ + a[(n)+1] = (d) & 255 + +#define GET2(a,n) \ + (((a)[n] << 8) | (a)[(n)+1]) + +#define PUT2INC(a,n,d) PUT2(a,n,d), a += 2 + + +/* Standard C headers plus the external interface definition */ + +#include +#include +#include +#include +#include +#include + +#ifndef PCRE_SPY +#define PCRE_DEFINITION /* Win32 __declspec(export) trigger for .dll */ +#endif + +#include "pcre.h" + +/* In case there is no definition of offsetof() provided - though any proper +Standard C system should have one. */ + +#ifndef offsetof +#define offsetof(p_type,field) ((size_t)&(((p_type *)0)->field)) +#endif + +/* These are the public options that can change during matching. */ + +#define PCRE_IMS (PCRE_CASELESS|PCRE_MULTILINE|PCRE_DOTALL) + +/* Private options flags start at the most significant end of the four bytes, +but skip the top bit so we can use ints for convenience without getting tangled +with negative values. The public options defined in pcre.h start at the least +significant end. Make sure they don't overlap, though now that we have expanded +to four bytes there is plenty of space. */ + +#define PCRE_FIRSTSET 0x40000000 /* first_byte is set */ +#define PCRE_REQCHSET 0x20000000 /* req_byte is set */ +#define PCRE_STARTLINE 0x10000000 /* start after \n for multiline */ +#define PCRE_ICHANGED 0x08000000 /* i option changes within regex */ + +/* Options for the "extra" block produced by pcre_study(). */ + +#define PCRE_STUDY_MAPPED 0x01 /* a map of starting chars exists */ + +/* Masks for identifying the public options which are permitted at compile +time, run time or study time, respectively. */ + +#define PUBLIC_OPTIONS \ + (PCRE_CASELESS|PCRE_EXTENDED|PCRE_ANCHORED|PCRE_MULTILINE| \ + PCRE_DOTALL|PCRE_DOLLAR_ENDONLY|PCRE_EXTRA|PCRE_UNGREEDY|PCRE_UTF8| \ + PCRE_NO_AUTO_CAPTURE) + +#define PUBLIC_EXEC_OPTIONS \ + (PCRE_ANCHORED|PCRE_NOTBOL|PCRE_NOTEOL|PCRE_NOTEMPTY) + +#define PUBLIC_STUDY_OPTIONS 0 /* None defined */ + +/* Magic number to provide a small check against being handed junk. */ + +#define MAGIC_NUMBER 0x50435245UL /* 'PCRE' */ + +/* Negative values for the firstchar and reqchar variables */ + +#define REQ_UNSET (-2) +#define REQ_NONE (-1) + +/* Flags added to firstbyte or reqbyte; a "non-literal" item is either a +variable-length repeat, or a anything other than literal characters. */ + +#define REQ_CASELESS 0x0100 /* indicates caselessness */ +#define REQ_VARY 0x0200 /* reqbyte followed non-literal item */ + +/* Miscellaneous definitions */ + +typedef int BOOL; + +#define FALSE 0 +#define TRUE 1 + +/* Escape items that are just an encoding of a particular data value. Note that +ESC_n is defined as yet another macro, which is set in config.h to either \n +(the default) or \r (which some people want). */ + +#ifndef ESC_e +#define ESC_e 27 +#endif + +#ifndef ESC_f +#define ESC_f '\f' +#endif + +#ifndef ESC_n +#define ESC_n NEWLINE +#endif + +#ifndef ESC_r +#define ESC_r '\r' +#endif + +/* We can't officially use ESC_t because it is a POSIX reserved identifier +(presumably because of all the others like size_t). */ + +#ifndef ESC_tee +#define ESC_tee '\t' +#endif + +/* These are escaped items that aren't just an encoding of a particular data +value such as \n. They must have non-zero values, as check_escape() returns +their negation. Also, they must appear in the same order as in the opcode +definitions below, up to ESC_z. There's a dummy for OP_ANY because it +corresponds to "." rather than an escape sequence. The final one must be +ESC_REF as subsequent values are used for \1, \2, \3, etc. There is are two +tests in the code for an escape greater than ESC_b and less than ESC_Z to +detect the types that may be repeated. These are the types that consume a +character. If any new escapes are put in between that don't consume a +character, that code will have to change. */ + +enum { ESC_A = 1, ESC_G, ESC_B, ESC_b, ESC_D, ESC_d, ESC_S, ESC_s, ESC_W, + ESC_w, ESC_dum1, ESC_C, ESC_Z, ESC_z, ESC_E, ESC_Q, ESC_REF }; + +/* Flag bits and data types for the extended class (OP_XCLASS) for classes that +contain UTF-8 characters with values greater than 255. */ + +#define XCL_NOT 0x01 /* Flag: this is a negative class */ +#define XCL_MAP 0x02 /* Flag: a 32-byte map is present */ + +#define XCL_END 0 /* Marks end of individual items */ +#define XCL_SINGLE 1 /* Single item (one multibyte char) follows */ +#define XCL_RANGE 2 /* A range (two multibyte chars) follows */ + + +/* Opcode table: OP_BRA must be last, as all values >= it are used for brackets +that extract substrings. Starting from 1 (i.e. after OP_END), the values up to +OP_EOD must correspond in order to the list of escapes immediately above. +Note that whenever this list is updated, the two macro definitions that follow +must also be updated to match. */ + +enum { + OP_END, /* 0 End of pattern */ + + /* Values corresponding to backslashed metacharacters */ + + OP_SOD, /* 1 Start of data: \A */ + OP_SOM, /* 2 Start of match (subject + offset): \G */ + OP_NOT_WORD_BOUNDARY, /* 3 \B */ + OP_WORD_BOUNDARY, /* 4 \b */ + OP_NOT_DIGIT, /* 5 \D */ + OP_DIGIT, /* 6 \d */ + OP_NOT_WHITESPACE, /* 7 \S */ + OP_WHITESPACE, /* 8 \s */ + OP_NOT_WORDCHAR, /* 9 \W */ + OP_WORDCHAR, /* 10 \w */ + OP_ANY, /* 11 Match any character */ + OP_ANYBYTE, /* 12 Match any byte (\C); different to OP_ANY for UTF-8 */ + OP_EODN, /* 13 End of data or \n at end of data: \Z. */ + OP_EOD, /* 14 End of data: \z */ + + OP_OPT, /* 15 Set runtime options */ + OP_CIRC, /* 16 Start of line - varies with multiline switch */ + OP_DOLL, /* 17 End of line - varies with multiline switch */ + OP_CHARS, /* 18 Match string of characters */ + OP_NOT, /* 19 Match anything but the following char */ + + OP_STAR, /* 20 The maximizing and minimizing versions of */ + OP_MINSTAR, /* 21 all these opcodes must come in pairs, with */ + OP_PLUS, /* 22 the minimizing one second. */ + OP_MINPLUS, /* 23 This first set applies to single characters */ + OP_QUERY, /* 24 */ + OP_MINQUERY, /* 25 */ + OP_UPTO, /* 26 From 0 to n matches */ + OP_MINUPTO, /* 27 */ + OP_EXACT, /* 28 Exactly n matches */ + + OP_NOTSTAR, /* 29 The maximizing and minimizing versions of */ + OP_NOTMINSTAR, /* 30 all these opcodes must come in pairs, with */ + OP_NOTPLUS, /* 31 the minimizing one second. */ + OP_NOTMINPLUS, /* 32 This set applies to "not" single characters */ + OP_NOTQUERY, /* 33 */ + OP_NOTMINQUERY, /* 34 */ + OP_NOTUPTO, /* 35 From 0 to n matches */ + OP_NOTMINUPTO, /* 36 */ + OP_NOTEXACT, /* 37 Exactly n matches */ + + OP_TYPESTAR, /* 38 The maximizing and minimizing versions of */ + OP_TYPEMINSTAR, /* 39 all these opcodes must come in pairs, with */ + OP_TYPEPLUS, /* 40 the minimizing one second. These codes must */ + OP_TYPEMINPLUS, /* 41 be in exactly the same order as those above. */ + OP_TYPEQUERY, /* 42 This set applies to character types such as \d */ + OP_TYPEMINQUERY, /* 43 */ + OP_TYPEUPTO, /* 44 From 0 to n matches */ + OP_TYPEMINUPTO, /* 45 */ + OP_TYPEEXACT, /* 46 Exactly n matches */ + + OP_CRSTAR, /* 47 The maximizing and minimizing versions of */ + OP_CRMINSTAR, /* 48 all these opcodes must come in pairs, with */ + OP_CRPLUS, /* 49 the minimizing one second. These codes must */ + OP_CRMINPLUS, /* 50 be in exactly the same order as those above. */ + OP_CRQUERY, /* 51 These are for character classes and back refs */ + OP_CRMINQUERY, /* 52 */ + OP_CRRANGE, /* 53 These are different to the three seta above. */ + OP_CRMINRANGE, /* 54 */ + + OP_CLASS, /* 55 Match a character class, chars < 256 only */ + OP_NCLASS, /* 56 Same, but the bitmap was created from a negative + class - the difference is relevant only when a UTF-8 + character > 255 is encountered. */ + + OP_XCLASS, /* 56 Extended class for handling UTF-8 chars within the + class. This does both positive and negative. */ + + OP_REF, /* 57 Match a back reference */ + OP_RECURSE, /* 58 Match a numbered subpattern (possibly recursive) */ + OP_CALLOUT, /* 59 Call out to external function if provided */ + + OP_ALT, /* 60 Start of alternation */ + OP_KET, /* 61 End of group that doesn't have an unbounded repeat */ + OP_KETRMAX, /* 62 These two must remain together and in this */ + OP_KETRMIN, /* 63 order. They are for groups the repeat for ever. */ + + /* The assertions must come before ONCE and COND */ + + OP_ASSERT, /* 64 Positive lookahead */ + OP_ASSERT_NOT, /* 65 Negative lookahead */ + OP_ASSERTBACK, /* 66 Positive lookbehind */ + OP_ASSERTBACK_NOT, /* 67 Negative lookbehind */ + OP_REVERSE, /* 68 Move pointer back - used in lookbehind assertions */ + + /* ONCE and COND must come after the assertions, with ONCE first, as there's + a test for >= ONCE for a subpattern that isn't an assertion. */ + + OP_ONCE, /* 69 Once matched, don't back up into the subpattern */ + OP_COND, /* 70 Conditional group */ + OP_CREF, /* 71 Used to hold an extraction string number (cond ref) */ + + OP_BRAZERO, /* 72 These two must remain together and in this */ + OP_BRAMINZERO, /* 73 order. */ + + OP_BRANUMBER, /* 74 Used for extracting brackets whose number is greater + than can fit into an opcode. */ + + OP_BRA /* 75 This and greater values are used for brackets that + extract substrings up to a basic limit. After that, + use is made of OP_BRANUMBER. */ +}; + +/* WARNING: There is an implicit assumption in study.c that all opcodes are +less than 128 in value. This makes handling UTF-8 character sequences easier. +*/ + + +/* This macro defines textual names for all the opcodes. There are used only +for debugging, in pcre.c when DEBUG is defined, and also in pcretest.c. The +macro is referenced only in printint.c. */ + +#define OP_NAME_LIST \ + "End", "\\A", "\\G", "\\B", "\\b", "\\D", "\\d", \ + "\\S", "\\s", "\\W", "\\w", "Any", "Anybyte", "\\Z", "\\z", \ + "Opt", "^", "$", "chars", "not", \ + "*", "*?", "+", "+?", "?", "??", "{", "{", "{", \ + "*", "*?", "+", "+?", "?", "??", "{", "{", "{", \ + "*", "*?", "+", "+?", "?", "??", "{", "{", "{", \ + "*", "*?", "+", "+?", "?", "??", "{", "{", \ + "class", "nclass", "xclass", "Ref", "Recurse", "Callout", \ + "Alt", "Ket", "KetRmax", "KetRmin", "Assert", "Assert not", \ + "AssertB", "AssertB not", "Reverse", "Once", "Cond", "Cond ref",\ + "Brazero", "Braminzero", "Branumber", "Bra" + + +/* This macro defines the length of fixed length operations in the compiled +regex. The lengths are used when searching for specific things, and also in the +debugging printing of a compiled regex. We use a macro so that it can be +incorporated both into pcre.c and pcretest.c without being publicly exposed. + +As things have been extended, some of these are no longer fixed lenths, but are +minima instead. For example, the length of a single-character repeat may vary +in UTF-8 mode. The code that uses this table must know about such things. */ + +#define OP_LENGTHS \ + 1, /* End */ \ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* \A, \G, \B, \B, \D, \d, \S, \s, \W, \w */ \ + 1, 1, 1, 1, 2, 1, 1, /* Any, Anybyte, \Z, \z, Opt, ^, $ */ \ + 2, /* Chars - the minimum length */ \ + 2, /* not */ \ + /* Positive single-char repeats */ \ + 2, 2, 2, 2, 2, 2, /* *, *?, +, +?, ?, ?? ** These are */ \ + 4, 4, 4, /* upto, minupto, exact ** minima */ \ + /* Negative single-char repeats */ \ + 2, 2, 2, 2, 2, 2, /* NOT *, *?, +, +?, ?, ?? */ \ + 4, 4, 4, /* NOT upto, minupto, exact */ \ + /* Positive type repeats */ \ + 2, 2, 2, 2, 2, 2, /* Type *, *?, +, +?, ?, ?? */ \ + 4, 4, 4, /* Type upto, minupto, exact */ \ + /* Character class & ref repeats */ \ + 1, 1, 1, 1, 1, 1, /* *, *?, +, +?, ?, ?? */ \ + 5, 5, /* CRRANGE, CRMINRANGE */ \ + 33, /* CLASS */ \ + 33, /* NCLASS */ \ + 0, /* XCLASS - variable length */ \ + 3, /* REF */ \ + 1+LINK_SIZE, /* RECURSE */ \ + 2, /* CALLOUT */ \ + 1+LINK_SIZE, /* Alt */ \ + 1+LINK_SIZE, /* Ket */ \ + 1+LINK_SIZE, /* KetRmax */ \ + 1+LINK_SIZE, /* KetRmin */ \ + 1+LINK_SIZE, /* Assert */ \ + 1+LINK_SIZE, /* Assert not */ \ + 1+LINK_SIZE, /* Assert behind */ \ + 1+LINK_SIZE, /* Assert behind not */ \ + 1+LINK_SIZE, /* Reverse */ \ + 1+LINK_SIZE, /* Once */ \ + 1+LINK_SIZE, /* COND */ \ + 3, /* CREF */ \ + 1, 1, /* BRAZERO, BRAMINZERO */ \ + 3, /* BRANUMBER */ \ + 1+LINK_SIZE /* BRA */ \ + + +/* The highest extraction number before we have to start using additional +bytes. (Originally PCRE didn't have support for extraction counts highter than +this number.) The value is limited by the number of opcodes left after OP_BRA, +i.e. 255 - OP_BRA. We actually set it a bit lower to leave room for additional +opcodes. */ + +#define EXTRACT_BASIC_MAX 150 + +/* A magic value for OP_CREF to indicate the "in recursion" condition. */ + +#define CREF_RECURSE 0xffff + +/* The texts of compile-time error messages are defined as macros here so that +they can be accessed by the POSIX wrapper and converted into error codes. Yes, +I could have used error codes in the first place, but didn't feel like changing +just to accommodate the POSIX wrapper. */ + +#define ERR1 "\\ at end of pattern" +#define ERR2 "\\c at end of pattern" +#define ERR3 "unrecognized character follows \\" +#define ERR4 "numbers out of order in {} quantifier" +#define ERR5 "number too big in {} quantifier" +#define ERR6 "missing terminating ] for character class" +#define ERR7 "invalid escape sequence in character class" +#define ERR8 "range out of order in character class" +#define ERR9 "nothing to repeat" +#define ERR10 "operand of unlimited repeat could match the empty string" +#define ERR11 "internal error: unexpected repeat" +#define ERR12 "unrecognized character after (?" +#define ERR13 "POSIX named classes are supported only within a class" +#define ERR14 "missing )" +#define ERR15 "reference to non-existent subpattern" +#define ERR16 "erroffset passed as NULL" +#define ERR17 "unknown option bit(s) set" +#define ERR18 "missing ) after comment" +#define ERR19 "parentheses nested too deeply" +#define ERR20 "regular expression too large" +#define ERR21 "failed to get memory" +#define ERR22 "unmatched parentheses" +#define ERR23 "internal error: code overflow" +#define ERR24 "unrecognized character after (?<" +#define ERR25 "lookbehind assertion is not fixed length" +#define ERR26 "malformed number after (?(" +#define ERR27 "conditional group contains more than two branches" +#define ERR28 "assertion expected after (?(" +#define ERR29 "(?R or (?digits must be followed by )" +#define ERR30 "unknown POSIX class name" +#define ERR31 "POSIX collating elements are not supported" +#define ERR32 "this version of PCRE is not compiled with PCRE_UTF8 support" +#define ERR33 "spare error" +#define ERR34 "character value in \\x{...} sequence is too large" +#define ERR35 "invalid condition (?(0)" +#define ERR36 "\\C not allowed in lookbehind assertion" +#define ERR37 "PCRE does not support \\L, \\l, \\N, \\P, \\p, \\U, \\u, or \\X" +#define ERR38 "number after (?C is > 255" +#define ERR39 "closing ) for (?C expected" +#define ERR40 "recursive call could loop indefinitely" +#define ERR41 "unrecognized character after (?P" +#define ERR42 "syntax error after (?P" +#define ERR43 "two named groups have the same name" + +/* All character handling must be done as unsigned characters. Otherwise there +are problems with top-bit-set characters and functions such as isspace(). +However, we leave the interface to the outside world as char *, because that +should make things easier for callers. We define a short type for unsigned char +to save lots of typing. I tried "uchar", but it causes problems on Digital +Unix, where it is defined in sys/types, so use "uschar" instead. */ + +typedef unsigned char uschar; + +/* The real format of the start of the pcre block; the index of names and the +code vector run on as long as necessary after the end. */ + +typedef struct real_pcre { + unsigned long int magic_number; + size_t size; /* Total that was malloced */ + const unsigned char *tables; /* Pointer to tables */ + unsigned long int options; + unsigned short int top_bracket; + unsigned short int top_backref; + unsigned short int first_byte; + unsigned short int req_byte; + unsigned short int name_entry_size; /* Size of any name items; 0 => none */ + unsigned short int name_count; /* Number of name items */ +} real_pcre; + +/* The format of the block used to store data from pcre_study(). */ + +typedef struct pcre_study_data { + size_t size; /* Total that was malloced */ + uschar options; + uschar start_bits[32]; +} pcre_study_data; + +/* Structure for passing "static" information around between the functions +doing the compiling, so that they are thread-safe. */ + +typedef struct compile_data { + const uschar *lcc; /* Points to lower casing table */ + const uschar *fcc; /* Points to case-flipping table */ + const uschar *cbits; /* Points to character type table */ + const uschar *ctypes; /* Points to table of type maps */ + const uschar *start_code; /* The start of the compiled code */ + uschar *name_table; /* The name/number table */ + int names_found; /* Number of entries so far */ + int name_entry_size; /* Size of each entry */ + int top_backref; /* Maximum back reference */ + unsigned int backref_map; /* Bitmap of low back refs */ + int req_varyopt; /* "After variable item" flag for reqbyte */ +} compile_data; + +/* Structure for maintaining a chain of pointers to the currently incomplete +branches, for testing for left recursion. */ + +typedef struct branch_chain { + struct branch_chain *outer; + uschar *current; +} branch_chain; + +/* Structure for items in a linked list that represents an explicit recursive +call within the pattern. */ + +typedef struct recursion_info { + struct recursion_info *prev; /* Previous recursion record (or NULL) */ + int group_num; /* Number of group that was called */ + const uschar *after_call; /* "Return value": points after the call in the expr */ + const uschar *save_start; /* Old value of md->start_match */ + int *offset_save; /* Pointer to start of saved offsets */ + int saved_max; /* Number of saved offsets */ +} recursion_info; + +/* Structure for passing "static" information around between the functions +doing the matching, so that they are thread-safe. */ + +typedef struct match_data { + unsigned long int match_call_count; /* As it says */ + unsigned long int match_limit;/* As it says */ + int *offset_vector; /* Offset vector */ + int offset_end; /* One past the end */ + int offset_max; /* The maximum usable for return data */ + const uschar *lcc; /* Points to lower casing table */ + const uschar *ctypes; /* Points to table of type maps */ + BOOL offset_overflow; /* Set if too many extractions */ + BOOL notbol; /* NOTBOL flag */ + BOOL noteol; /* NOTEOL flag */ + BOOL utf8; /* UTF8 flag */ + BOOL endonly; /* Dollar not before final \n */ + BOOL notempty; /* Empty string match not wanted */ + const uschar *start_code; /* For use when recursing */ + const uschar *start_subject; /* Start of the subject string */ + const uschar *end_subject; /* End of the subject string */ + const uschar *start_match; /* Start of this match attempt */ + const uschar *end_match_ptr; /* Subject position at end match */ + int end_offset_top; /* Highwater mark at end of match */ + int capture_last; /* Most recent capture number */ + int start_offset; /* The start offset value */ + recursion_info *recursive; /* Linked list of recursion data */ + void *callout_data; /* To pass back to callouts */ +} match_data; + +/* Bit definitions for entries in the pcre_ctypes table. */ + +#define ctype_space 0x01 +#define ctype_letter 0x02 +#define ctype_digit 0x04 +#define ctype_xdigit 0x08 +#define ctype_word 0x10 /* alphameric or '_' */ +#define ctype_meta 0x80 /* regexp meta char or zero (end pattern) */ + +/* Offsets for the bitmap tables in pcre_cbits. Each table contains a set +of bits for a class map. Some classes are built by combining these tables. */ + +#define cbit_space 0 /* [:space:] or \s */ +#define cbit_xdigit 32 /* [:xdigit:] */ +#define cbit_digit 64 /* [:digit:] or \d */ +#define cbit_upper 96 /* [:upper:] */ +#define cbit_lower 128 /* [:lower:] */ +#define cbit_word 160 /* [:word:] or \w */ +#define cbit_graph 192 /* [:graph:] */ +#define cbit_print 224 /* [:print:] */ +#define cbit_punct 256 /* [:punct:] */ +#define cbit_cntrl 288 /* [:cntrl:] */ +#define cbit_length 320 /* Length of the cbits table */ + +/* Offsets of the various tables from the base tables pointer, and +total length. */ + +#define lcc_offset 0 +#define fcc_offset 256 +#define cbits_offset 512 +#define ctypes_offset (cbits_offset + cbit_length) +#define tables_length (ctypes_offset + 256) + +/* End of internal.h */ diff --git a/lc-continuity/mk4/continuity/pcre/ltmain.sh b/lc-continuity/mk4/continuity/pcre/ltmain.sh new file mode 100644 index 0000000000000000000000000000000000000000..de848c62e412318775aec3fd77aaa162bf6b0ef3 --- /dev/null +++ b/lc-continuity/mk4/continuity/pcre/ltmain.sh @@ -0,0 +1,5069 @@ +# ltmain.sh - Provide generalized library-building support services. +# NOTE: Changing this file will not affect anything until you rerun configure. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 +# Free Software Foundation, Inc. +# Originally by Gordon Matzigkeit , 1996 +# +# This program 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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. + +# Check that we have a working $echo. +if test "X$1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X$1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then + # Yippee, $echo works! + : +else + # Restart under the correct shell, and then maybe $echo will work. + exec $SHELL "$0" --no-reexec ${1+"$@"} +fi + +if test "X$1" = X--fallback-echo; then + # used as fallback echo + shift + cat <&2 + echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit 1 +fi + +# Global variables. +mode=$default_mode +nonopt= +prev= +prevopt= +run= +show="$echo" +show_help= +execute_dlfiles= +lo2o="s/\\.lo\$/.${objext}/" +o2lo="s/\\.${objext}\$/.lo/" + +# Parse our command line options once, thoroughly. +while test $# -gt 0 +do + arg="$1" + shift + + case $arg in + -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;; + *) optarg= ;; + esac + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + execute_dlfiles) + execute_dlfiles="$execute_dlfiles $arg" + ;; + *) + eval "$prev=\$arg" + ;; + esac + + prev= + prevopt= + continue + fi + + # Have we seen a non-optional argument yet? + case $arg in + --help) + show_help=yes + ;; + + --version) + echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP" + exit 0 + ;; + + --config) + ${SED} -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $0 + exit 0 + ;; + + --debug) + echo "$progname: enabling shell trace mode" + set -x + ;; + + --dry-run | -n) + run=: + ;; + + --features) + echo "host: $host" + if test "$build_libtool_libs" = yes; then + echo "enable shared libraries" + else + echo "disable shared libraries" + fi + if test "$build_old_libs" = yes; then + echo "enable static libraries" + else + echo "disable static libraries" + fi + exit 0 + ;; + + --finish) mode="finish" ;; + + --mode) prevopt="--mode" prev=mode ;; + --mode=*) mode="$optarg" ;; + + --preserve-dup-deps) duplicate_deps="yes" ;; + + --quiet | --silent) + show=: + ;; + + -dlopen) + prevopt="-dlopen" + prev=execute_dlfiles + ;; + + -*) + $echo "$modename: unrecognized option \`$arg'" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + + *) + nonopt="$arg" + break + ;; + esac +done + +if test -n "$prevopt"; then + $echo "$modename: option \`$prevopt' requires an argument" 1>&2 + $echo "$help" 1>&2 + exit 1 +fi + +# If this variable is set in any of the actions, the command in it +# will be execed at the end. This prevents here-documents from being +# left over by shells. +exec_cmd= + +if test -z "$show_help"; then + + # Infer the operation mode. + if test -z "$mode"; then + case $nonopt in + *cc | *++ | gcc* | *-gcc* | xlc*) + mode=link + for arg + do + case $arg in + -c) + mode=compile + break + ;; + esac + done + ;; + *db | *dbx | *strace | *truss) + mode=execute + ;; + *install*|cp|mv) + mode=install + ;; + *rm) + mode=uninstall + ;; + *) + # If we have no mode, but dlfiles were specified, then do execute mode. + test -n "$execute_dlfiles" && mode=execute + + # Just use the default operation mode. + if test -z "$mode"; then + if test -n "$nonopt"; then + $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2 + else + $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2 + fi + fi + ;; + esac + fi + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$execute_dlfiles" && test "$mode" != execute; then + $echo "$modename: unrecognized option \`-dlopen'" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + # Change the help message to a mode-specific one. + generic_help="$help" + help="Try \`$modename --help --mode=$mode' for more information." + + # These modes are in order of execution frequency so that they run quickly. + case $mode in + # libtool compile mode + compile) + modename="$modename: compile" + # Get the compilation command and the source file. + base_compile= + prev= + lastarg= + srcfile="$nonopt" + suppress_output= + + user_target=no + for arg + do + case $prev in + "") ;; + xcompiler) + # Aesthetically quote the previous argument. + prev= + lastarg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + + case $arg in + # Double-quote args containing other shell metacharacters. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + + # Add the previous argument to base_compile. + if test -z "$base_compile"; then + base_compile="$lastarg" + else + base_compile="$base_compile $lastarg" + fi + continue + ;; + esac + + # Accept any command-line options. + case $arg in + -o) + if test "$user_target" != "no"; then + $echo "$modename: you cannot specify \`-o' more than once" 1>&2 + exit 1 + fi + user_target=next + ;; + + -static) + build_old_libs=yes + continue + ;; + + -prefer-pic) + pic_mode=yes + continue + ;; + + -prefer-non-pic) + pic_mode=no + continue + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Wc,*) + args=`$echo "X$arg" | $Xsed -e "s/^-Wc,//"` + lastarg= + save_ifs="$IFS"; IFS=',' + for arg in $args; do + IFS="$save_ifs" + + # Double-quote args containing other shell metacharacters. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + lastarg="$lastarg $arg" + done + IFS="$save_ifs" + lastarg=`$echo "X$lastarg" | $Xsed -e "s/^ //"` + + # Add the arguments to base_compile. + if test -z "$base_compile"; then + base_compile="$lastarg" + else + base_compile="$base_compile $lastarg" + fi + continue + ;; + esac + + case $user_target in + next) + # The next one is the -o target name + user_target=yes + continue + ;; + yes) + # We got the output file + user_target=set + libobj="$arg" + continue + ;; + esac + + # Accept the current argument as the source file. + lastarg="$srcfile" + srcfile="$arg" + + # Aesthetically quote the previous argument. + + # Backslashify any backslashes, double quotes, and dollar signs. + # These are the only characters that are still specially + # interpreted inside of double-quoted scrings. + lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"` + + # Double-quote args containing other shell metacharacters. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + case $lastarg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + lastarg="\"$lastarg\"" + ;; + esac + + # Add the previous argument to base_compile. + if test -z "$base_compile"; then + base_compile="$lastarg" + else + base_compile="$base_compile $lastarg" + fi + done + + case $user_target in + set) + ;; + no) + # Get the name of the library object. + libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'` + ;; + *) + $echo "$modename: you must specify a target with \`-o'" 1>&2 + exit 1 + ;; + esac + + # Recognize several different file suffixes. + # If the user specifies -o file.o, it is replaced with file.lo + xform='[cCFSfmso]' + case $libobj in + *.ada) xform=ada ;; + *.adb) xform=adb ;; + *.ads) xform=ads ;; + *.asm) xform=asm ;; + *.c++) xform=c++ ;; + *.cc) xform=cc ;; + *.cpp) xform=cpp ;; + *.cxx) xform=cxx ;; + *.f90) xform=f90 ;; + *.for) xform=for ;; + esac + + libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"` + + case $libobj in + *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;; + *) + $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2 + exit 1 + ;; + esac + + if test -z "$base_compile"; then + $echo "$modename: you must specify a compilation command" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + # Delete any leftover library objects. + if test "$build_old_libs" = yes; then + removelist="$obj $libobj" + else + removelist="$libobj" + fi + + $run $rm $removelist + trap "$run $rm $removelist; exit 1" 1 2 15 + + # On Cygwin there's no "real" PIC flag so we must build both object types + case $host_os in + cygwin* | mingw* | pw32* | os2*) + pic_mode=default + ;; + esac + if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then + # non-PIC code in shared libraries is not supported + pic_mode=default + fi + + # Calculate the filename of the output object if compiler does + # not support -o with -c + if test "$compiler_c_o" = no; then + output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext} + lockfile="$output_obj.lock" + removelist="$removelist $output_obj $lockfile" + trap "$run $rm $removelist; exit 1" 1 2 15 + else + need_locks=no + lockfile= + fi + + # Lock this critical section if it is needed + # We use this script file to make the link, it avoids creating a new file + if test "$need_locks" = yes; then + until $run ln "$0" "$lockfile" 2>/dev/null; do + $show "Waiting for $lockfile to be removed" + sleep 2 + done + elif test "$need_locks" = warn; then + if test -f "$lockfile"; then + echo "\ +*** ERROR, $lockfile exists and contains: +`cat $lockfile 2>/dev/null` + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $run $rm $removelist + exit 1 + fi + echo $srcfile > "$lockfile" + fi + + if test -n "$fix_srcfile_path"; then + eval srcfile=\"$fix_srcfile_path\" + fi + + # Only build a PIC object if we are building libtool libraries. + if test "$build_libtool_libs" = yes; then + # Without this assignment, base_compile gets emptied. + fbsd_hideous_sh_bug=$base_compile + + if test "$pic_mode" != no; then + # All platforms use -DPIC, to notify preprocessed assembler code. + command="$base_compile $srcfile $pic_flag -DPIC" + else + # Don't build PIC code + command="$base_compile $srcfile" + fi + if test "$build_old_libs" = yes; then + lo_libobj="$libobj" + dir=`$echo "X$libobj" | $Xsed -e 's%/[^/]*$%%'` + if test "X$dir" = "X$libobj"; then + dir="$objdir" + else + dir="$dir/$objdir" + fi + libobj="$dir/"`$echo "X$libobj" | $Xsed -e 's%^.*/%%'` + + if test -d "$dir"; then + $show "$rm $libobj" + $run $rm $libobj + else + $show "$mkdir $dir" + $run $mkdir $dir + status=$? + if test $status -ne 0 && test ! -d $dir; then + exit $status + fi + fi + fi + if test "$compiler_o_lo" = yes; then + output_obj="$libobj" + command="$command -o $output_obj" + elif test "$compiler_c_o" = yes; then + output_obj="$obj" + command="$command -o $output_obj" + fi + + $run $rm "$output_obj" + $show "$command" + if $run eval "$command"; then : + else + test -n "$output_obj" && $run $rm $removelist + exit 1 + fi + + if test "$need_locks" = warn && + test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then + echo "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $run $rm $removelist + exit 1 + fi + + # Just move the object if needed, then go on to compile the next one + if test x"$output_obj" != x"$libobj"; then + $show "$mv $output_obj $libobj" + if $run $mv $output_obj $libobj; then : + else + error=$? + $run $rm $removelist + exit $error + fi + fi + + # If we have no pic_flag, then copy the object into place and finish. + if (test -z "$pic_flag" || test "$pic_mode" != default) && + test "$build_old_libs" = yes; then + # Rename the .lo from within objdir to obj + if test -f $obj; then + $show $rm $obj + $run $rm $obj + fi + + $show "$mv $libobj $obj" + if $run $mv $libobj $obj; then : + else + error=$? + $run $rm $removelist + exit $error + fi + + xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$obj"; then + xdir="." + else + xdir="$xdir" + fi + baseobj=`$echo "X$obj" | $Xsed -e "s%.*/%%"` + libobj=`$echo "X$baseobj" | $Xsed -e "$o2lo"` + # Now arrange that obj and lo_libobj become the same file + $show "(cd $xdir && $LN_S $baseobj $libobj)" + if $run eval '(cd $xdir && $LN_S $baseobj $libobj)'; then + # Unlock the critical section if it was locked + if test "$need_locks" != no; then + $run $rm "$lockfile" + fi + exit 0 + else + error=$? + $run $rm $removelist + exit $error + fi + fi + + # Allow error messages only from the first compilation. + suppress_output=' >/dev/null 2>&1' + fi + + # Only build a position-dependent object if we build old libraries. + if test "$build_old_libs" = yes; then + if test "$pic_mode" != yes; then + # Don't build PIC code + command="$base_compile $srcfile" + else + # All platforms use -DPIC, to notify preprocessed assembler code. + command="$base_compile $srcfile $pic_flag -DPIC" + fi + if test "$compiler_c_o" = yes; then + command="$command -o $obj" + output_obj="$obj" + fi + + # Suppress compiler output if we already did a PIC compilation. + command="$command$suppress_output" + $run $rm "$output_obj" + $show "$command" + if $run eval "$command"; then : + else + $run $rm $removelist + exit 1 + fi + + if test "$need_locks" = warn && + test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then + echo "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $run $rm $removelist + exit 1 + fi + + # Just move the object if needed + if test x"$output_obj" != x"$obj"; then + $show "$mv $output_obj $obj" + if $run $mv $output_obj $obj; then : + else + error=$? + $run $rm $removelist + exit $error + fi + fi + + # Create an invalid libtool object if no PIC, so that we do not + # accidentally link it into a program. + if test "$build_libtool_libs" != yes; then + $show "echo timestamp > $libobj" + $run eval "echo timestamp > \$libobj" || exit $? + else + # Move the .lo from within objdir + $show "$mv $libobj $lo_libobj" + if $run $mv $libobj $lo_libobj; then : + else + error=$? + $run $rm $removelist + exit $error + fi + fi + fi + + # Unlock the critical section if it was locked + if test "$need_locks" != no; then + $run $rm "$lockfile" + fi + + exit 0 + ;; + + # libtool link mode + link | relink) + modename="$modename: link" + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + # It is impossible to link a dll without this setting, and + # we shouldn't force the makefile maintainer to figure out + # which system we are compiling for in order to pass an extra + # flag for every libtool invokation. + # allow_undefined=no + + # FIXME: Unfortunately, there are problems with the above when trying + # to make a dll which has undefined symbols, in which case not + # even a static library is built. For now, we need to specify + # -no-undefined on the libtool link line when we can be certain + # that all symbols are satisfied, otherwise we get a static library. + allow_undefined=yes + ;; + *) + allow_undefined=yes + ;; + esac + libtool_args="$nonopt" + compile_command="$nonopt" + finalize_command="$nonopt" + + compile_rpath= + finalize_rpath= + compile_shlibpath= + finalize_shlibpath= + convenience= + old_convenience= + deplibs= + old_deplibs= + compiler_flags= + linker_flags= + dllsearchpath= + lib_search_path=`pwd` + + avoid_version=no + dlfiles= + dlprefiles= + dlself=no + export_dynamic=no + export_symbols= + export_symbols_regex= + generated= + libobjs= + ltlibs= + module=no + no_install=no + objs= + prefer_static_libs=no + preload=no + prev= + prevarg= + release= + rpath= + xrpath= + perm_rpath= + temp_rpath= + thread_safe=no + vinfo= + + # We need to know -static, to get the right output filenames. + for arg + do + case $arg in + -all-static | -static) + if test "X$arg" = "X-all-static"; then + if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then + $echo "$modename: warning: complete static linking is impossible in this configuration" 1>&2 + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + else + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + fi + build_libtool_libs=no + build_old_libs=yes + prefer_static_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + while test $# -gt 0; do + arg="$1" + shift + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + qarg=\"`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`\" ### testsuite: skip nested quoting test + ;; + *) qarg=$arg ;; + esac + libtool_args="$libtool_args $qarg" + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + output) + compile_command="$compile_command @OUTPUT@" + finalize_command="$finalize_command @OUTPUT@" + ;; + esac + + case $prev in + dlfiles|dlprefiles) + if test "$preload" = no; then + # Add the symbol object into the linking commands. + compile_command="$compile_command @SYMFILE@" + finalize_command="$finalize_command @SYMFILE@" + preload=yes + fi + case $arg in + *.la | *.lo) ;; # We handle these cases below. + force) + if test "$dlself" = no; then + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + self) + if test "$prev" = dlprefiles; then + dlself=yes + elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then + dlself=yes + else + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + *) + if test "$prev" = dlfiles; then + dlfiles="$dlfiles $arg" + else + dlprefiles="$dlprefiles $arg" + fi + prev= + continue + ;; + esac + ;; + expsyms) + export_symbols="$arg" + if test ! -f "$arg"; then + $echo "$modename: symbol file \`$arg' does not exist" + exit 1 + fi + prev= + continue + ;; + expsyms_regex) + export_symbols_regex="$arg" + prev= + continue + ;; + release) + release="-$arg" + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case $arg in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + $echo "$modename: only absolute run-paths are allowed" 1>&2 + exit 1 + ;; + esac + if test "$prev" = rpath; then + case "$rpath " in + *" $arg "*) ;; + *) rpath="$rpath $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) xrpath="$xrpath $arg" ;; + esac + fi + prev= + continue + ;; + xcompiler) + compiler_flags="$compiler_flags $qarg" + prev= + compile_command="$compile_command $qarg" + finalize_command="$finalize_command $qarg" + continue + ;; + xlinker) + linker_flags="$linker_flags $qarg" + compiler_flags="$compiler_flags $wl$qarg" + prev= + compile_command="$compile_command $wl$qarg" + finalize_command="$finalize_command $wl$qarg" + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi # test -n $prev + + prevarg="$arg" + + case $arg in + -all-static) + if test -n "$link_static_flag"; then + compile_command="$compile_command $link_static_flag" + finalize_command="$finalize_command $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2 + continue + ;; + + -avoid-version) + avoid_version=yes + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + export_dynamic=yes + continue + ;; + + -export-symbols | -export-symbols-regex) + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + $echo "$modename: more than one -exported-symbols argument is not allowed" + exit 1 + fi + if test "X$arg" = "X-export-symbols"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* + # so, if we see these flags be careful not to treat them like -L + -L[A-Z][A-Z]*:*) + case $with_gcc/$host in + no/*-*-irix* | no/*-*-nonstopux*) + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + ;; + esac + continue + ;; + + -L*) + dir=`$echo "X$arg" | $Xsed -e 's/^-L//'` + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2 + exit 1 + fi + dir="$absdir" + ;; + esac + case "$deplibs " in + *" -L$dir "*) ;; + *) + deplibs="$deplibs -L$dir" + lib_search_path="$lib_search_path $dir" + ;; + esac + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + case :$dllsearchpath: in + *":$dir:"*) ;; + *) dllsearchpath="$dllsearchpath:$dir";; + esac + ;; + esac + continue + ;; + + -l*) + if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then + case $host in + *-*-cygwin* | *-*-pw32* | *-*-beos*) + # These systems don't actually have a C or math library (as such) + continue + ;; + *-*-mingw* | *-*-os2*) + # These systems don't actually have a C library (as such) + test "X$arg" = "X-lc" && continue + ;; + *-*-openbsd* | *-*-freebsd*) + # Do not include libc due to us having libc/libc_r. + test "X$arg" = "X-lc" && continue + ;; + esac + elif test "X$arg" = "X-lc_r"; then + case $host in + *-*-openbsd* | *-*-freebsd*) + # Do not include libc_r directly, use -pthread flag. + continue + ;; + esac + fi + deplibs="$deplibs $arg" + continue + ;; + + -module) + module=yes + continue + ;; + + -no-fast-install) + fast_install=no + continue + ;; + + -no-install) + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + # The PATH hackery in wrapper scripts is required on Windows + # in order for the loader to find any dlls it needs. + $echo "$modename: warning: \`-no-install' is ignored for $host" 1>&2 + $echo "$modename: warning: assuming \`-no-fast-install' instead" 1>&2 + fast_install=no + ;; + *) no_install=yes ;; + esac + continue + ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -o) prev=output ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -R) + prev=xrpath + continue + ;; + + -R*) + dir=`$echo "X$arg" | $Xsed -e 's/^-R//'` + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + $echo "$modename: only absolute run-paths are allowed" 1>&2 + exit 1 + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) xrpath="$xrpath $dir" ;; + esac + continue + ;; + + -static) + # The effects of -static are defined in a previous loop. + # We used to do the same as -all-static on platforms that + # didn't have a PIC flag, but the assumption that the effects + # would be equivalent was wrong. It would break on at least + # Digital Unix and AIX. + continue + ;; + + -thread-safe) + thread_safe=yes + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + + -Wc,*) + args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wc,//'` + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + case $flag in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + flag="\"$flag\"" + ;; + esac + arg="$arg $wl$flag" + compiler_flags="$compiler_flags $flag" + done + IFS="$save_ifs" + arg=`$echo "X$arg" | $Xsed -e "s/^ //"` + ;; + + -Wl,*) + args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wl,//'` + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + case $flag in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + flag="\"$flag\"" + ;; + esac + arg="$arg $wl$flag" + compiler_flags="$compiler_flags $wl$flag" + linker_flags="$linker_flags $flag" + done + IFS="$save_ifs" + arg=`$echo "X$arg" | $Xsed -e "s/^ //"` + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Xlinker) + prev=xlinker + continue + ;; + + # Some other compiler flag. + -* | +*) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + ;; + + *.lo | *.$objext) + # A library or standard object. + if test "$prev" = dlfiles; then + # This file was specified with -dlopen. + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + dlfiles="$dlfiles $arg" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + if test "$prev" = dlprefiles; then + # Preload the old-style object. + dlprefiles="$dlprefiles "`$echo "X$arg" | $Xsed -e "$lo2o"` + prev= + else + case $arg in + *.lo) libobjs="$libobjs $arg" ;; + *) objs="$objs $arg" ;; + esac + fi + ;; + + *.$libext) + # An archive. + deplibs="$deplibs $arg" + old_deplibs="$old_deplibs $arg" + continue + ;; + + *.la) + # A libtool-controlled library. + + if test "$prev" = dlfiles; then + # This library was specified with -dlopen. + dlfiles="$dlfiles $arg" + prev= + elif test "$prev" = dlprefiles; then + # The library was specified with -dlpreopen. + dlprefiles="$dlprefiles $arg" + prev= + else + deplibs="$deplibs $arg" + fi + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + ;; + esac # arg + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + fi + done # argument parsing loop + + if test -n "$prev"; then + $echo "$modename: the \`$prevarg' option requires an argument" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + fi + + # calculate the name of the file, without its directory + outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'` + libobjs_save="$libobjs" + + if test -n "$shlibpath_var"; then + # get the directories listed in $shlibpath_var + eval shlib_search_path=\`\$echo \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\` + else + shlib_search_path= + fi + eval sys_lib_search_path=\"$sys_lib_search_path_spec\" + eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" + + output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'` + if test "X$output_objdir" = "X$output"; then + output_objdir="$objdir" + else + output_objdir="$output_objdir/$objdir" + fi + # Create the object directory. + if test ! -d $output_objdir; then + $show "$mkdir $output_objdir" + $run $mkdir $output_objdir + status=$? + if test $status -ne 0 && test ! -d $output_objdir; then + exit $status + fi + fi + + # Determine the type of output + case $output in + "") + $echo "$modename: you must specify an output file" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + *.$libext) linkmode=oldlib ;; + *.lo | *.$objext) linkmode=obj ;; + *.la) linkmode=lib ;; + *) linkmode=prog ;; # Anything else should be a program. + esac + + specialdeplibs= + libs= + # Find all interdependent deplibs by searching for libraries + # that are linked more than once (e.g. -la -lb -la) + for deplib in $deplibs; do + if test "X$duplicate_deps" = "Xyes" ; then + case "$libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + libs="$libs $deplib" + done + deplibs= + newdependency_libs= + newlib_search_path= + need_relink=no # whether we're linking any uninstalled libtool libraries + notinst_deplibs= # not-installed libtool libraries + notinst_path= # paths that contain not-installed libtool libraries + case $linkmode in + lib) + passes="conv link" + for file in $dlfiles $dlprefiles; do + case $file in + *.la) ;; + *) + $echo "$modename: libraries can \`-dlopen' only libtool libraries: $file" 1>&2 + exit 1 + ;; + esac + done + ;; + prog) + compile_deplibs= + finalize_deplibs= + alldeplibs=no + newdlfiles= + newdlprefiles= + passes="conv scan dlopen dlpreopen link" + ;; + *) passes="conv" + ;; + esac + for pass in $passes; do + if test $linkmode = prog; then + # Determine which files to process + case $pass in + dlopen) + libs="$dlfiles" + save_deplibs="$deplibs" # Collect dlpreopened libraries + deplibs= + ;; + dlpreopen) libs="$dlprefiles" ;; + link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; + esac + fi + for deplib in $libs; do + lib= + found=no + case $deplib in + -l*) + if test $linkmode = oldlib && test $linkmode = obj; then + $echo "$modename: warning: \`-l' is ignored for archives/objects: $deplib" 1>&2 + continue + fi + if test $pass = conv; then + deplibs="$deplib $deplibs" + continue + fi + name=`$echo "X$deplib" | $Xsed -e 's/^-l//'` + for searchdir in $newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path; do + # Search the libtool library + lib="$searchdir/lib${name}.la" + if test -f "$lib"; then + found=yes + break + fi + done + if test "$found" != yes; then + # deplib doesn't seem to be a libtool library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test $linkmode = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + ;; # -l + -L*) + case $linkmode in + lib) + deplibs="$deplib $deplibs" + test $pass = conv && continue + newdependency_libs="$deplib $newdependency_libs" + newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` + ;; + prog) + if test $pass = conv; then + deplibs="$deplib $deplibs" + continue + fi + if test $pass = scan; then + deplibs="$deplib $deplibs" + newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + ;; + *) + $echo "$modename: warning: \`-L' is ignored for archives/objects: $deplib" 1>&2 + ;; + esac # linkmode + continue + ;; # -L + -R*) + if test $pass = link; then + dir=`$echo "X$deplib" | $Xsed -e 's/^-R//'` + # Make sure the xrpath contains only unique directories. + case "$xrpath " in + *" $dir "*) ;; + *) xrpath="$xrpath $dir" ;; + esac + fi + deplibs="$deplib $deplibs" + continue + ;; + *.la) lib="$deplib" ;; + *.$libext) + if test $pass = conv; then + deplibs="$deplib $deplibs" + continue + fi + case $linkmode in + lib) + if test "$deplibs_check_method" != pass_all; then + echo + echo "*** Warning: Trying to link with static lib archive $deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because the file extensions .$libext of this argument makes me believe" + echo "*** that it is just a static archive that I should not used here." + else + echo + echo "*** Warning: Linking the shared library $output against the" + echo "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + fi + continue + ;; + prog) + if test $pass != link; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + continue + ;; + esac # linkmode + ;; # *.$libext + *.lo | *.$objext) + if test $pass = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then + # If there is no dlopen support or we're linking statically, + # we need to preload. + newdlprefiles="$newdlprefiles $deplib" + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + newdlfiles="$newdlfiles $deplib" + fi + continue + ;; + %DEPLIBS%) + alldeplibs=yes + continue + ;; + esac # case $deplib + if test $found = yes || test -f "$lib"; then : + else + $echo "$modename: cannot find the library \`$lib'" 1>&2 + exit 1 + fi + + # Check to see that this really is a libtool archive. + if (${SED} -e '2q' $lib | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + exit 1 + fi + + ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'` + test "X$ladir" = "X$lib" && ladir="." + + dlname= + dlopen= + dlpreopen= + libdir= + library_names= + old_library= + # If the library was installed with an old release of libtool, + # it will not redefine variable installed. + installed=yes + + # Read the .la file + case $lib in + */* | *\\*) . $lib ;; + *) . ./$lib ;; + esac + + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan" || + { test $linkmode = oldlib && test $linkmode = obj; }; then + # Add dl[pre]opened files of deplib + test -n "$dlopen" && dlfiles="$dlfiles $dlopen" + test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen" + fi + + if test $pass = conv; then + # Only check for convenience libraries + deplibs="$lib $deplibs" + if test -z "$libdir"; then + if test -z "$old_library"; then + $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 + exit 1 + fi + # It is a libtool convenience library, so add in its objects. + convenience="$convenience $ladir/$objdir/$old_library" + old_convenience="$old_convenience $ladir/$objdir/$old_library" + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if test "X$duplicate_deps" = "Xyes" ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done + elif test $linkmode != prog && test $linkmode != lib; then + $echo "$modename: \`$lib' is not a convenience library" 1>&2 + exit 1 + fi + continue + fi # $pass = conv + + # Get the name of the library we link against. + linklib= + for l in $old_library $library_names; do + linklib="$l" + done + if test -z "$linklib"; then + $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 + exit 1 + fi + + # This library was specified with -dlopen. + if test $pass = dlopen; then + if test -z "$libdir"; then + $echo "$modename: cannot -dlopen a convenience library: \`$lib'" 1>&2 + exit 1 + fi + if test -z "$dlname" || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then + # If there is no dlname, no dlopen support or we're linking + # statically, we need to preload. + dlprefiles="$dlprefiles $lib" + else + newdlfiles="$newdlfiles $lib" + fi + continue + fi # $pass = dlopen + + # We need an absolute path. + case $ladir in + [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; + *) + abs_ladir=`cd "$ladir" && pwd` + if test -z "$abs_ladir"; then + $echo "$modename: warning: cannot determine absolute directory name of \`$ladir'" 1>&2 + $echo "$modename: passing it literally to the linker, although it might fail" 1>&2 + abs_ladir="$ladir" + fi + ;; + esac + laname=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` + + # Find the relevant object directory and library name. + if test "X$installed" = Xyes; then + if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then + $echo "$modename: warning: library \`$lib' was moved." 1>&2 + dir="$ladir" + absdir="$abs_ladir" + libdir="$abs_ladir" + else + dir="$libdir" + absdir="$libdir" + fi + else + dir="$ladir/$objdir" + absdir="$abs_ladir/$objdir" + # Remove this search path later + notinst_path="$notinst_path $abs_ladir" + fi # $installed = yes + name=`$echo "X$laname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` + + # This library was specified with -dlpreopen. + if test $pass = dlpreopen; then + if test -z "$libdir"; then + $echo "$modename: cannot -dlpreopen a convenience library: \`$lib'" 1>&2 + exit 1 + fi + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + newdlprefiles="$newdlprefiles $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + newdlprefiles="$newdlprefiles $dir/$dlname" + else + newdlprefiles="$newdlprefiles $dir/$linklib" + fi + fi # $pass = dlpreopen + + if test -z "$libdir"; then + # Link the convenience library + if test $linkmode = lib; then + deplibs="$dir/$old_library $deplibs" + elif test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$dir/$old_library $compile_deplibs" + finalize_deplibs="$dir/$old_library $finalize_deplibs" + else + deplibs="$lib $deplibs" + fi + continue + fi + + if test $linkmode = prog && test $pass != link; then + newlib_search_path="$newlib_search_path $ladir" + deplibs="$lib $deplibs" + + linkalldeplibs=no + if test "$link_all_deplibs" != no || test -z "$library_names" || + test "$build_libtool_libs" = no; then + linkalldeplibs=yes + fi + + tmp_libs= + for deplib in $dependency_libs; do + case $deplib in + -L*) newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`;; ### testsuite: skip nested quoting test + esac + # Need to link against all dependency_libs? + if test $linkalldeplibs = yes; then + deplibs="$deplib $deplibs" + else + # Need to hardcode shared library paths + # or/and link against static libraries + newdependency_libs="$deplib $newdependency_libs" + fi + if test "X$duplicate_deps" = "Xyes" ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done # for deplib + continue + fi # $linkmode = prog... + + link_static=no # Whether the deplib will be linked statically + if test -n "$library_names" && + { test "$prefer_static_libs" = no || test -z "$old_library"; }; then + # Link against this shared library + + if test "$linkmode,$pass" = "prog,link" || + { test $linkmode = lib && test $hardcode_into_libs = yes; }; then + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) compile_rpath="$compile_rpath $absdir" + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" + esac + ;; + esac + if test $linkmode = prog; then + # We need to hardcode the library path + if test -n "$shlibpath_var"; then + # Make sure the rpath contains only unique directories. + case "$temp_rpath " in + *" $dir "*) ;; + *" $absdir "*) ;; + *) temp_rpath="$temp_rpath $dir" ;; + esac + fi + fi + fi # $linkmode,$pass = prog,link... + + if test "$alldeplibs" = yes && + { test "$deplibs_check_method" = pass_all || + { test "$build_libtool_libs" = yes && + test -n "$library_names"; }; }; then + # We only need to search for static libraries + continue + fi + + if test "$installed" = no; then + notinst_deplibs="$notinst_deplibs $lib" + need_relink=yes + fi + + if test -n "$old_archive_from_expsyms_cmds"; then + # figure out the soname + set dummy $library_names + realname="$2" + shift; shift + libname=`eval \\$echo \"$libname_spec\"` + # use dlname if we got it. it's perfectly good, no? + if test -n "$dlname"; then + soname="$dlname" + elif test -n "$soname_spec"; then + # bleh windows + case $host in + *cygwin*) + major=`expr $current - $age` + versuffix="-$major" + ;; + esac + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + + # Make a new name for the extract_expsyms_cmds to use + soroot="$soname" + soname=`echo $soroot | ${SED} -e 's/^.*\///'` + newlib="libimp-`echo $soname | ${SED} 's/^lib//;s/\.dll$//'`.a" + + # If the library has no export list, then create one now + if test -f "$output_objdir/$soname-def"; then : + else + $show "extracting exported symbol list from \`$soname'" + save_ifs="$IFS"; IFS='~' + eval cmds=\"$extract_expsyms_cmds\" + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + + # Create $newlib + if test -f "$output_objdir/$newlib"; then :; else + $show "generating import library for \`$soname'" + save_ifs="$IFS"; IFS='~' + eval cmds=\"$old_archive_from_expsyms_cmds\" + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + # make sure the library variables are pointing to the new library + dir=$output_objdir + linklib=$newlib + fi # test -n $old_archive_from_expsyms_cmds + + if test $linkmode = prog || test "$mode" != relink; then + add_shlibpath= + add_dir= + add= + lib_linked=yes + case $hardcode_action in + immediate | unsupported) + if test "$hardcode_direct" = no; then + add="$dir/$linklib" + elif test "$hardcode_minus_L" = no; then + case $host in + *-*-sunos*) add_shlibpath="$dir" ;; + esac + add_dir="-L$dir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = no; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + relink) + if test "$hardcode_direct" = yes; then + add="$dir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$dir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + *) lib_linked=no ;; + esac + + if test "$lib_linked" != yes; then + $echo "$modename: configuration error: unsupported hardcode properties" + exit 1 + fi + + if test -n "$add_shlibpath"; then + case :$compile_shlibpath: in + *":$add_shlibpath:"*) ;; + *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;; + esac + fi + if test $linkmode = prog; then + test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" + test -n "$add" && compile_deplibs="$add $compile_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + if test "$hardcode_direct" != yes && \ + test "$hardcode_minus_L" != yes && \ + test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; + esac + fi + fi + fi + + if test $linkmode = prog || test "$mode" = relink; then + add_shlibpath= + add_dir= + add= + # Finalize command for both is simple: just hardcode it. + if test "$hardcode_direct" = yes; then + add="$libdir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$libdir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; + esac + add="-l$name" + else + # We cannot seem to hardcode it, guess we'll fake it. + add_dir="-L$libdir" + add="-l$name" + fi + + if test $linkmode = prog; then + test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" + test -n "$add" && finalize_deplibs="$add $finalize_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + fi + fi + elif test $linkmode = prog; then + if test "$alldeplibs" = yes && + { test "$deplibs_check_method" = pass_all || + { test "$build_libtool_libs" = yes && + test -n "$library_names"; }; }; then + # We only need to search for static libraries + continue + fi + + # Try to link the static library + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test "$hardcode_direct" != unsupported; then + test -n "$old_library" && linklib="$old_library" + compile_deplibs="$dir/$linklib $compile_deplibs" + finalize_deplibs="$dir/$linklib $finalize_deplibs" + else + compile_deplibs="-l$name -L$dir $compile_deplibs" + finalize_deplibs="-l$name -L$dir $finalize_deplibs" + fi + elif test "$build_libtool_libs" = yes; then + # Not a shared library + if test "$deplibs_check_method" != pass_all; then + # We're trying link a shared library against a static one + # but the system doesn't support it. + + # Just print a warning and add the library to dependency_libs so + # that the program can be linked against the static library. + echo + echo "*** Warning: This system can not link to static lib archive $lib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have." + if test "$module" = yes; then + echo "*** But as you try to build a module library, libtool will still create " + echo "*** a static module, that should work as long as the dlopening application" + echo "*** is linked with the -dlopen flag to resolve symbols at runtime." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + else + convenience="$convenience $dir/$old_library" + old_convenience="$old_convenience $dir/$old_library" + deplibs="$dir/$old_library $deplibs" + link_static=yes + fi + fi # link shared/static library? + + if test $linkmode = lib; then + if test -n "$dependency_libs" && + { test $hardcode_into_libs != yes || test $build_old_libs = yes || + test $link_static = yes; }; then + # Extract -R from dependency_libs + temp_deplibs= + for libdir in $dependency_libs; do + case $libdir in + -R*) temp_xrpath=`$echo "X$libdir" | $Xsed -e 's/^-R//'` + case " $xrpath " in + *" $temp_xrpath "*) ;; + *) xrpath="$xrpath $temp_xrpath";; + esac;; + *) temp_deplibs="$temp_deplibs $libdir";; + esac + done + dependency_libs="$temp_deplibs" + fi + + newlib_search_path="$newlib_search_path $absdir" + # Link against this library + test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" + # ... and its dependency_libs + tmp_libs= + for deplib in $dependency_libs; do + newdependency_libs="$deplib $newdependency_libs" + if test "X$duplicate_deps" = "Xyes" ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done + + if test $link_all_deplibs != no; then + # Add the search paths of all dependency libraries + for deplib in $dependency_libs; do + case $deplib in + -L*) path="$deplib" ;; + *.la) + dir=`$echo "X$deplib" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$deplib" && dir="." + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2 + absdir="$dir" + fi + ;; + esac + if grep "^installed=no" $deplib > /dev/null; then + path="-L$absdir/$objdir" + else + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + if test -z "$libdir"; then + $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 + exit 1 + fi + if test "$absdir" != "$libdir"; then + $echo "$modename: warning: \`$deplib' seems to be moved" 1>&2 + fi + path="-L$absdir" + fi + ;; + *) continue ;; + esac + case " $deplibs " in + *" $path "*) ;; + *) deplibs="$deplibs $path" ;; + esac + done + fi # link_all_deplibs != no + fi # linkmode = lib + done # for deplib in $libs + if test $pass = dlpreopen; then + # Link the dlpreopened libraries before other libraries + for deplib in $save_deplibs; do + deplibs="$deplib $deplibs" + done + fi + if test $pass != dlopen; then + test $pass != scan && dependency_libs="$newdependency_libs" + if test $pass != conv; then + # Make sure lib_search_path contains only unique directories. + lib_search_path= + for dir in $newlib_search_path; do + case "$lib_search_path " in + *" $dir "*) ;; + *) lib_search_path="$lib_search_path $dir" ;; + esac + done + newlib_search_path= + fi + + if test "$linkmode,$pass" != "prog,link"; then + vars="deplibs" + else + vars="compile_deplibs finalize_deplibs" + fi + for var in $vars dependency_libs; do + # Add libraries to $var in reverse order + eval tmp_libs=\"\$$var\" + new_libs= + for deplib in $tmp_libs; do + case $deplib in + -L*) new_libs="$deplib $new_libs" ;; + *) + case " $specialdeplibs " in + *" $deplib "*) new_libs="$deplib $new_libs" ;; + *) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$deplib $new_libs" ;; + esac + ;; + esac + ;; + esac + done + tmp_libs= + for deplib in $new_libs; do + case $deplib in + -L*) + case " $tmp_libs " in + *" $deplib "*) ;; + *) tmp_libs="$tmp_libs $deplib" ;; + esac + ;; + *) tmp_libs="$tmp_libs $deplib" ;; + esac + done + eval $var=\"$tmp_libs\" + done # for var + fi + if test "$pass" = "conv" && + { test "$linkmode" = "lib" || test "$linkmode" = "prog"; }; then + libs="$deplibs" # reset libs + deplibs= + fi + done # for pass + if test $linkmode = prog; then + dlfiles="$newdlfiles" + dlprefiles="$newdlprefiles" + fi + + case $linkmode in + oldlib) + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2 + fi + + if test -n "$rpath"; then + $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2 + fi + + if test -n "$xrpath"; then + $echo "$modename: warning: \`-R' is ignored for archives" 1>&2 + fi + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored for archives" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for archives" 1>&2 + fi + + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2 + fi + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs="$output" + objs="$objs$old_deplibs" + ;; + + lib) + # Make sure we only generate libraries of the form `libNAME.la'. + case $outputname in + lib*) + name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` + eval libname=\"$libname_spec\" + ;; + *) + if test "$module" = no; then + $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + if test "$need_lib_prefix" != no; then + # Add the "lib" prefix for modules if required + name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` + eval libname=\"$libname_spec\" + else + libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` + fi + ;; + esac + + if test -n "$objs"; then + if test "$deplibs_check_method" != pass_all; then + $echo "$modename: cannot build libtool library \`$output' from non-libtool objects on this host:$objs" 2>&1 + exit 1 + else + echo + echo "*** Warning: Linking the shared library $output against the non-libtool" + echo "*** objects $objs is not portable!" + libobjs="$libobjs $objs" + fi + fi + + if test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen self' is ignored for libtool libraries" 1>&2 + fi + + set dummy $rpath + if test $# -gt 2; then + $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2 + fi + install_libdir="$2" + + oldlibs= + if test -z "$rpath"; then + if test "$build_libtool_libs" = yes; then + # Building a libtool convenience library. + libext=al + oldlibs="$output_objdir/$libname.$libext $oldlibs" + build_libtool_libs=convenience + build_old_libs=yes + fi + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored for convenience libraries" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2 + fi + else + + # Parse the version information argument. + save_ifs="$IFS"; IFS=':' + set dummy $vinfo 0 0 0 + IFS="$save_ifs" + + if test -n "$8"; then + $echo "$modename: too many parameters to \`-version-info'" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + current="$2" + revision="$3" + age="$4" + + # Check that each of the things are valid numbers. + case $current in + 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;; + *) + $echo "$modename: CURRENT \`$current' is not a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit 1 + ;; + esac + + case $revision in + 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;; + *) + $echo "$modename: REVISION \`$revision' is not a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit 1 + ;; + esac + + case $age in + 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;; + *) + $echo "$modename: AGE \`$age' is not a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit 1 + ;; + esac + + if test $age -gt $current; then + $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit 1 + fi + + # Calculate the version variables. + major= + versuffix= + verstring= + case $version_type in + none) ;; + + darwin) + # Like Linux, but with the current version available in + # verstring for coding it into the library header + major=.`expr $current - $age` + versuffix="$major.$age.$revision" + # Darwin ld doesn't like 0 for these options... + minor_current=`expr $current + 1` + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + ;; + + freebsd-aout) + major=".$current" + versuffix=".$current.$revision"; + ;; + + freebsd-elf) + major=".$current" + versuffix=".$current"; + ;; + + irix | nonstopux) + major=`expr $current - $age + 1` + + case $version_type in + nonstopux) verstring_prefix=nonstopux ;; + *) verstring_prefix=sgi ;; + esac + verstring="$verstring_prefix$major.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$revision + while test $loop != 0; do + iface=`expr $revision - $loop` + loop=`expr $loop - 1` + verstring="$verstring_prefix$major.$iface:$verstring" + done + + # Before this point, $major must not contain `.'. + major=.$major + versuffix="$major.$revision" + ;; + + linux) + major=.`expr $current - $age` + versuffix="$major.$age.$revision" + ;; + + osf) + major=.`expr $current - $age` + versuffix=".$current.$age.$revision" + verstring="$current.$age.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$age + while test $loop != 0; do + iface=`expr $current - $loop` + loop=`expr $loop - 1` + verstring="$verstring:${iface}.0" + done + + # Make executables depend on our current version. + verstring="$verstring:${current}.0" + ;; + + sunos) + major=".$current" + versuffix=".$current.$revision" + ;; + + windows) + # Use '-' rather than '.', since we only want one + # extension on DOS 8.3 filesystems. + major=`expr $current - $age` + versuffix="-$major" + ;; + + *) + $echo "$modename: unknown library version type \`$version_type'" 1>&2 + echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit 1 + ;; + esac + + # Clear the version info if we defaulted, and they specified a release. + if test -z "$vinfo" && test -n "$release"; then + major= + verstring="0.0" + case $version_type in + darwin) + # we can't check for "0.0" in archive_cmds due to quoting + # problems, so we reset it completely + verstring="" + ;; + *) + verstring="0.0" + ;; + esac + if test "$need_version" = no; then + versuffix= + else + versuffix=".0.0" + fi + fi + + # Remove version info from name if versioning should be avoided + if test "$avoid_version" = yes && test "$need_version" = no; then + major= + versuffix= + verstring="" + fi + + # Check to see if the archive will have undefined symbols. + if test "$allow_undefined" = yes; then + if test "$allow_undefined_flag" = unsupported; then + $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2 + build_libtool_libs=no + build_old_libs=yes + fi + else + # Don't allow undefined symbols. + allow_undefined_flag="$no_undefined_flag" + fi + fi + + if test "$mode" != relink; then + # Remove our outputs. + $show "${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.*" + $run ${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.* + fi + + # Now set the variables for building old libraries. + if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then + oldlibs="$oldlibs $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP` + fi + + # Eliminate all temporary directories. + for path in $notinst_path; do + lib_search_path=`echo "$lib_search_path " | ${SED} -e 's% $path % %g'` + deplibs=`echo "$deplibs " | ${SED} -e 's% -L$path % %g'` + dependency_libs=`echo "$dependency_libs " | ${SED} -e 's% -L$path % %g'` + done + + if test -n "$xrpath"; then + # If the user specified any rpath flags, then add them. + temp_xrpath= + for libdir in $xrpath; do + temp_xrpath="$temp_xrpath -R$libdir" + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" ;; + esac + done + if test $hardcode_into_libs != yes || test $build_old_libs = yes; then + dependency_libs="$temp_xrpath $dependency_libs" + fi + fi + + # Make sure dlfiles contains only unique files that won't be dlpreopened + old_dlfiles="$dlfiles" + dlfiles= + for lib in $old_dlfiles; do + case " $dlprefiles $dlfiles " in + *" $lib "*) ;; + *) dlfiles="$dlfiles $lib" ;; + esac + done + + # Make sure dlprefiles contains only unique files + old_dlprefiles="$dlprefiles" + dlprefiles= + for lib in $old_dlprefiles; do + case "$dlprefiles " in + *" $lib "*) ;; + *) dlprefiles="$dlprefiles $lib" ;; + esac + done + + if test "$build_libtool_libs" = yes; then + if test -n "$rpath"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos*) + # these systems don't actually have a c library (as such)! + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C library is in the System framework + deplibs="$deplibs -framework System" + ;; + *-*-netbsd*) + # Don't link with libc until the a.out ld.so is fixed. + ;; + *-*-openbsd* | *-*-freebsd*) + # Do not include libc due to us having libc/libc_r. + ;; + *) + # Add libc to deplibs on all other systems if necessary. + if test $build_libtool_need_lc = "yes"; then + deplibs="$deplibs -lc" + fi + ;; + esac + fi + + # Transform deplibs into only deplibs that can be linked in shared. + name_save=$name + libname_save=$libname + release_save=$release + versuffix_save=$versuffix + major_save=$major + # I'm not sure if I'm treating the release correctly. I think + # release should show up in the -l (ie -lgmp5) so we don't want to + # add it in twice. Is that correct? + release="" + versuffix="" + major="" + newdeplibs= + droppeddeps=no + case $deplibs_check_method in + pass_all) + # Don't check for shared/static. Everything works. + # This might be a little naive. We might want to check + # whether the library exists or not. But this is on + # osf3 & osf4 and I'm not really sure... Just + # implementing what was already the behaviour. + newdeplibs=$deplibs + ;; + test_compile) + # This code stresses the "libraries are programs" paradigm to its + # limits. Maybe even breaks it. We compile a program, linking it + # against the deplibs as a proxy for the library. Then we can check + # whether they linked in statically or dynamically with ldd. + $rm conftest.c + cat > conftest.c </dev/null` + for potent_lib in $potential_libs; do + # Follow soft links. + if ls -lLd "$potent_lib" 2>/dev/null \ + | grep " -> " >/dev/null; then + continue + fi + # The statement above tries to avoid entering an + # endless loop below, in case of cyclic links. + # We might still enter an endless loop, since a link + # loop can be closed while we follow links, + # but so what? + potlib="$potent_lib" + while test -h "$potlib" 2>/dev/null; do + potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` + case $potliblink in + [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; + *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";; + esac + done + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \ + | ${SED} 10q \ + | egrep "$file_magic_regex" > /dev/null; then + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + break 2 + fi + done + done + if test -n "$a_deplib" ; then + droppeddeps=yes + echo + echo "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + echo "*** with $libname but no candidates were found. (...for file magic test)" + else + echo "*** with $libname and none of the candidates passed a file format test" + echo "*** using a file magic. Last file checked: $potlib" + fi + fi + else + # Add a -L argument. + newdeplibs="$newdeplibs $a_deplib" + fi + done # Gone through all deplibs. + ;; + match_pattern*) + set dummy $deplibs_check_method + match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"` + for a_deplib in $deplibs; do + name="`expr $a_deplib : '-l\(.*\)'`" + # If $name is empty we are operating on a -L argument. + if test -n "$name" && test "$name" != "0"; then + libname=`eval \\$echo \"$libname_spec\"` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + potential_libs=`ls $i/$libname[.-]* 2>/dev/null` + for potent_lib in $potential_libs; do + potlib="$potent_lib" # see symlink-check below in file_magic test + if eval echo \"$potent_lib\" 2>/dev/null \ + | ${SED} 10q \ + | egrep "$match_pattern_regex" > /dev/null; then + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + break 2 + fi + done + done + if test -n "$a_deplib" ; then + droppeddeps=yes + echo + echo "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + echo "*** with $libname but no candidates were found. (...for regex pattern test)" + else + echo "*** with $libname and none of the candidates passed a file format test" + echo "*** using a regex pattern. Last file checked: $potlib" + fi + fi + else + # Add a -L argument. + newdeplibs="$newdeplibs $a_deplib" + fi + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs="" + if $echo "X $deplibs" | $Xsed -e 's/ -lc$//' \ + -e 's/ -[LR][^ ]*//g' -e 's/[ ]//g' | + grep . >/dev/null; then + echo + if test "X$deplibs_check_method" = "Xnone"; then + echo "*** Warning: inter-library dependencies are not supported in this platform." + else + echo "*** Warning: inter-library dependencies are not known to be supported." + fi + echo "*** All declared inter-library dependencies are being dropped." + droppeddeps=yes + fi + ;; + esac + versuffix=$versuffix_save + major=$major_save + release=$release_save + libname=$libname_save + name=$name_save + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + newdeplibs=`$echo "X $newdeplibs" | $Xsed -e 's/ -lc / -framework System /'` + ;; + esac + + if test "$droppeddeps" = yes; then + if test "$module" = yes; then + echo + echo "*** Warning: libtool could not satisfy all declared inter-library" + echo "*** dependencies of module $libname. Therefore, libtool will create" + echo "*** a static module, that should work as long as the dlopening" + echo "*** application is linked with the -dlopen flag." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + else + echo "*** The inter-library dependencies that have been dropped here will be" + echo "*** automatically added whenever a program is linked with this library" + echo "*** or is declared to -dlopen it." + + if test $allow_undefined = no; then + echo + echo "*** Since this library must not contain undefined symbols," + echo "*** because either the platform does not support them or" + echo "*** it was explicitly requested with -no-undefined," + echo "*** libtool will only create a static version of it." + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + fi + fi + # Done checking deplibs! + deplibs=$newdeplibs + fi + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + + # Test again, we may have decided not to build it any more + if test "$build_libtool_libs" = yes; then + if test $hardcode_into_libs = yes; then + # Hardcode the library paths + hardcode_libdirs= + dep_rpath= + rpath="$finalize_rpath" + test "$mode" != relink && rpath="$compile_rpath$rpath" + for libdir in $rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + dep_rpath="$dep_rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$perm_rpath $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval dep_rpath=\"$hardcode_libdir_flag_spec\" + fi + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + rpath="$rpath$dir:" + done + eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" + fi + test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" + fi + + shlibpath="$finalize_shlibpath" + test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath" + if test -n "$shlibpath"; then + eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" + fi + + # Get the real and link names of the library. + eval library_names=\"$library_names_spec\" + set dummy $library_names + realname="$2" + shift; shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + test -z "$dlname" && dlname=$soname + + lib="$output_objdir/$realname" + for link + do + linknames="$linknames $link" + done + + # Ensure that we have .o objects for linkers which dislike .lo + # (e.g. aix) in case we are running --disable-static + for obj in $libobjs; do + xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$obj"; then + xdir="." + else + xdir="$xdir" + fi + baseobj=`$echo "X$obj" | $Xsed -e 's%^.*/%%'` + oldobj=`$echo "X$baseobj" | $Xsed -e "$lo2o"` + if test ! -f $xdir/$oldobj; then + $show "(cd $xdir && ${LN_S} $baseobj $oldobj)" + $run eval '(cd $xdir && ${LN_S} $baseobj $oldobj)' || exit $? + fi + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then + $show "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $run $rm $export_symbols + eval cmds=\"$export_symbols_cmds\" + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + if test -n "$export_symbols_regex"; then + $show "egrep -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\"" + $run eval 'egrep -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + $show "$mv \"${export_symbols}T\" \"$export_symbols\"" + $run eval '$mv "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"' + fi + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + else + gentop="$output_objdir/${outputname}x" + $show "${rm}r $gentop" + $run ${rm}r "$gentop" + $show "mkdir $gentop" + $run mkdir "$gentop" + status=$? + if test $status -ne 0 && test ! -d "$gentop"; then + exit $status + fi + generated="$generated $gentop" + + for xlib in $convenience; do + # Extract the objects. + case $xlib in + [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; + *) xabs=`pwd`"/$xlib" ;; + esac + xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` + xdir="$gentop/$xlib" + + $show "${rm}r $xdir" + $run ${rm}r "$xdir" + $show "mkdir $xdir" + $run mkdir "$xdir" + status=$? + if test $status -ne 0 && test ! -d "$xdir"; then + exit $status + fi + $show "(cd $xdir && $AR x $xabs)" + $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? + + libobjs="$libobjs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP` + done + fi + fi + + if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + linker_flags="$linker_flags $flag" + fi + + # Make a backup of the uninstalled library when relinking + if test "$mode" = relink; then + $run eval '(cd $output_objdir && $rm ${realname}U && $mv $realname ${realname}U)' || exit $? + fi + + # Do each of the archive commands. + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + eval cmds=\"$archive_expsym_cmds\" + else + save_deplibs="$deplibs" + for conv in $convenience; do + tmp_deplibs= + for test_deplib in $deplibs; do + if test "$test_deplib" != "$conv"; then + tmp_deplibs="$tmp_deplibs $test_deplib" + fi + done + deplibs="$tmp_deplibs" + done + eval cmds=\"$archive_cmds\" + deplibs="$save_deplibs" + fi + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + $run eval '(cd $output_objdir && $rm ${realname}T && $mv $realname ${realname}T && $mv "$realname"U $realname)' || exit $? + exit 0 + fi + + # Create links to the real library. + for linkname in $linknames; do + if test "$realname" != "$linkname"; then + $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)" + $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $? + fi + done + + # If -module or -export-dynamic was specified, set the dlname. + if test "$module" = yes || test "$export_dynamic" = yes; then + # On all known operating systems, these are identical. + dlname="$soname" + fi + fi + ;; + + obj) + if test -n "$deplibs"; then + $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2 + fi + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2 + fi + + if test -n "$rpath"; then + $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2 + fi + + if test -n "$xrpath"; then + $echo "$modename: warning: \`-R' is ignored for objects" 1>&2 + fi + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for objects" 1>&2 + fi + + case $output in + *.lo) + if test -n "$objs$old_deplibs"; then + $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2 + exit 1 + fi + libobj="$output" + obj=`$echo "X$output" | $Xsed -e "$lo2o"` + ;; + *) + libobj= + obj="$output" + ;; + esac + + # Delete the old objects. + $run $rm $obj $libobj + + # Objects from convenience libraries. This assumes + # single-version convenience libraries. Whenever we create + # different ones for PIC/non-PIC, this we'll have to duplicate + # the extraction. + reload_conv_objs= + gentop= + # reload_cmds runs $LD directly, so let us get rid of + # -Wl from whole_archive_flag_spec + wl= + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\" + else + gentop="$output_objdir/${obj}x" + $show "${rm}r $gentop" + $run ${rm}r "$gentop" + $show "mkdir $gentop" + $run mkdir "$gentop" + status=$? + if test $status -ne 0 && test ! -d "$gentop"; then + exit $status + fi + generated="$generated $gentop" + + for xlib in $convenience; do + # Extract the objects. + case $xlib in + [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; + *) xabs=`pwd`"/$xlib" ;; + esac + xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` + xdir="$gentop/$xlib" + + $show "${rm}r $xdir" + $run ${rm}r "$xdir" + $show "mkdir $xdir" + $run mkdir "$xdir" + status=$? + if test $status -ne 0 && test ! -d "$xdir"; then + exit $status + fi + $show "(cd $xdir && $AR x $xabs)" + $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? + + reload_conv_objs="$reload_objs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP` + done + fi + fi + + # Create the old-style object. + reload_objs="$objs$old_deplibs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test + + output="$obj" + eval cmds=\"$reload_cmds\" + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${rm}r $gentop + fi + + exit 0 + fi + + if test "$build_libtool_libs" != yes; then + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${rm}r $gentop + fi + + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + $show "echo timestamp > $libobj" + $run eval "echo timestamp > $libobj" || exit $? + exit 0 + fi + + if test -n "$pic_flag" || test "$pic_mode" != default; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs $reload_conv_objs" + output="$libobj" + eval cmds=\"$reload_cmds\" + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + else + # Just create a symlink. + $show $rm $libobj + $run $rm $libobj + xdir=`$echo "X$libobj" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$libobj"; then + xdir="." + else + xdir="$xdir" + fi + baseobj=`$echo "X$libobj" | $Xsed -e 's%^.*/%%'` + oldobj=`$echo "X$baseobj" | $Xsed -e "$lo2o"` + $show "(cd $xdir && $LN_S $oldobj $baseobj)" + $run eval '(cd $xdir && $LN_S $oldobj $baseobj)' || exit $? + fi + + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${rm}r $gentop + fi + + exit 0 + ;; + + prog) + case $host in + *cygwin*) output=`echo $output | ${SED} -e 's,.exe$,,;s,$,.exe,'` ;; + esac + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for programs" 1>&2 + fi + + if test "$preload" = yes; then + if test "$dlopen_support" = unknown && test "$dlopen_self" = unknown && + test "$dlopen_self_static" = unknown; then + $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support." + fi + fi + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + compile_deplibs=`$echo "X $compile_deplibs" | $Xsed -e 's/ -lc / -framework System /'` + finalize_deplibs=`$echo "X $finalize_deplibs" | $Xsed -e 's/ -lc / -framework System /'` + case $host in + *darwin*) + # Don't allow lazy linking, it breaks C++ global constructors + compile_command="$compile_command ${wl}-bind_at_load" + finalize_command="$finalize_command ${wl}-bind_at_load" + ;; + esac + ;; + esac + + compile_command="$compile_command $compile_deplibs" + finalize_command="$finalize_command $finalize_deplibs" + + if test -n "$rpath$xrpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath $xrpath; do + # This is the magic to use -rpath. + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" ;; + esac + done + fi + + # Now hardcode the library paths + rpath= + hardcode_libdirs= + for libdir in $compile_rpath $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + rpath="$rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$perm_rpath $libdir" ;; + esac + fi + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + case :$dllsearchpath: in + *":$libdir:"*) ;; + *) dllsearchpath="$dllsearchpath:$libdir";; + esac + ;; + esac + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + compile_rpath="$rpath" + + rpath= + hardcode_libdirs= + for libdir in $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + rpath="$rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + finalize_rpath="$rpath" + + if test -n "$libobjs" && test "$build_old_libs" = yes; then + # Transform all the library objects into standard objects. + compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + fi + + dlsyms= + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + dlsyms="${outputname}S.c" + else + $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2 + fi + fi + + if test -n "$dlsyms"; then + case $dlsyms in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist="$output_objdir/${outputname}.nm" + + $show "$rm $nlist ${nlist}S ${nlist}T" + $run $rm "$nlist" "${nlist}S" "${nlist}T" + + # Parse the name list into a source file. + $show "creating $output_objdir/$dlsyms" + + test -z "$run" && $echo > "$output_objdir/$dlsyms" "\ +/* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */ +/* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +/* Prevent the only kind of declaration conflicts we can make. */ +#define lt_preloaded_symbols some_other_symbol + +/* External symbol declarations for the compiler. */\ +" + + if test "$dlself" = yes; then + $show "generating symbol list for \`$output'" + + test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$echo "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + for arg in $progfiles; do + $show "extracting global C symbols from \`$arg'" + $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $run eval 'egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + $run eval '$mv "$nlist"T "$nlist"' + fi + + if test -n "$export_symbols_regex"; then + $run eval 'egrep -e "$export_symbols_regex" "$nlist" > "$nlist"T' + $run eval '$mv "$nlist"T "$nlist"' + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols="$output_objdir/$output.exp" + $run $rm $export_symbols + $run eval "${SED} -n -e '/^: @PROGRAM@$/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + else + $run eval "${SED} -e 's/\([][.*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$output.exp"' + $run eval 'grep -f "$output_objdir/$output.exp" < "$nlist" > "$nlist"T' + $run eval 'mv "$nlist"T "$nlist"' + fi + fi + + for arg in $dlprefiles; do + $show "extracting global C symbols from \`$arg'" + name=`echo "$arg" | ${SED} -e 's%^.*/%%'` + $run eval 'echo ": $name " >> "$nlist"' + $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" + done + + if test -z "$run"; then + # Make sure we have at least an empty file. + test -f "$nlist" || : > "$nlist" + + if test -n "$exclude_expsyms"; then + egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T + $mv "$nlist"T "$nlist" + fi + + # Try sorting and uniquifying the output. + if grep -v "^: " < "$nlist" | + if sort -k 3 /dev/null 2>&1; then + sort -k 3 + else + sort +2 + fi | + uniq > "$nlist"S; then + : + else + grep -v "^: " < "$nlist" > "$nlist"S + fi + + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"' + else + echo '/* NONE */' >> "$output_objdir/$dlsyms" + fi + + $echo >> "$output_objdir/$dlsyms" "\ + +#undef lt_preloaded_symbols + +#if defined (__STDC__) && __STDC__ +# define lt_ptr void * +#else +# define lt_ptr char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + lt_ptr address; +} +lt_preloaded_symbols[] = +{\ +" + + eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$dlsyms" + + $echo >> "$output_objdir/$dlsyms" "\ + {0, (lt_ptr) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + fi + + pic_flag_for_symtable= + case $host in + # compiling the symbol table file with pic_flag works around + # a FreeBSD bug that causes programs to crash when -lm is + # linked before any other PIC object. But we must not use + # pic_flag when linking with -static. The problem exists in + # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. + *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) + case "$compile_command " in + *" -static "*) ;; + *) pic_flag_for_symtable=" $pic_flag -DPIC -DFREEBSD_WORKAROUND";; + esac;; + *-*-hpux*) + case "$compile_command " in + *" -static "*) ;; + *) pic_flag_for_symtable=" $pic_flag -DPIC";; + esac + esac + + # Now compile the dynamic symbol file. + $show "(cd $output_objdir && $CC -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")" + $run eval '(cd $output_objdir && $CC -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $? + + # Clean up the generated files. + $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T" + $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T" + + # Transform the symbol file into the correct name. + compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + ;; + *) + $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2 + exit 1 + ;; + esac + else + # We keep going just in case the user didn't refer to + # lt_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + + # Nullify the symbol file. + compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` + fi + + if test $need_relink = no || test "$build_libtool_libs" != yes; then + # Replace the output file specification. + compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + link_command="$compile_command$compile_rpath" + + # We have no uninstalled library dependencies, so finalize right now. + $show "$link_command" + $run eval "$link_command" + status=$? + + # Delete the generated files. + if test -n "$dlsyms"; then + $show "$rm $output_objdir/${outputname}S.${objext}" + $run $rm "$output_objdir/${outputname}S.${objext}" + fi + + exit $status + fi + + if test -n "$shlibpath_var"; then + # We should set the shlibpath_var + rpath= + for dir in $temp_rpath; do + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) + # Absolute path. + rpath="$rpath$dir:" + ;; + *) + # Relative path: add a thisdir entry. + rpath="$rpath\$thisdir/$dir:" + ;; + esac + done + temp_rpath="$rpath" + fi + + if test -n "$compile_shlibpath$finalize_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + compile_var= + finalize_var= + if test -n "$runpath_var"; then + if test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + rpath="$rpath$dir:" + done + compile_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + if test -n "$finalize_perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $finalize_perm_rpath; do + rpath="$rpath$dir:" + done + finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + fi + + if test "$no_install" = yes; then + # We don't need to create a wrapper script. + link_command="$compile_var$compile_command$compile_rpath" + # Replace the output file specification. + link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + # Delete the old output file. + $run $rm $output + # Link the executable and exit + $show "$link_command" + $run eval "$link_command" || exit $? + exit 0 + fi + + if test "$hardcode_action" = relink; then + # Fast installation is not supported + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + + $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2 + $echo "$modename: \`$output' will be relinked during installation" 1>&2 + else + if test "$fast_install" != no; then + link_command="$finalize_var$compile_command$finalize_rpath" + if test "$fast_install" = yes; then + relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'` + else + # fast_install is set to needless + relink_command= + fi + else + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + fi + fi + + # Replace the output file specification. + link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname + + $show "$link_command" + $run eval "$link_command" || exit $? + + # Now create the wrapper script. + $show "creating $output" + + # Quote the relink command for shipping. + if test -n "$relink_command"; then + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` + relink_command="$var=\"$var_value\"; export $var; $relink_command" + fi + done + relink_command="(cd `pwd`; $relink_command)" + relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` + fi + + # Quote $echo for shipping. + if test "X$echo" = "X$SHELL $0 --fallback-echo"; then + case $0 in + [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $0 --fallback-echo";; + *) qecho="$SHELL `pwd`/$0 --fallback-echo";; + esac + qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"` + else + qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"` + fi + + # Only actually do things if our run command is non-null. + if test -z "$run"; then + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) output=`echo $output|${SED} 's,.exe$,,'` ;; + esac + # test for cygwin because mv fails w/o .exe extensions + case $host in + *cygwin*) exeext=.exe ;; + *) exeext= ;; + esac + $rm $output + trap "$rm $output; exit 1" 1 2 15 + + $echo > $output "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed="${SED}"' -e 1s/^X//' +sed_quote_subst='$sed_quote_subst' + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +if test \"\${CDPATH+set}\" = set; then CDPATH=:; export CDPATH; fi + +relink_command=\"$relink_command\" + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variable: + notinst_deplibs='$notinst_deplibs' +else + # When we are sourced in execute mode, \$file and \$echo are already set. + if test \"\$libtool_execute_magic\" != \"$magic\"; then + echo=\"$qecho\" + file=\"\$0\" + # Make sure echo works. + if test \"X\$1\" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift + elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then + # Yippee, \$echo works! + : + else + # Restart under the correct shell, and then maybe \$echo will work. + exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"} + fi + fi\ +" + $echo >> $output "\ + + # Find the directory that this script lives in. + thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\` + done + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test "$fast_install" = yes; then + echo >> $output "\ + program=lt-'$outputname'$exeext + progdir=\"\$thisdir/$objdir\" + + if test ! -f \"\$progdir/\$program\" || \\ + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ + test \"X\$file\" != \"X\$progdir/\$program\"; }; then + + file=\"\$\$-\$program\" + + if test ! -d \"\$progdir\"; then + $mkdir \"\$progdir\" + else + $rm \"\$progdir/\$file\" + fi" + + echo >> $output "\ + + # relink executable if necessary + if test -n \"\$relink_command\"; then + if relink_command_output=\`eval \$relink_command 2>&1\`; then : + else + $echo \"\$relink_command_output\" >&2 + $rm \"\$progdir/\$file\" + exit 1 + fi + fi + + $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $rm \"\$progdir/\$program\"; + $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $rm \"\$progdir/\$file\" + fi" + else + echo >> $output "\ + program='$outputname' + progdir=\"\$thisdir/$objdir\" +" + fi + + echo >> $output "\ + + if test -f \"\$progdir/\$program\"; then" + + # Export our shlibpath_var if we have one. + if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $echo >> $output "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + # The second colon is a workaround for a bug in BeOS R4 ${SED} + $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\` + + export $shlibpath_var +" + fi + + # fixup the dll searchpath if we need to. + if test -n "$dllsearchpath"; then + $echo >> $output "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + $echo >> $output "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. +" + case $host in + # win32 systems need to use the prog path for dll + # lookup to work + *-*-cygwin* | *-*-pw32*) + $echo >> $output "\ + exec \$progdir/\$program \${1+\"\$@\"} +" + ;; + + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2*) + $echo >> $output "\ + exec \$progdir\\\\\$program \${1+\"\$@\"} +" + ;; + + *) + $echo >> $output "\ + # Export the path to the program. + PATH=\"\$progdir:\$PATH\" + export PATH + + exec \$program \${1+\"\$@\"} +" + ;; + esac + $echo >> $output "\ + \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\" + exit 1 + fi + else + # The program doesn't exist. + \$echo \"\$0: error: \$progdir/\$program does not exist\" 1>&2 + \$echo \"This script is just a wrapper for \$program.\" 1>&2 + echo \"See the $PACKAGE documentation for more information.\" 1>&2 + exit 1 + fi +fi\ +" + chmod +x $output + fi + exit 0 + ;; + esac + + # See if we need to build an old-fashioned archive. + for oldlib in $oldlibs; do + + if test "$build_libtool_libs" = convenience; then + oldobjs="$libobjs_save" + addlibs="$convenience" + build_libtool_libs=no + else + if test "$build_libtool_libs" = module; then + oldobjs="$libobjs_save" + build_libtool_libs=no + else + oldobjs="$objs$old_deplibs "`$echo "X$libobjs_save" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP` + fi + addlibs="$old_convenience" + fi + + if test -n "$addlibs"; then + gentop="$output_objdir/${outputname}x" + $show "${rm}r $gentop" + $run ${rm}r "$gentop" + $show "mkdir $gentop" + $run mkdir "$gentop" + status=$? + if test $status -ne 0 && test ! -d "$gentop"; then + exit $status + fi + generated="$generated $gentop" + + # Add in members from convenience archives. + for xlib in $addlibs; do + # Extract the objects. + case $xlib in + [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; + *) xabs=`pwd`"/$xlib" ;; + esac + xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` + xdir="$gentop/$xlib" + + $show "${rm}r $xdir" + $run ${rm}r "$xdir" + $show "mkdir $xdir" + $run mkdir "$xdir" + status=$? + if test $status -ne 0 && test ! -d "$xdir"; then + exit $status + fi + $show "(cd $xdir && $AR x $xabs)" + $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? + + oldobjs="$oldobjs "`find $xdir -name \*.${objext} -print -o -name \*.lo -print | $NL2SP` + done + fi + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then + eval cmds=\"$old_archive_from_new_cmds\" + else + # Ensure that we have .o objects in place in case we decided + # not to build a shared library, and have fallen back to building + # static libs even though --disable-static was passed! + for oldobj in $oldobjs; do + if test ! -f $oldobj; then + xdir=`$echo "X$oldobj" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$oldobj"; then + xdir="." + else + xdir="$xdir" + fi + baseobj=`$echo "X$oldobj" | $Xsed -e 's%^.*/%%'` + obj=`$echo "X$baseobj" | $Xsed -e "$o2lo"` + $show "(cd $xdir && ${LN_S} $obj $baseobj)" + $run eval '(cd $xdir && ${LN_S} $obj $baseobj)' || exit $? + fi + done + + eval cmds=\"$old_archive_cmds\" + fi + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + done + + if test -n "$generated"; then + $show "${rm}r$generated" + $run ${rm}r$generated + fi + + # Now create the libtool archive. + case $output in + *.la) + old_library= + test "$build_old_libs" = yes && old_library="$libname.$libext" + $show "creating $output" + + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` + relink_command="$var=\"$var_value\"; export $var; $relink_command" + fi + done + # Quote the link command for shipping. + relink_command="(cd `pwd`; $SHELL $0 --mode=relink $libtool_args)" + relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` + + # Only create the output if not a dry run. + if test -z "$run"; then + for installed in no yes; do + if test "$installed" = yes; then + if test -z "$install_libdir"; then + break + fi + output="$output_objdir/$outputname"i + # Replace all uninstalled libtool libraries with the installed ones + newdependency_libs= + for deplib in $dependency_libs; do + case $deplib in + *.la) + name=`$echo "X$deplib" | $Xsed -e 's%^.*/%%'` + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + if test -z "$libdir"; then + $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 + exit 1 + fi + newdependency_libs="$newdependency_libs $libdir/$name" + ;; + *) newdependency_libs="$newdependency_libs $deplib" ;; + esac + done + dependency_libs="$newdependency_libs" + newdlfiles= + for lib in $dlfiles; do + name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + if test -z "$libdir"; then + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + exit 1 + fi + newdlfiles="$newdlfiles $libdir/$name" + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + if test -z "$libdir"; then + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + exit 1 + fi + newdlprefiles="$newdlprefiles $libdir/$name" + done + dlprefiles="$newdlprefiles" + fi + $rm $output + # place dlname in correct position for cygwin + tdlname=$dlname + case $host,$output,$installed,$module,$dlname in + *cygwin*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;; + esac + $echo > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='$tdlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Is this an already installed library? +installed=$installed + +# Files to dlopen/dlpreopen +dlopen='$dlfiles' +dlpreopen='$dlprefiles' + +# Directory that this library needs to be installed in: +libdir='$install_libdir'" + if test "$installed" = no && test $need_relink = yes; then + $echo >> $output "\ +relink_command=\"$relink_command\"" + fi + done + fi + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)" + $run eval '(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)' || exit $? + ;; + esac + exit 0 + ;; + + # libtool install mode + install) + modename="$modename: install" + + # There may be an optional sh(1) argument at the beginning of + # install_prog (especially on Windows NT). + if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || + # Allow the use of GNU shtool's install command. + $echo "X$nonopt" | $Xsed | grep shtool > /dev/null; then + # Aesthetically quote it. + arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + arg="\"$arg\"" + ;; + esac + install_prog="$arg " + arg="$1" + shift + else + install_prog= + arg="$nonopt" + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + arg="\"$arg\"" + ;; + esac + install_prog="$install_prog$arg" + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=no + stripme= + for arg + do + if test -n "$dest"; then + files="$files $dest" + dest="$arg" + continue + fi + + case $arg in + -d) isdir=yes ;; + -f) prev="-f" ;; + -g) prev="-g" ;; + -m) prev="-m" ;; + -o) prev="-o" ;; + -s) + stripme=" -s" + continue + ;; + -*) ;; + + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + prev= + else + dest="$arg" + continue + fi + ;; + esac + + # Aesthetically quote the argument. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + arg="\"$arg\"" + ;; + esac + install_prog="$install_prog $arg" + done + + if test -z "$install_prog"; then + $echo "$modename: you must specify an install program" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + if test -n "$prev"; then + $echo "$modename: the \`$prev' option requires an argument" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + if test -z "$files"; then + if test -z "$dest"; then + $echo "$modename: no file or destination specified" 1>&2 + else + $echo "$modename: you must specify a destination" 1>&2 + fi + $echo "$help" 1>&2 + exit 1 + fi + + # Strip any trailing slash from the destination. + dest=`$echo "X$dest" | $Xsed -e 's%/$%%'` + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=yes + if test "$isdir" = yes; then + destdir="$dest" + destname= + else + destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'` + test "X$destdir" = "X$dest" && destdir=. + destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'` + + # Not a directory, so check to see that there is only one file specified. + set dummy $files + if test $# -gt 2; then + $echo "$modename: \`$dest' is not a directory" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + fi + case $destdir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case $file in + *.lo) ;; + *) + $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case $file in + *.$libext) + # Do the static libraries later. + staticlibs="$staticlibs $file" + ;; + + *.la) + # Check to see that this really is a libtool archive. + if (${SED} -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$file' is not a valid libtool archive" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + library_names= + old_library= + relink_command= + # If there is no directory component, then add one. + case $file in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) current_libdirs="$current_libdirs $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) future_libdirs="$future_libdirs $libdir" ;; + esac + fi + + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/ + test "X$dir" = "X$file/" && dir= + dir="$dir$objdir" + + if test -n "$relink_command"; then + $echo "$modename: warning: relinking \`$file'" 1>&2 + $show "$relink_command" + if $run eval "$relink_command"; then : + else + $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 + continue + fi + fi + + # See the names of the shared library. + set dummy $library_names + if test -n "$2"; then + realname="$2" + shift + shift + + srcname="$realname" + test -n "$relink_command" && srcname="$realname"T + + # Install the shared library and build the symlinks. + $show "$install_prog $dir/$srcname $destdir/$realname" + $run eval "$install_prog $dir/$srcname $destdir/$realname" || exit $? + if test -n "$stripme" && test -n "$striplib"; then + $show "$striplib $destdir/$realname" + $run eval "$striplib $destdir/$realname" || exit $? + fi + + if test $# -gt 0; then + # Delete the old symlinks, and create new ones. + for linkname + do + if test "$linkname" != "$realname"; then + $show "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)" + $run eval "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)" + fi + done + fi + + # Do each command in the postinstall commands. + lib="$destdir/$realname" + eval cmds=\"$postinstall_cmds\" + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + + # Install the pseudo-library for information purposes. + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + instname="$dir/$name"i + $show "$install_prog $instname $destdir/$name" + $run eval "$install_prog $instname $destdir/$name" || exit $? + + # Maybe install the static library, too. + test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + destfile="$destdir/$destfile" + fi + + # Deduce the name of the destination old-style object file. + case $destfile in + *.lo) + staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"` + ;; + *.$objext) + staticdest="$destfile" + destfile= + ;; + *) + $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + esac + + # Install the libtool object if requested. + if test -n "$destfile"; then + $show "$install_prog $file $destfile" + $run eval "$install_prog $file $destfile" || exit $? + fi + + # Install the old object if enabled. + if test "$build_old_libs" = yes; then + # Deduce the name of the old-style object file. + staticobj=`$echo "X$file" | $Xsed -e "$lo2o"` + + $show "$install_prog $staticobj $staticdest" + $run eval "$install_prog \$staticobj \$staticdest" || exit $? + fi + exit 0 + ;; + + *) + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + destfile="$destdir/$destfile" + fi + + # Do a test to see if this is really a libtool program. + case $host in + *cygwin*|*mingw*) + wrapper=`echo $file | ${SED} -e 's,.exe$,,'` + ;; + *) + wrapper=$file + ;; + esac + if (${SED} -e '4q' $wrapper | egrep "^# Generated by .*$PACKAGE")>/dev/null 2>&1; then + notinst_deplibs= + relink_command= + + # If there is no directory component, then add one. + case $file in + */* | *\\*) . $wrapper ;; + *) . ./$wrapper ;; + esac + + # Check the variables that should have been set. + if test -z "$notinst_deplibs"; then + $echo "$modename: invalid libtool wrapper script \`$wrapper'" 1>&2 + exit 1 + fi + + finalize=yes + for lib in $notinst_deplibs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + # If there is no directory component, then add one. + case $lib in + */* | *\\*) . $lib ;; + *) . ./$lib ;; + esac + fi + libfile="$libdir/"`$echo "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test + if test -n "$libdir" && test ! -f "$libfile"; then + $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2 + finalize=no + fi + done + + relink_command= + # If there is no directory component, then add one. + case $file in + */* | *\\*) . $wrapper ;; + *) . ./$wrapper ;; + esac + + outputname= + if test "$fast_install" = no && test -n "$relink_command"; then + if test "$finalize" = yes && test -z "$run"; then + tmpdir="/tmp" + test -n "$TMPDIR" && tmpdir="$TMPDIR" + tmpdir="$tmpdir/libtool-$$" + if $mkdir -p "$tmpdir" && chmod 700 "$tmpdir"; then : + else + $echo "$modename: error: cannot create temporary directory \`$tmpdir'" 1>&2 + continue + fi + file=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + outputname="$tmpdir/$file" + # Replace the output file specification. + relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'` + + $show "$relink_command" + if $run eval "$relink_command"; then : + else + $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 + ${rm}r "$tmpdir" + continue + fi + file="$outputname" + else + $echo "$modename: warning: cannot relink \`$file'" 1>&2 + fi + else + # Install the binary that we compiled earlier. + file=`$echo "X$file" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + # remove .exe since cygwin /usr/bin/install will append another + # one anyways + case $install_prog,$host in + /usr/bin/install*,*cygwin*) + case $file:$destfile in + *.exe:*.exe) + # this is ok + ;; + *.exe:*) + destfile=$destfile.exe + ;; + *:*.exe) + destfile=`echo $destfile | ${SED} -e 's,.exe$,,'` + ;; + esac + ;; + esac + $show "$install_prog$stripme $file $destfile" + $run eval "$install_prog\$stripme \$file \$destfile" || exit $? + test -n "$outputname" && ${rm}r "$tmpdir" + ;; + esac + done + + for file in $staticlibs; do + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + + # Set up the ranlib parameters. + oldlib="$destdir/$name" + + $show "$install_prog $file $oldlib" + $run eval "$install_prog \$file \$oldlib" || exit $? + + if test -n "$stripme" && test -n "$striplib"; then + $show "$old_striplib $oldlib" + $run eval "$old_striplib $oldlib" || exit $? + fi + + # Do each command in the postinstall commands. + eval cmds=\"$old_postinstall_cmds\" + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + done + + if test -n "$future_libdirs"; then + $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2 + fi + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + test -n "$run" && current_libdirs=" -n$current_libdirs" + exec_cmd='$SHELL $0 --finish$current_libdirs' + else + exit 0 + fi + ;; + + # libtool finish mode + finish) + modename="$modename: finish" + libdirs="$nonopt" + admincmds= + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for dir + do + libdirs="$libdirs $dir" + done + + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + eval cmds=\"$finish_cmds\" + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || admincmds="$admincmds + $cmd" + done + IFS="$save_ifs" + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $run eval "$cmds" || admincmds="$admincmds + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + test "$show" = ":" && exit 0 + + echo "----------------------------------------------------------------------" + echo "Libraries have been installed in:" + for libdir in $libdirs; do + echo " $libdir" + done + echo + echo "If you ever happen to want to link against installed libraries" + echo "in a given directory, LIBDIR, you must either use libtool, and" + echo "specify the full pathname of the library, or use the \`-LLIBDIR'" + echo "flag during linking and do at least one of the following:" + if test -n "$shlibpath_var"; then + echo " - add LIBDIR to the \`$shlibpath_var' environment variable" + echo " during execution" + fi + if test -n "$runpath_var"; then + echo " - add LIBDIR to the \`$runpath_var' environment variable" + echo " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + echo " - use the \`$flag' linker flag" + fi + if test -n "$admincmds"; then + echo " - have your system administrator run these commands:$admincmds" + fi + if test -f /etc/ld.so.conf; then + echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" + fi + echo + echo "See any operating system documentation about shared libraries for" + echo "more information, such as the ld(1) and ld.so(8) manual pages." + echo "----------------------------------------------------------------------" + exit 0 + ;; + + # libtool execute mode + execute) + modename="$modename: execute" + + # The first argument is the command name. + cmd="$nonopt" + if test -z "$cmd"; then + $echo "$modename: you must specify a COMMAND" 1>&2 + $echo "$help" + exit 1 + fi + + # Handle -dlopen flags immediately. + for file in $execute_dlfiles; do + if test ! -f "$file"; then + $echo "$modename: \`$file' is not a file" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + dir= + case $file in + *.la) + # Check to see that this really is a libtool archive. + if (${SED} -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + # Read the libtool library. + dlname= + library_names= + + # If there is no directory component, then add one. + case $file in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'" + continue + fi + + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$file" && dir=. + + if test -f "$dir/$objdir/$dlname"; then + dir="$dir/$objdir" + else + $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2 + exit 1 + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$file" && dir=. + ;; + + *) + $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2 + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir="$absdir" + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic="$magic" + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case $file in + -*) ;; + *) + # Do a test to see if this is really a libtool program. + if (${SED} -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + # If there is no directory component, then add one. + case $file in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Transform arg to wrapped name. + file="$progdir/$program" + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"` + args="$args \"$file\"" + done + + if test -z "$run"; then + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # Restore saved enviroment variables + if test "${save_LC_ALL+set}" = set; then + LC_ALL="$save_LC_ALL"; export LC_ALL + fi + if test "${save_LANG+set}" = set; then + LANG="$save_LANG"; export LANG + fi + + # Now prepare to actually exec the command. + exec_cmd="\$cmd$args" + else + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\"" + $echo "export $shlibpath_var" + fi + $echo "$cmd$args" + exit 0 + fi + ;; + + # libtool clean and uninstall mode + clean | uninstall) + modename="$modename: $mode" + rm="$nonopt" + files= + rmforce= + exit_status=0 + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + for arg + do + case $arg in + -f) rm="$rm $arg"; rmforce=yes ;; + -*) rm="$rm $arg" ;; + *) files="$files $arg" ;; + esac + done + + if test -z "$rm"; then + $echo "$modename: you must specify an RM program" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + rmdirs= + + for file in $files; do + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + if test "X$dir" = "X$file"; then + dir=. + objdir="$objdir" + else + objdir="$dir/$objdir" + fi + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + test $mode = uninstall && objdir="$dir" + + # Remember objdir for removal later, being careful to avoid duplicates + if test $mode = clean; then + case " $rmdirs " in + *" $objdir "*) ;; + *) rmdirs="$rmdirs $objdir" ;; + esac + fi + + # Don't error if the file doesn't exist and rm -f was used. + if (test -L "$file") >/dev/null 2>&1 \ + || (test -h "$file") >/dev/null 2>&1 \ + || test -f "$file"; then + : + elif test -d "$file"; then + exit_status=1 + continue + elif test "$rmforce" = yes; then + continue + fi + + rmfiles="$file" + + case $name in + *.la) + # Possibly a libtool archive, so verify it. + if (${SED} -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + . $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + rmfiles="$rmfiles $objdir/$n" + done + test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library" + test $mode = clean && rmfiles="$rmfiles $objdir/$name $objdir/${name}i" + + if test $mode = uninstall; then + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + eval cmds=\"$postuninstall_cmds\" + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" + if test $? != 0 && test "$rmforce" != yes; then + exit_status=1 + fi + done + IFS="$save_ifs" + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + eval cmds=\"$old_postuninstall_cmds\" + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" + if test $? != 0 && test "$rmforce" != yes; then + exit_status=1 + fi + done + IFS="$save_ifs" + fi + # FIXME: should reinstall the best remaining shared library. + fi + fi + ;; + + *.lo) + if test "$build_old_libs" = yes; then + oldobj=`$echo "X$name" | $Xsed -e "$lo2o"` + rmfiles="$rmfiles $dir/$oldobj" + fi + ;; + + *) + # Do a test to see if this is a libtool program. + if test $mode = clean && + (${SED} -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + relink_command= + . $dir/$file + + rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}" + if test "$fast_install" = yes && test -n "$relink_command"; then + rmfiles="$rmfiles $objdir/lt-$name" + fi + fi + ;; + esac + $show "$rm $rmfiles" + $run $rm $rmfiles || exit_status=1 + done + + # Try to remove the ${objdir}s in the directories where we deleted files + for dir in $rmdirs; do + if test -d "$dir"; then + $show "rmdir $dir" + $run rmdir $dir >/dev/null 2>&1 + fi + done + + exit $exit_status + ;; + + "") + $echo "$modename: you must specify a MODE" 1>&2 + $echo "$generic_help" 1>&2 + exit 1 + ;; + esac + + if test -z "$exec_cmd"; then + $echo "$modename: invalid operation mode \`$mode'" 1>&2 + $echo "$generic_help" 1>&2 + exit 1 + fi +fi # test -z "$show_help" + +if test -n "$exec_cmd"; then + eval exec $exec_cmd + exit 1 +fi + +# We need to display help for each of the modes. +case $mode in +"") $echo \ +"Usage: $modename [OPTION]... [MODE-ARG]... + +Provide generalized library-building support services. + + --config show all configuration variables + --debug enable verbose shell tracing +-n, --dry-run display commands without modifying any files + --features display basic configuration information and exit + --finish same as \`--mode=finish' + --help display this help message and exit + --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS] + --quiet same as \`--silent' + --silent don't print informational messages + --version print version information + +MODE must be one of the following: + + clean remove files from the build directory + compile compile a source file into a libtool object + execute automatically set library path, then run a program + finish complete the installation of libtool libraries + install install libraries or executables + link create a library or an executable + uninstall remove libraries from an installed directory + +MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for +a more detailed description of MODE." + exit 0 + ;; + +clean) + $echo \ +"Usage: $modename [OPTION]... --mode=clean RM [RM-OPTION]... FILE... + +Remove files from the build directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, object or program, all the files associated +with it are deleted. Otherwise, only FILE itself is deleted using RM." + ;; + +compile) + $echo \ +"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +This mode accepts the following additional options: + + -o OUTPUT-FILE set the output file name to OUTPUT-FILE + -prefer-pic try to building PIC objects only + -prefer-non-pic try to building non-PIC objects only + -static always build a \`.o' file suitable for static linking + +COMPILE-COMMAND is a command to be used in creating a \`standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix \`.c' with the +library object suffix, \`.lo'." + ;; + +execute) + $echo \ +"Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to \`-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + +finish) + $echo \ +"Usage: $modename [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the \`--dry-run' option if you just want to see what would be executed." + ;; + +install) + $echo \ +"Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the \`install' or \`cp' program. + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + +link) + $echo \ +"Usage: $modename [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -avoid-version do not add a version suffix if possible + -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -export-symbols SYMFILE + try to export only the symbols listed in SYMFILE + -export-symbols-regex REGEX + try to export only the symbols matching REGEX + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -module build a library that can dlopened + -no-fast-install disable the fast-install mode + -no-install link a not-installable executable + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries + -static do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + +All other options (arguments beginning with \`-') are ignored. + +Every other argument is treated as a filename. Files ending in \`.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in \`.la', then a libtool library is created, +only library objects (\`.lo' files) may be specified, and \`-rpath' is +required, except when creating a convenience library. + +If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created +using \`ar' and \`ranlib', or on Windows using \`lib'. + +If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file +is created, otherwise an executable program is created." + ;; + +uninstall) + $echo \ +"Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + +*) + $echo "$modename: invalid operation mode \`$mode'" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; +esac + +echo +$echo "Try \`$modename --help' for more information about other modes." + +exit 0 + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: diff --git a/lc-continuity/mk4/continuity/pcre/maketables.c b/lc-continuity/mk4/continuity/pcre/maketables.c new file mode 100644 index 0000000000000000000000000000000000000000..257fe89cec9a663ea9d114a290d81ee7c26d3a6f --- /dev/null +++ b/lc-continuity/mk4/continuity/pcre/maketables.c @@ -0,0 +1,136 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* +PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + +Written by: Philip Hazel + + Copyright (c) 1997-2003 University of Cambridge + +----------------------------------------------------------------------------- +Permission is granted to anyone to use this software for any purpose on any +computer system, and to redistribute it freely, subject to the following +restrictions: + +1. This software 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. + +2. The origin of this software must not be misrepresented, either by + explicit claim or by omission. + +3. Altered versions must be plainly marked as such, and must not be + misrepresented as being the original software. + +4. If PCRE is embedded in any software that is released under the GNU + General Purpose Licence (GPL), then the terms of that licence shall + supersede any condition above with which it is incompatible. +----------------------------------------------------------------------------- + +See the file Tech.Notes for some information on the internals. +*/ + + +/* This file is compiled on its own as part of the PCRE library. However, +it is also included in the compilation of dftables.c, in which case the macro +DFTABLES is defined. */ + +#ifndef DFTABLES +#include "internal.h" +#endif + + + +/************************************************* +* Create PCRE character tables * +*************************************************/ + +/* This function builds a set of character tables for use by PCRE and returns +a pointer to them. They are build using the ctype functions, and consequently +their contents will depend upon the current locale setting. When compiled as +part of the library, the store is obtained via pcre_malloc(), but when compiled +inside dftables, use malloc(). + +Arguments: none +Returns: pointer to the contiguous block of data +*/ + +const unsigned char * +pcre_maketables(void) +{ +unsigned char *yield, *p; +int i; + +#ifndef DFTABLES +yield = (unsigned char*)(pcre_malloc)(tables_length); +#else +yield = (unsigned char*)malloc(tables_length); +#endif + +if (yield == NULL) return NULL; +p = yield; + +/* First comes the lower casing table */ + +for (i = 0; i < 256; i++) *p++ = tolower(i); + +/* Next the case-flipping table */ + +for (i = 0; i < 256; i++) *p++ = islower(i)? toupper(i) : tolower(i); + +/* Then the character class tables. Don't try to be clever and save effort +on exclusive ones - in some locales things may be different. Note that the +table for "space" includes everything "isspace" gives, including VT in the +default locale. This makes it work for the POSIX class [:space:]. */ + +memset(p, 0, cbit_length); +for (i = 0; i < 256; i++) + { + if (isdigit(i)) + { + p[cbit_digit + i/8] |= 1 << (i&7); + p[cbit_word + i/8] |= 1 << (i&7); + } + if (isupper(i)) + { + p[cbit_upper + i/8] |= 1 << (i&7); + p[cbit_word + i/8] |= 1 << (i&7); + } + if (islower(i)) + { + p[cbit_lower + i/8] |= 1 << (i&7); + p[cbit_word + i/8] |= 1 << (i&7); + } + if (i == '_') p[cbit_word + i/8] |= 1 << (i&7); + if (isspace(i)) p[cbit_space + i/8] |= 1 << (i&7); + if (isxdigit(i))p[cbit_xdigit + i/8] |= 1 << (i&7); + if (isgraph(i)) p[cbit_graph + i/8] |= 1 << (i&7); + if (isprint(i)) p[cbit_print + i/8] |= 1 << (i&7); + if (ispunct(i)) p[cbit_punct + i/8] |= 1 << (i&7); + if (iscntrl(i)) p[cbit_cntrl + i/8] |= 1 << (i&7); + } +p += cbit_length; + +/* Finally, the character type table. In this, we exclude VT from the white +space chars, because Perl doesn't recognize it as such for \s and for comments +within regexes. */ + +for (i = 0; i < 256; i++) + { + int x = 0; + if (i != 0x0b && isspace(i)) x += ctype_space; + if (isalpha(i)) x += ctype_letter; + if (isdigit(i)) x += ctype_digit; + if (isxdigit(i)) x += ctype_xdigit; + if (isalnum(i) || i == '_') x += ctype_word; + if (strchr("*+?{^.$|()[", i) != 0) x += ctype_meta; + *p++ = x; + } + +return yield; +} + +/* End of maketables.c */ diff --git a/lc-continuity/mk4/continuity/pcre/makevp.bat b/lc-continuity/mk4/continuity/pcre/makevp.bat new file mode 100644 index 0000000000000000000000000000000000000000..10bd2487a47122967ec8417cb9909644c0e2afd4 --- /dev/null +++ b/lc-continuity/mk4/continuity/pcre/makevp.bat @@ -0,0 +1,25 @@ +@echo off + +REM This file was contributed by Alexander Tokarev for building PCRE for use +REM with Virtual Pascal. It has not been tested with the latest PCRE release. + +REM CHANGE THIS FOR YOUR BORLAND C++ COMPILER PATH + +SET BORLAND=c:\usr\apps\bcc55 + +sh configure + +bcc32 -DDFTABLES -DSTATIC -DVPCOMPAT -I%BORLAND%\include -L%BORLAND%\lib dftables.c + +dftables > chartables.c + +bcc32 -c -RT- -y- -v- -u- -P- -O2 -5 -DSTATIC -DVPCOMPAT -UDFTABLES -I%BORLAND%\include get.c maketables.c pcre.c study.c + +tlib %BORLAND%\lib\cw32.lib *calloc *del *strncmp *memcpy *memmove *memset +tlib pcre.lib +get.obj +maketables.obj +pcre.obj +study.obj +calloc.obj +del.obj +strncmp.obj +memcpy.obj +memmove.obj +memset.obj + +del *.obj *.exe *.tds *.bak >nul 2>nul + +echo --- +echo Now the library should be complete. Please check all messages above. +echo Don't care for warnings, it's OK. diff --git a/lc-continuity/mk4/continuity/pcre/mkinstalldirs b/lc-continuity/mk4/continuity/pcre/mkinstalldirs new file mode 100644 index 0000000000000000000000000000000000000000..82a287bb773e47ed8c736925e1f488061ef63d3d --- /dev/null +++ b/lc-continuity/mk4/continuity/pcre/mkinstalldirs @@ -0,0 +1,40 @@ +#! /bin/sh +# mkinstalldirs --- make directory hierarchy +# Author: Noah Friedman +# Created: 1993-05-16 +# Public domain + +# $Id: mkinstalldirs,v 1.1 2003/11/07 14:48:15 aleigh Exp $ + +errstatus=0 + +for file +do + set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` + shift + + pathcomp= + for d + do + pathcomp="$pathcomp$d" + case "$pathcomp" in + -* ) pathcomp=./$pathcomp ;; + esac + + if test ! -d "$pathcomp"; then + echo "mkdir $pathcomp" + + mkdir "$pathcomp" || lasterr=$? + + if test ! -d "$pathcomp"; then + errstatus=$lasterr + fi + fi + + pathcomp="$pathcomp/" + done +done + +exit $errstatus + +# mkinstalldirs ends here diff --git a/lc-continuity/mk4/continuity/pcre/pcre-config.in b/lc-continuity/mk4/continuity/pcre/pcre-config.in new file mode 100644 index 0000000000000000000000000000000000000000..8daded9fe12c7d42747e0c250f4fb9ba0192d256 --- /dev/null +++ b/lc-continuity/mk4/continuity/pcre/pcre-config.in @@ -0,0 +1,59 @@ +#!/bin/sh + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +exec_prefix_set=no + +usage="\ +Usage: pcre-config [--prefix] [--exec-prefix] [--version] [--libs] [--libs-posix] [--cflags] [--cflags-posix]" + +if test $# -eq 0; then + echo "${usage}" 1>&2 + exit 1 +fi + +while test $# -gt 0; do + case "$1" in + -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) optarg= ;; + esac + + case $1 in + --prefix=*) + prefix=$optarg + if test $exec_prefix_set = no ; then + exec_prefix=$optarg + fi + ;; + --prefix) + echo $prefix + ;; + --exec-prefix=*) + exec_prefix=$optarg + exec_prefix_set=yes + ;; + --exec-prefix) + echo $exec_prefix + ;; + --version) + echo @PCRE_VERSION@ + ;; + --cflags | --cflags-posix) + if test @includedir@ != /usr/include ; then + includes=-I@includedir@ + fi + echo $includes + ;; + --libs-posix) + echo -L@libdir@ -lpcreposix -lpcre + ;; + --libs) + echo -L@libdir@ -lpcre + ;; + *) + echo "${usage}" 1>&2 + exit 1 + ;; + esac + shift +done diff --git a/lc-continuity/mk4/continuity/pcre/pcre.c b/lc-continuity/mk4/continuity/pcre/pcre.c new file mode 100644 index 0000000000000000000000000000000000000000..5da0f76102cdebf2fb79449772d189201c277a67 --- /dev/null +++ b/lc-continuity/mk4/continuity/pcre/pcre.c @@ -0,0 +1,7596 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* +This is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. See +the file Tech.Notes for some information on the internals. + +Written by: Philip Hazel + + Copyright (c) 1997-2003 University of Cambridge + +----------------------------------------------------------------------------- +Permission is granted to anyone to use this software for any purpose on any +computer system, and to redistribute it freely, subject to the following +restrictions: + +1. This software 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. + +2. The origin of this software must not be misrepresented, either by + explicit claim or by omission. + +3. Altered versions must be plainly marked as such, and must not be + misrepresented as being the original software. + +4. If PCRE is embedded in any software that is released under the GNU + General Purpose Licence (GPL), then the terms of that licence shall + supersede any condition above with which it is incompatible. +----------------------------------------------------------------------------- +*/ + +/* Define DEBUG to get debugging output on stdout. */ + +/* #define DEBUG */ + +/* Use a macro for debugging printing, 'cause that eliminates the use of #ifdef +inline, and there are *still* stupid compilers about that don't like indented +pre-processor statements. I suppose it's only been 10 years... */ + +#ifdef DEBUG +#define DPRINTF(p) printf p +#else +#define DPRINTF(p) /*nothing*/ +#endif + +/* Include the internals header, which itself includes Standard C headers plus +the external pcre header. */ + +#include "internal.h" + + +/* Allow compilation as C++ source code, should anybody want to do that. */ + +#ifdef __cplusplus +#define class pcre_class +#endif + + +/* Maximum number of items on the nested bracket stacks at compile time. This +applies to the nesting of all kinds of parentheses. It does not limit +un-nested, non-capturing parentheses. This number can be made bigger if +necessary - it is used to dimension one int and one unsigned char vector at +compile time. */ + +#define BRASTACK_SIZE 200 + + +/* Maximum number of ints of offset to save on the stack for recursive calls. +If the offset vector is bigger, malloc is used. This should be a multiple of 3, +because the offset vector is always a multiple of 3 long. */ + +#define REC_STACK_SAVE_MAX 30 + + +/* The number of bytes in a literal character string above which we can't add +any more is set at 250 in order to allow for UTF-8 characters. (In theory it +could be 255 when UTF-8 support is excluded, but that means that some of the +test output would be different, which just complicates things.) */ + +#define MAXLIT 250 + + +/* The maximum remaining length of subject we are prepared to search for a +req_byte match. */ + +#define REQ_BYTE_MAX 1000 + + +/* Table of sizes for the fixed-length opcodes. It's defined in a macro so that +the definition is next to the definition of the opcodes in internal.h. */ + +static uschar OP_lengths[] = { OP_LENGTHS }; + +/* Min and max values for the common repeats; for the maxima, 0 => infinity */ + +static const char rep_min[] = { 0, 0, 1, 1, 0, 0 }; +static const char rep_max[] = { 0, 0, 0, 0, 1, 1 }; + +/* Table for handling escaped characters in the range '0'-'z'. Positive returns +are simple data values; negative values are for special things like \d and so +on. Zero means further processing is needed (for things like \x), or the escape +is invalid. */ + +static const short int escapes[] = { + 0, 0, 0, 0, 0, 0, 0, 0, /* 0 - 7 */ + 0, 0, ':', ';', '<', '=', '>', '?', /* 8 - ? */ + '@', -ESC_A, -ESC_B, -ESC_C, -ESC_D, -ESC_E, 0, -ESC_G, /* @ - G */ + 0, 0, 0, 0, 0, 0, 0, 0, /* H - O */ + 0, -ESC_Q, 0, -ESC_S, 0, 0, 0, -ESC_W, /* P - W */ + 0, 0, -ESC_Z, '[', '\\', ']', '^', '_', /* X - _ */ + '`', 7, -ESC_b, 0, -ESC_d, ESC_e, ESC_f, 0, /* ` - g */ + 0, 0, 0, 0, 0, 0, ESC_n, 0, /* h - o */ + 0, 0, ESC_r, -ESC_s, ESC_tee, 0, 0, -ESC_w, /* p - w */ + 0, 0, -ESC_z /* x - z */ +}; + +/* Tables of names of POSIX character classes and their lengths. The list is +terminated by a zero length entry. The first three must be alpha, upper, lower, +as this is assumed for handling case independence. */ + +static const char *posix_names[] = { + "alpha", "lower", "upper", + "alnum", "ascii", "blank", "cntrl", "digit", "graph", + "print", "punct", "space", "word", "xdigit" }; + +static const uschar posix_name_lengths[] = { + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 6, 0 }; + +/* Table of class bit maps for each POSIX class; up to three may be combined +to form the class. The table for [:blank:] is dynamically modified to remove +the vertical space characters. */ + +static const int posix_class_maps[] = { + cbit_lower, cbit_upper, -1, /* alpha */ + cbit_lower, -1, -1, /* lower */ + cbit_upper, -1, -1, /* upper */ + cbit_digit, cbit_lower, cbit_upper, /* alnum */ + cbit_print, cbit_cntrl, -1, /* ascii */ + cbit_space, -1, -1, /* blank - a GNU extension */ + cbit_cntrl, -1, -1, /* cntrl */ + cbit_digit, -1, -1, /* digit */ + cbit_graph, -1, -1, /* graph */ + cbit_print, -1, -1, /* print */ + cbit_punct, -1, -1, /* punct */ + cbit_space, -1, -1, /* space */ + cbit_word, -1, -1, /* word - a Perl extension */ + cbit_xdigit,-1, -1 /* xdigit */ +}; + +/* Table to identify ASCII digits and hex digits. This is used when compiling +patterns. Note that the tables in chartables are dependent on the locale, and +may mark arbitrary characters as digits - but the PCRE compiling code expects +to handle only 0-9, a-z, and A-Z as digits when compiling. That is why we have +a private table here. It costs 256 bytes, but it is a lot faster than doing +character value tests (at least in some simple cases I timed), and in some +applications one wants PCRE to compile efficiently as well as match +efficiently. + +For convenience, we use the same bit definitions as in chartables: + + 0x04 decimal digit + 0x08 hexadecimal digit + +Then we can use ctype_digit and ctype_xdigit in the code. */ + +static const unsigned char digitab[] = + { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0- 7 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 8- 15 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 16- 23 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 24- 31 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* - ' */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* ( - / */ + 0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c, /* 0 - 7 */ + 0x0c,0x0c,0x00,0x00,0x00,0x00,0x00,0x00, /* 8 - ? */ + 0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00, /* @ - G */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* H - O */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* P - W */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* X - _ */ + 0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00, /* ` - g */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* h - o */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p - w */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* x -127 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 128-135 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 136-143 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 144-151 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 152-159 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 160-167 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 168-175 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 176-183 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 184-191 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 192-199 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 200-207 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 208-215 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 216-223 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 224-231 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 232-239 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 240-247 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};/* 248-255 */ + +/* Definition to allow mutual recursion */ + +static BOOL + compile_regex(int, int, int *, uschar **, const uschar **, const char **, + BOOL, int, int *, int *, branch_chain *, compile_data *); + +/* Structure for building a chain of data that actually lives on the +stack, for holding the values of the subject pointer at the start of each +subpattern, so as to detect when an empty string has been matched by a +subpattern - to break infinite loops. */ + +typedef struct eptrblock { + struct eptrblock *prev; + const uschar *saved_eptr; +} eptrblock; + +/* Flag bits for the match() function */ + +#define match_condassert 0x01 /* Called to check a condition assertion */ +#define match_isgroup 0x02 /* Set if start of bracketed group */ + +/* Non-error returns from the match() function. Error returns are externally +defined PCRE_ERROR_xxx codes, which are all negative. */ + +#define MATCH_MATCH 1 +#define MATCH_NOMATCH 0 + + + +/************************************************* +* Global variables * +*************************************************/ + +/* PCRE is thread-clean and doesn't use any global variables in the normal +sense. However, it calls memory allocation and free functions via the two +indirections below, and it can optionally do callouts. These values can be +changed by the caller, but are shared between all threads. However, when +compiling for Virtual Pascal, things are done differently (see pcre.in). */ + +#ifndef VPCOMPAT +void *(*pcre_malloc)(size_t) = malloc; +void (*pcre_free)(void *) = free; +int (*pcre_callout)(pcre_callout_block *) = NULL; +#endif + + +/************************************************* +* Macros and tables for character handling * +*************************************************/ + +/* When UTF-8 encoding is being used, a character is no longer just a single +byte. The macros for character handling generate simple sequences when used in +byte-mode, and more complicated ones for UTF-8 characters. */ + +#ifndef SUPPORT_UTF8 +#define GETCHAR(c, eptr) c = *eptr; +#define GETCHARINC(c, eptr) c = *eptr++; +#define GETCHARINCTEST(c, eptr) c = *eptr++; +#define GETCHARLEN(c, eptr, len) c = *eptr; +#define BACKCHAR(eptr) + +#else /* SUPPORT_UTF8 */ + +/* Get the next UTF-8 character, not advancing the pointer. This is called when +we know we are in UTF-8 mode. */ + +#define GETCHAR(c, eptr) \ + c = *eptr; \ + if ((c & 0xc0) == 0xc0) \ + { \ + int gcii; \ + int gcaa = utf8_table4[c & 0x3f]; /* Number of additional bytes */ \ + int gcss = 6*gcaa; \ + c = (c & utf8_table3[gcaa]) << gcss; \ + for (gcii = 1; gcii <= gcaa; gcii++) \ + { \ + gcss -= 6; \ + c |= (eptr[gcii] & 0x3f) << gcss; \ + } \ + } + +/* Get the next UTF-8 character, advancing the pointer. This is called when we +know we are in UTF-8 mode. */ + +#define GETCHARINC(c, eptr) \ + c = *eptr++; \ + if ((c & 0xc0) == 0xc0) \ + { \ + int gcaa = utf8_table4[c & 0x3f]; /* Number of additional bytes */ \ + int gcss = 6*gcaa; \ + c = (c & utf8_table3[gcaa]) << gcss; \ + while (gcaa-- > 0) \ + { \ + gcss -= 6; \ + c |= (*eptr++ & 0x3f) << gcss; \ + } \ + } + +/* Get the next character, testing for UTF-8 mode, and advancing the pointer */ + +#define GETCHARINCTEST(c, eptr) \ + c = *eptr++; \ + if (md->utf8 && (c & 0xc0) == 0xc0) \ + { \ + int gcaa = utf8_table4[c & 0x3f]; /* Number of additional bytes */ \ + int gcss = 6*gcaa; \ + c = (c & utf8_table3[gcaa]) << gcss; \ + while (gcaa-- > 0) \ + { \ + gcss -= 6; \ + c |= (*eptr++ & 0x3f) << gcss; \ + } \ + } + +/* Get the next UTF-8 character, not advancing the pointer, incrementing length +if there are extra bytes. This is called when we know we are in UTF-8 mode. */ + +#define GETCHARLEN(c, eptr, len) \ + c = *eptr; \ + if ((c & 0xc0) == 0xc0) \ + { \ + int gcii; \ + int gcaa = utf8_table4[c & 0x3f]; /* Number of additional bytes */ \ + int gcss = 6*gcaa; \ + c = (c & utf8_table3[gcaa]) << gcss; \ + for (gcii = 1; gcii <= gcaa; gcii++) \ + { \ + gcss -= 6; \ + c |= (eptr[gcii] & 0x3f) << gcss; \ + } \ + len += gcaa; \ + } + +/* If the pointer is not at the start of a character, move it back until +it is. Called only in UTF-8 mode. */ + +#define BACKCHAR(eptr) while((*eptr & 0xc0) == 0x80) eptr--; + +#endif + + + +/************************************************* +* Default character tables * +*************************************************/ + +/* A default set of character tables is included in the PCRE binary. Its source +is built by the maketables auxiliary program, which uses the default C ctypes +functions, and put in the file chartables.c. These tables are used by PCRE +whenever the caller of pcre_compile() does not provide an alternate set of +tables. */ + +#include "chartables.c" + + + +#ifdef SUPPORT_UTF8 +/************************************************* +* Tables for UTF-8 support * +*************************************************/ + +/* These are the breakpoints for different numbers of bytes in a UTF-8 +character. */ + +static const int utf8_table1[] = + { 0x7f, 0x7ff, 0xffff, 0x1fffff, 0x3ffffff, 0x7fffffff}; + +/* These are the indicator bits and the mask for the data bits to set in the +first byte of a character, indexed by the number of additional bytes. */ + +static const int utf8_table2[] = { 0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc}; +static const int utf8_table3[] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01}; + +/* Table of the number of extra characters, indexed by the first character +masked with 0x3f. The highest number for a valid UTF-8 character is in fact +0x3d. */ + +static const uschar utf8_table4[] = { + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 }; + + +/************************************************* +* Convert character value to UTF-8 * +*************************************************/ + +/* This function takes an integer value in the range 0 - 0x7fffffff +and encodes it as a UTF-8 character in 0 to 6 bytes. + +Arguments: + cvalue the character value + buffer pointer to buffer for result - at least 6 bytes long + +Returns: number of characters placed in the buffer +*/ + +static int +ord2utf8(int cvalue, uschar *buffer) +{ +register int i, j; +for (i = 0; i < sizeof(utf8_table1)/sizeof(int); i++) + if (cvalue <= utf8_table1[i]) break; +buffer += i; +for (j = i; j > 0; j--) + { + *buffer-- = 0x80 | (cvalue & 0x3f); + cvalue >>= 6; + } +*buffer = utf8_table2[i] | cvalue; +return i + 1; +} +#endif + + + +/************************************************* +* Print compiled regex * +*************************************************/ + +/* The code for doing this is held in a separate file that is also included in +pcretest.c. It defines a function called print_internals(). */ + +#ifdef DEBUG +#include "printint.c" +#endif + + + +/************************************************* +* Return version string * +*************************************************/ + +#define STRING(a) # a +#define XSTRING(s) STRING(s) + +const char * +pcre_version(void) +{ +return XSTRING(PCRE_MAJOR) "." XSTRING(PCRE_MINOR) " " XSTRING(PCRE_DATE); +} + + + + +/************************************************* +* (Obsolete) Return info about compiled pattern * +*************************************************/ + +/* This is the original "info" function. It picks potentially useful data out +of the private structure, but its interface was too rigid. It remains for +backwards compatibility. The public options are passed back in an int - though +the re->options field has been expanded to a long int, all the public options +at the low end of it, and so even on 16-bit systems this will still be OK. +Therefore, I haven't changed the API for pcre_info(). + +Arguments: + external_re points to compiled code + optptr where to pass back the options + first_byte where to pass back the first character, + or -1 if multiline and all branches start ^, + or -2 otherwise + +Returns: number of capturing subpatterns + or negative values on error +*/ + +int +pcre_info(const pcre *external_re, int *optptr, int *first_byte) +{ +const real_pcre *re = (const real_pcre *)external_re; +if (re == NULL) return PCRE_ERROR_NULL; +if (re->magic_number != MAGIC_NUMBER) return PCRE_ERROR_BADMAGIC; +if (optptr != NULL) *optptr = (int)(re->options & PUBLIC_OPTIONS); +if (first_byte != NULL) + *first_byte = ((re->options & PCRE_FIRSTSET) != 0)? re->first_byte : + ((re->options & PCRE_STARTLINE) != 0)? -1 : -2; +return re->top_bracket; +} + + + +/************************************************* +* Return info about compiled pattern * +*************************************************/ + +/* This is a newer "info" function which has an extensible interface so +that additional items can be added compatibly. + +Arguments: + external_re points to compiled code + extra_data points extra data, or NULL + what what information is required + where where to put the information + +Returns: 0 if data returned, negative on error +*/ + +int +pcre_fullinfo(const pcre *external_re, const pcre_extra *extra_data, int what, + void *where) +{ +const real_pcre *re = (const real_pcre *)external_re; +const pcre_study_data *study = NULL; + +if (re == NULL || where == NULL) return PCRE_ERROR_NULL; +if (re->magic_number != MAGIC_NUMBER) return PCRE_ERROR_BADMAGIC; + +if (extra_data != NULL && (extra_data->flags & PCRE_EXTRA_STUDY_DATA) != 0) + study = extra_data->study_data; + +switch (what) + { + case PCRE_INFO_OPTIONS: + *((unsigned long int *)where) = re->options & PUBLIC_OPTIONS; + break; + + case PCRE_INFO_SIZE: + *((size_t *)where) = re->size; + break; + + case PCRE_INFO_STUDYSIZE: + *((size_t *)where) = (study == NULL)? 0 : study->size; + break; + + case PCRE_INFO_CAPTURECOUNT: + *((int *)where) = re->top_bracket; + break; + + case PCRE_INFO_BACKREFMAX: + *((int *)where) = re->top_backref; + break; + + case PCRE_INFO_FIRSTBYTE: + *((int *)where) = + ((re->options & PCRE_FIRSTSET) != 0)? re->first_byte : + ((re->options & PCRE_STARTLINE) != 0)? -1 : -2; + break; + + case PCRE_INFO_FIRSTTABLE: + *((const uschar **)where) = + (study != NULL && (study->options & PCRE_STUDY_MAPPED) != 0)? + study->start_bits : NULL; + break; + + case PCRE_INFO_LASTLITERAL: + *((int *)where) = + ((re->options & PCRE_REQCHSET) != 0)? re->req_byte : -1; + break; + + case PCRE_INFO_NAMEENTRYSIZE: + *((int *)where) = re->name_entry_size; + break; + + case PCRE_INFO_NAMECOUNT: + *((int *)where) = re->name_count; + break; + + case PCRE_INFO_NAMETABLE: + *((const uschar **)where) = (const uschar *)re + sizeof(real_pcre); + break; + + default: return PCRE_ERROR_BADOPTION; + } + +return 0; +} + + + +/************************************************* +* Return info about what features are configured * +*************************************************/ + +/* This is function which has an extensible interface so that additional items +can be added compatibly. + +Arguments: + what what information is required + where where to put the information + +Returns: 0 if data returned, negative on error +*/ + +int +pcre_config(int what, void *where) +{ +switch (what) + { + case PCRE_CONFIG_UTF8: + #ifdef SUPPORT_UTF8 + *((int *)where) = 1; + #else + *((int *)where) = 0; + #endif + break; + + case PCRE_CONFIG_NEWLINE: + *((int *)where) = NEWLINE; + break; + + case PCRE_CONFIG_LINK_SIZE: + *((int *)where) = LINK_SIZE; + break; + + case PCRE_CONFIG_POSIX_MALLOC_THRESHOLD: + *((int *)where) = POSIX_MALLOC_THRESHOLD; + break; + + case PCRE_CONFIG_MATCH_LIMIT: + *((unsigned int *)where) = MATCH_LIMIT; + break; + + default: return PCRE_ERROR_BADOPTION; + } + +return 0; +} + + + +#ifdef DEBUG +/************************************************* +* Debugging function to print chars * +*************************************************/ + +/* Print a sequence of chars in printable format, stopping at the end of the +subject if the requested. + +Arguments: + p points to characters + length number to print + is_subject TRUE if printing from within md->start_subject + md pointer to matching data block, if is_subject is TRUE + +Returns: nothing +*/ + +static void +pchars(const uschar *p, int length, BOOL is_subject, match_data *md) +{ +int c; +if (is_subject && length > md->end_subject - p) length = md->end_subject - p; +while (length-- > 0) + if (isprint(c = *(p++))) printf("%c", c); else printf("\\x%02x", c); +} +#endif + + + + +/************************************************* +* Handle escapes * +*************************************************/ + +/* This function is called when a \ has been encountered. It either returns a +positive value for a simple escape such as \n, or a negative value which +encodes one of the more complicated things such as \d. When UTF-8 is enabled, +a positive value greater than 255 may be returned. On entry, ptr is pointing at +the \. On exit, it is on the final character of the escape sequence. + +Arguments: + ptrptr points to the pattern position pointer + errorptr points to the pointer to the error message + bracount number of previous extracting brackets + options the options bits + isclass TRUE if inside a character class + cd pointer to char tables block + +Returns: zero or positive => a data character + negative => a special escape sequence + on error, errorptr is set +*/ + +static int +check_escape(const uschar **ptrptr, const char **errorptr, int bracount, + int options, BOOL isclass, compile_data *cd) +{ +const uschar *ptr = *ptrptr; +int c, i; + +/* If backslash is at the end of the pattern, it's an error. */ + +c = *(++ptr); +if (c == 0) *errorptr = ERR1; + +/* Digits or letters may have special meaning; all others are literals. */ + +else if (c < '0' || c > 'z') {} + +/* Do an initial lookup in a table. A non-zero result is something that can be +returned immediately. Otherwise further processing may be required. */ + +else if ((i = escapes[c - '0']) != 0) c = i; + +/* Escapes that need further processing, or are illegal. */ + +else + { + const uschar *oldptr; + switch (c) + { + /* A number of Perl escapes are not handled by PCRE. We give an explicit + error. */ + + case 'l': + case 'L': + case 'N': + case 'p': + case 'P': + case 'u': + case 'U': + case 'X': + *errorptr = ERR37; + break; + + /* The handling of escape sequences consisting of a string of digits + starting with one that is not zero is not straightforward. By experiment, + the way Perl works seems to be as follows: + + Outside a character class, the digits are read as a decimal number. If the + number is less than 10, or if there are that many previous extracting + left brackets, then it is a back reference. Otherwise, up to three octal + digits are read to form an escaped byte. Thus \123 is likely to be octal + 123 (cf \0123, which is octal 012 followed by the literal 3). If the octal + value is greater than 377, the least significant 8 bits are taken. Inside a + character class, \ followed by a digit is always an octal number. */ + + case '1': case '2': case '3': case '4': case '5': + case '6': case '7': case '8': case '9': + + if (!isclass) + { + oldptr = ptr; + c -= '0'; + while ((digitab[ptr[1]] & ctype_digit) != 0) + c = c * 10 + *(++ptr) - '0'; + if (c < 10 || c <= bracount) + { + c = -(ESC_REF + c); + break; + } + ptr = oldptr; /* Put the pointer back and fall through */ + } + + /* Handle an octal number following \. If the first digit is 8 or 9, Perl + generates a binary zero byte and treats the digit as a following literal. + Thus we have to pull back the pointer by one. */ + + if ((c = *ptr) >= '8') + { + ptr--; + c = 0; + break; + } + + /* \0 always starts an octal number, but we may drop through to here with a + larger first octal digit. */ + + case '0': + c -= '0'; + while(i++ < 2 && ptr[1] >= '0' && ptr[1] <= '7') + c = c * 8 + *(++ptr) - '0'; + c &= 255; /* Take least significant 8 bits */ + break; + + /* \x is complicated when UTF-8 is enabled. \x{ddd} is a character number + which can be greater than 0xff, but only if the ddd are hex digits. */ + + case 'x': +#ifdef SUPPORT_UTF8 + if (ptr[1] == '{' && (options & PCRE_UTF8) != 0) + { + const uschar *pt = ptr + 2; + register int count = 0; + c = 0; + while ((digitab[*pt] & ctype_xdigit) != 0) + { + int cc = *pt++; + if (cc >= 'a') cc -= 32; /* Convert to upper case */ + count++; + c = c * 16 + cc - ((cc < 'A')? '0' : ('A' - 10)); + } + if (*pt == '}') + { + if (c < 0 || count > 8) *errorptr = ERR34; + ptr = pt; + break; + } + /* If the sequence of hex digits does not end with '}', then we don't + recognize this construct; fall through to the normal \x handling. */ + } +#endif + + /* Read just a single hex char */ + + c = 0; + while (i++ < 2 && (digitab[ptr[1]] & ctype_xdigit) != 0) + { + int cc = *(++ptr); + if (cc >= 'a') cc -= 32; /* Convert to upper case */ + c = c * 16 + cc - ((cc < 'A')? '0' : ('A' - 10)); + } + break; + + /* Other special escapes not starting with a digit are straightforward */ + + case 'c': + c = *(++ptr); + if (c == 0) + { + *errorptr = ERR2; + return 0; + } + + /* A letter is upper-cased; then the 0x40 bit is flipped. This coding + is ASCII-specific, but then the whole concept of \cx is ASCII-specific. */ + + if (c >= 'a' && c <= 'z') c -= 32; + c ^= 0x40; + break; + + /* PCRE_EXTRA enables extensions to Perl in the matter of escapes. Any + other alphameric following \ is an error if PCRE_EXTRA was set; otherwise, + for Perl compatibility, it is a literal. This code looks a bit odd, but + there used to be some cases other than the default, and there may be again + in future, so I haven't "optimized" it. */ + + default: + if ((options & PCRE_EXTRA) != 0) switch(c) + { + default: + *errorptr = ERR3; + break; + } + break; + } + } + +*ptrptr = ptr; +return c; +} + + + +/************************************************* +* Check for counted repeat * +*************************************************/ + +/* This function is called when a '{' is encountered in a place where it might +start a quantifier. It looks ahead to see if it really is a quantifier or not. +It is only a quantifier if it is one of the forms {ddd} {ddd,} or {ddd,ddd} +where the ddds are digits. + +Arguments: + p pointer to the first char after '{' + cd pointer to char tables block + +Returns: TRUE or FALSE +*/ + +static BOOL +is_counted_repeat(const uschar *p, compile_data *cd) +{ +if ((digitab[*p++] && ctype_digit) == 0) return FALSE; +while ((digitab[*p] & ctype_digit) != 0) p++; +if (*p == '}') return TRUE; + +if (*p++ != ',') return FALSE; +if (*p == '}') return TRUE; + +if ((digitab[*p++] && ctype_digit) == 0) return FALSE; +while ((digitab[*p] & ctype_digit) != 0) p++; + +return (*p == '}'); +} + + + +/************************************************* +* Read repeat counts * +*************************************************/ + +/* Read an item of the form {n,m} and return the values. This is called only +after is_counted_repeat() has confirmed that a repeat-count quantifier exists, +so the syntax is guaranteed to be correct, but we need to check the values. + +Arguments: + p pointer to first char after '{' + minp pointer to int for min + maxp pointer to int for max + returned as -1 if no max + errorptr points to pointer to error message + cd pointer to character tables clock + +Returns: pointer to '}' on success; + current ptr on error, with errorptr set +*/ + +static const uschar * +read_repeat_counts(const uschar *p, int *minp, int *maxp, + const char **errorptr, compile_data *cd) +{ +int min = 0; +int max = -1; + +while ((digitab[*p] & ctype_digit) != 0) min = min * 10 + *p++ - '0'; + +if (*p == '}') max = min; else + { + if (*(++p) != '}') + { + max = 0; + while((digitab[*p] & ctype_digit) != 0) max = max * 10 + *p++ - '0'; + if (max < min) + { + *errorptr = ERR4; + return p; + } + } + } + +/* Do paranoid checks, then fill in the required variables, and pass back the +pointer to the terminating '}'. */ + +if (min > 65535 || max > 65535) + *errorptr = ERR5; +else + { + *minp = min; + *maxp = max; + } +return p; +} + + + +/************************************************* +* Find first significant op code * +*************************************************/ + +/* This is called by several functions that scan a compiled expression looking +for a fixed first character, or an anchoring op code etc. It skips over things +that do not influence this. For some calls, a change of option is important. + +Arguments: + code pointer to the start of the group + options pointer to external options + optbit the option bit whose changing is significant, or + zero if none are + +Returns: pointer to the first significant opcode +*/ + +static const uschar* +first_significant_code(const uschar *code, int *options, int optbit) +{ +for (;;) + { + switch ((int)*code) + { + case OP_OPT: + if (optbit > 0 && ((int)code[1] & optbit) != (*options & optbit)) + *options = (int)code[1]; + code += 2; + break; + + case OP_ASSERT_NOT: + case OP_ASSERTBACK: + case OP_ASSERTBACK_NOT: + do code += GET(code, 1); while (*code == OP_ALT); + /* Fall through */ + + case OP_CALLOUT: + case OP_CREF: + case OP_BRANUMBER: + case OP_WORD_BOUNDARY: + case OP_NOT_WORD_BOUNDARY: + code += OP_lengths[*code]; + break; + + default: + return code; + } + } +/* Control never reaches here */ +} + + + + +/************************************************* +* Find the fixed length of a pattern * +*************************************************/ + +/* Scan a pattern and compute the fixed length of subject that will match it, +if the length is fixed. This is needed for dealing with backward assertions. +In UTF8 mode, the result is in characters rather than bytes. + +Arguments: + code points to the start of the pattern (the bracket) + options the compiling options + +Returns: the fixed length, or -1 if there is no fixed length, + or -2 if \C was encountered +*/ + +static int +find_fixedlength(uschar *code, int options) +{ +int length = -1; + +register int branchlength = 0; +register uschar *cc = code + 1 + LINK_SIZE; + +/* Scan along the opcodes for this branch. If we get to the end of the +branch, check the length against that of the other branches. */ + +for (;;) + { + int d; + register int op = *cc; + if (op >= OP_BRA) op = OP_BRA; + + switch (op) + { + case OP_BRA: + case OP_ONCE: + case OP_COND: + d = find_fixedlength(cc, options); + if (d < 0) return d; + branchlength += d; + do cc += GET(cc, 1); while (*cc == OP_ALT); + cc += 1 + LINK_SIZE; + break; + + /* Reached end of a branch; if it's a ket it is the end of a nested + call. If it's ALT it is an alternation in a nested call. If it is + END it's the end of the outer call. All can be handled by the same code. */ + + case OP_ALT: + case OP_KET: + case OP_KETRMAX: + case OP_KETRMIN: + case OP_END: + if (length < 0) length = branchlength; + else if (length != branchlength) return -1; + if (*cc != OP_ALT) return length; + cc += 1 + LINK_SIZE; + branchlength = 0; + break; + + /* Skip over assertive subpatterns */ + + case OP_ASSERT: + case OP_ASSERT_NOT: + case OP_ASSERTBACK: + case OP_ASSERTBACK_NOT: + do cc += GET(cc, 1); while (*cc == OP_ALT); + /* Fall through */ + + /* Skip over things that don't match chars */ + + case OP_REVERSE: + case OP_BRANUMBER: + case OP_CREF: + case OP_OPT: + case OP_CALLOUT: + case OP_SOD: + case OP_SOM: + case OP_EOD: + case OP_EODN: + case OP_CIRC: + case OP_DOLL: + case OP_NOT_WORD_BOUNDARY: + case OP_WORD_BOUNDARY: + cc += OP_lengths[*cc]; + break; + + /* Handle char strings. In UTF-8 mode we must count characters, not bytes. + This requires a scan of the string, unfortunately. We assume valid UTF-8 + strings, so all we do is reduce the length by one for every byte whose bits + are 10xxxxxx. */ + + case OP_CHARS: + branchlength += *(++cc); +#ifdef SUPPORT_UTF8 + if ((options & PCRE_UTF8) != 0) + for (d = 1; d <= *cc; d++) + if ((cc[d] & 0xc0) == 0x80) branchlength--; +#endif + cc += *cc + 1; + break; + + /* Handle exact repetitions. The count is already in characters, but we + need to skip over a multibyte character in UTF8 mode. */ + + case OP_EXACT: + branchlength += GET2(cc,1); + cc += 4; +#ifdef SUPPORT_UTF8 + if ((options & PCRE_UTF8) != 0) + { + while((*cc & 0x80) == 0x80) cc++; + } +#endif + break; + + case OP_TYPEEXACT: + branchlength += GET2(cc,1); + cc += 4; + break; + + /* Handle single-char matchers */ + + case OP_NOT_DIGIT: + case OP_DIGIT: + case OP_NOT_WHITESPACE: + case OP_WHITESPACE: + case OP_NOT_WORDCHAR: + case OP_WORDCHAR: + case OP_ANY: + branchlength++; + cc++; + break; + + /* The single-byte matcher isn't allowed */ + + case OP_ANYBYTE: + return -2; + + /* Check a class for variable quantification */ + +#ifdef SUPPORT_UTF8 + case OP_XCLASS: + cc += GET(cc, 1) - 33; + /* Fall through */ +#endif + + case OP_CLASS: + case OP_NCLASS: + cc += 33; + + switch (*cc) + { + case OP_CRSTAR: + case OP_CRMINSTAR: + case OP_CRQUERY: + case OP_CRMINQUERY: + return -1; + + case OP_CRRANGE: + case OP_CRMINRANGE: + if (GET2(cc,1) != GET2(cc,3)) return -1; + branchlength += GET2(cc,1); + cc += 5; + break; + + default: + branchlength++; + } + break; + + /* Anything else is variable length */ + + default: + return -1; + } + } +/* Control never gets here */ +} + + + + +/************************************************* +* Scan compiled regex for numbered bracket * +*************************************************/ + +/* This little function scans through a compiled pattern until it finds a +capturing bracket with the given number. + +Arguments: + code points to start of expression + utf8 TRUE in UTF-8 mode + number the required bracket number + +Returns: pointer to the opcode for the bracket, or NULL if not found +*/ + +static const uschar * +find_bracket(const uschar *code, BOOL utf8, int number) +{ +#ifndef SUPPORT_UTF8 +utf8 = utf8; /* Stop pedantic compilers complaining */ +#endif + +for (;;) + { + register int c = *code; + if (c == OP_END) return NULL; + else if (c == OP_CHARS) code += code[1] + OP_lengths[c]; + else if (c > OP_BRA) + { + int n = c - OP_BRA; + if (n > EXTRACT_BASIC_MAX) n = GET2(code, 2+LINK_SIZE); + if (n == number) return (uschar *)code; + code += OP_lengths[OP_BRA]; + } + else + { + code += OP_lengths[c]; + + /* In UTF-8 mode, opcodes that are followed by a character may be followed + by a multi-byte character. The length in the table is a minimum, so we have + to scan along to skip the extra characters. All opcodes are less than 128, + so we can use relatively efficient code. */ + +#ifdef SUPPORT_UTF8 + if (utf8) switch(c) + { + case OP_EXACT: + case OP_UPTO: + case OP_MINUPTO: + case OP_STAR: + case OP_MINSTAR: + case OP_PLUS: + case OP_MINPLUS: + case OP_QUERY: + case OP_MINQUERY: + while ((*code & 0xc0) == 0x80) code++; + break; + } +#endif + } + } +} + + + +/************************************************* +* Scan compiled branch for non-emptiness * +*************************************************/ + +/* This function scans through a branch of a compiled pattern to see whether it +can match the empty string or not. It is called only from could_be_empty() +below. Note that first_significant_code() skips over assertions. If we hit an +unclosed bracket, we return "empty" - this means we've struck an inner bracket +whose current branch will already have been scanned. + +Arguments: + code points to start of search + endcode points to where to stop + utf8 TRUE if in UTF8 mode + +Returns: TRUE if what is matched could be empty +*/ + +static BOOL +could_be_empty_branch(const uschar *code, const uschar *endcode, BOOL utf8) +{ +register int c; +for (code = first_significant_code(code + 1 + LINK_SIZE, NULL, 0); + code < endcode; + code = first_significant_code(code + OP_lengths[c], NULL, 0)) + { + const uschar *ccode; + + c = *code; + + if (c >= OP_BRA) + { + BOOL empty_branch; + if (GET(code, 1) == 0) return TRUE; /* Hit unclosed bracket */ + + /* Scan a closed bracket */ + + empty_branch = FALSE; + do + { + if (!empty_branch && could_be_empty_branch(code, endcode, utf8)) + empty_branch = TRUE; + code += GET(code, 1); + } + while (*code == OP_ALT); + if (!empty_branch) return FALSE; /* All branches are non-empty */ + code += 1 + LINK_SIZE; + c = *code; + } + + else switch (c) + { + /* Check for quantifiers after a class */ + +#ifdef SUPPORT_UTF8 + case OP_XCLASS: + ccode = code + GET(code, 1); + goto CHECK_CLASS_REPEAT; +#endif + + case OP_CLASS: + case OP_NCLASS: + ccode = code + 33; + +#ifdef SUPPORT_UTF8 + CHECK_CLASS_REPEAT: +#endif + + switch (*ccode) + { + case OP_CRSTAR: /* These could be empty; continue */ + case OP_CRMINSTAR: + case OP_CRQUERY: + case OP_CRMINQUERY: + break; + + default: /* Non-repeat => class must match */ + case OP_CRPLUS: /* These repeats aren't empty */ + case OP_CRMINPLUS: + return FALSE; + + case OP_CRRANGE: + case OP_CRMINRANGE: + if (GET2(ccode, 1) > 0) return FALSE; /* Minimum > 0 */ + break; + } + break; + + /* Opcodes that must match a character */ + + case OP_NOT_DIGIT: + case OP_DIGIT: + case OP_NOT_WHITESPACE: + case OP_WHITESPACE: + case OP_NOT_WORDCHAR: + case OP_WORDCHAR: + case OP_ANY: + case OP_ANYBYTE: + case OP_CHARS: + case OP_NOT: + case OP_PLUS: + case OP_MINPLUS: + case OP_EXACT: + case OP_NOTPLUS: + case OP_NOTMINPLUS: + case OP_NOTEXACT: + case OP_TYPEPLUS: + case OP_TYPEMINPLUS: + case OP_TYPEEXACT: + return FALSE; + + /* End of branch */ + + case OP_KET: + case OP_KETRMAX: + case OP_KETRMIN: + case OP_ALT: + return TRUE; + + /* In UTF-8 mode, STAR, MINSTAR, QUERY, MINQUERY, UPTO, and MINUPTO may be + followed by a multibyte character */ + +#ifdef SUPPORT_UTF8 + case OP_STAR: + case OP_MINSTAR: + case OP_QUERY: + case OP_MINQUERY: + case OP_UPTO: + case OP_MINUPTO: + if (utf8) while ((code[2] & 0xc0) == 0x80) code++; + break; +#endif + } + } + +return TRUE; +} + + + +/************************************************* +* Scan compiled regex for non-emptiness * +*************************************************/ + +/* This function is called to check for left recursive calls. We want to check +the current branch of the current pattern to see if it could match the empty +string. If it could, we must look outwards for branches at other levels, +stopping when we pass beyond the bracket which is the subject of the recursion. + +Arguments: + code points to start of the recursion + endcode points to where to stop (current RECURSE item) + bcptr points to the chain of current (unclosed) branch starts + utf8 TRUE if in UTF-8 mode + +Returns: TRUE if what is matched could be empty +*/ + +static BOOL +could_be_empty(const uschar *code, const uschar *endcode, branch_chain *bcptr, + BOOL utf8) +{ +while (bcptr != NULL && bcptr->current >= code) + { + if (!could_be_empty_branch(bcptr->current, endcode, utf8)) return FALSE; + bcptr = bcptr->outer; + } +return TRUE; +} + + + +/************************************************* +* Check for POSIX class syntax * +*************************************************/ + +/* This function is called when the sequence "[:" or "[." or "[=" is +encountered in a character class. It checks whether this is followed by an +optional ^ and then a sequence of letters, terminated by a matching ":]" or +".]" or "=]". + +Argument: + ptr pointer to the initial [ + endptr where to return the end pointer + cd pointer to compile data + +Returns: TRUE or FALSE +*/ + +static BOOL +check_posix_syntax(const uschar *ptr, const uschar **endptr, compile_data *cd) +{ +int terminator; /* Don't combine these lines; the Solaris cc */ +terminator = *(++ptr); /* compiler warns about "non-constant" initializer. */ +if (*(++ptr) == '^') ptr++; +while ((cd->ctypes[*ptr] & ctype_letter) != 0) ptr++; +if (*ptr == terminator && ptr[1] == ']') + { + *endptr = ptr; + return TRUE; + } +return FALSE; +} + + + + +/************************************************* +* Check POSIX class name * +*************************************************/ + +/* This function is called to check the name given in a POSIX-style class entry +such as [:alnum:]. + +Arguments: + ptr points to the first letter + len the length of the name + +Returns: a value representing the name, or -1 if unknown +*/ + +static int +check_posix_name(const uschar *ptr, int len) +{ +register int yield = 0; +while (posix_name_lengths[yield] != 0) + { + if (len == posix_name_lengths[yield] && + strncmp((const char *)ptr, posix_names[yield], len) == 0) return yield; + yield++; + } +return -1; +} + + + + +/************************************************* +* Compile one branch * +*************************************************/ + +/* Scan the pattern, compiling it into the code vector. If the options are +changed during the branch, the pointer is used to change the external options +bits. + +Arguments: + optionsptr pointer to the option bits + brackets points to number of extracting brackets used + code points to the pointer to the current code point + ptrptr points to the current pattern pointer + errorptr points to pointer to error message + firstbyteptr set to initial literal character, or < 0 (REQ_UNSET, REQ_NONE) + reqbyteptr set to the last literal character required, else < 0 + bcptr points to current branch chain + cd contains pointers to tables etc. + +Returns: TRUE on success + FALSE, with *errorptr set on error +*/ + +static BOOL +compile_branch(int *optionsptr, int *brackets, uschar **codeptr, + const uschar **ptrptr, const char **errorptr, int *firstbyteptr, + int *reqbyteptr, branch_chain *bcptr, compile_data *cd) +{ +int repeat_type, op_type; +int repeat_min = 0, repeat_max = 0; /* To please picky compilers */ +int bravalue = 0; +int length; +int greedy_default, greedy_non_default; +int firstbyte, reqbyte; +int zeroreqbyte, zerofirstbyte; +int req_caseopt, reqvary, tempreqvary; +int condcount = 0; +int options = *optionsptr; +register int c; +register uschar *code = *codeptr; +uschar *tempcode; +BOOL inescq = FALSE; +BOOL groupsetfirstbyte = FALSE; +const uschar *ptr = *ptrptr; +const uschar *tempptr; +uschar *previous = NULL; +uschar class[32]; + +#ifdef SUPPORT_UTF8 +BOOL class_utf8; +BOOL utf8 = (options & PCRE_UTF8) != 0; +uschar *class_utf8data; +uschar utf8_char[6]; +#else +BOOL utf8 = FALSE; +#endif + +/* Set up the default and non-default settings for greediness */ + +greedy_default = ((options & PCRE_UNGREEDY) != 0); +greedy_non_default = greedy_default ^ 1; + +/* Initialize no first char, no required char. REQ_UNSET means "no char +matching encountered yet". It gets changed to REQ_NONE if we hit something that +matches a non-fixed char first char; reqbyte just remains unset if we never +find one. + +When we hit a repeat whose minimum is zero, we may have to adjust these values +to take the zero repeat into account. This is implemented by setting them to +zerofirstbyte and zeroreqbyte when such a repeat is encountered. The individual +item types that can be repeated set these backoff variables appropriately. */ + +firstbyte = reqbyte = zerofirstbyte = zeroreqbyte = REQ_UNSET; + +/* The variable req_caseopt contains either the REQ_CASELESS value or zero, +according to the current setting of the caseless flag. REQ_CASELESS is a bit +value > 255. It is added into the firstbyte or reqbyte variables to record the +case status of the value. */ + +req_caseopt = ((options & PCRE_CASELESS) != 0)? REQ_CASELESS : 0; + +/* Switch on next character until the end of the branch */ + +for (;; ptr++) + { + BOOL negate_class; + BOOL possessive_quantifier; + int class_charcount; + int class_lastchar; + int newoptions; + int recno; + int skipbytes; + int subreqbyte; + int subfirstbyte; + + c = *ptr; + if (inescq && c != 0) goto NORMAL_CHAR; + + if ((options & PCRE_EXTENDED) != 0) + { + if ((cd->ctypes[c] & ctype_space) != 0) continue; + if (c == '#') + { + /* The space before the ; is to avoid a warning on a silly compiler + on the Macintosh. */ + while ((c = *(++ptr)) != 0 && c != NEWLINE) ; + if (c != 0) continue; /* Else fall through to handle end of string */ + } + } + + switch(c) + { + /* The branch terminates at end of string, |, or ). */ + + case 0: + case '|': + case ')': + *firstbyteptr = firstbyte; + *reqbyteptr = reqbyte; + *codeptr = code; + *ptrptr = ptr; + return TRUE; + + /* Handle single-character metacharacters. In multiline mode, ^ disables + the setting of any following char as a first character. */ + + case '^': + if ((options & PCRE_MULTILINE) != 0) + { + if (firstbyte == REQ_UNSET) firstbyte = REQ_NONE; + } + previous = NULL; + *code++ = OP_CIRC; + break; + + case '$': + previous = NULL; + *code++ = OP_DOLL; + break; + + /* There can never be a first char if '.' is first, whatever happens about + repeats. The value of reqbyte doesn't change either. */ + + case '.': + if (firstbyte == REQ_UNSET) firstbyte = REQ_NONE; + zerofirstbyte = firstbyte; + zeroreqbyte = reqbyte; + previous = code; + *code++ = OP_ANY; + break; + + /* Character classes. If the included characters are all < 255 in value, we + build a 32-byte bitmap of the permitted characters, except in the special + case where there is only one such character. For negated classes, we build + the map as usual, then invert it at the end. However, we use a different + opcode so that data characters > 255 can be handled correctly. + + If the class contains characters outside the 0-255 range, a different + opcode is compiled. It may optionally have a bit map for characters < 256, + but those above are are explicitly listed afterwards. A flag byte tells + whether the bitmap is present, and whether this is a negated class or not. + */ + + case '[': + previous = code; + + /* PCRE supports POSIX class stuff inside a class. Perl gives an error if + they are encountered at the top level, so we'll do that too. */ + + if ((ptr[1] == ':' || ptr[1] == '.' || ptr[1] == '=') && + check_posix_syntax(ptr, &tempptr, cd)) + { + *errorptr = (ptr[1] == ':')? ERR13 : ERR31; + goto FAILED; + } + + /* If the first character is '^', set the negation flag and skip it. */ + + if ((c = *(++ptr)) == '^') + { + negate_class = TRUE; + c = *(++ptr); + } + else + { + negate_class = FALSE; + } + + /* Keep a count of chars with values < 256 so that we can optimize the case + of just a single character (as long as it's < 256). For higher valued UTF-8 + characters, we don't yet do any optimization. */ + + class_charcount = 0; + class_lastchar = -1; + +#ifdef SUPPORT_UTF8 + class_utf8 = FALSE; /* No chars >= 256 */ + class_utf8data = code + LINK_SIZE + 34; /* For UTF-8 items */ +#endif + + /* Initialize the 32-char bit map to all zeros. We have to build the + map in a temporary bit of store, in case the class contains only 1 + character (< 256), because in that case the compiled code doesn't use the + bit map. */ + + memset(class, 0, 32 * sizeof(uschar)); + + /* Process characters until ] is reached. By writing this as a "do" it + means that an initial ] is taken as a data character. The first pass + through the regex checked the overall syntax, so we don't need to be very + strict here. At the start of the loop, c contains the first byte of the + character. */ + + do + { +#ifdef SUPPORT_UTF8 + if (utf8 && c > 127) + { /* Braces are required because the */ + GETCHARLEN(c, ptr, ptr); /* macro generates multiple statements */ + } +#endif + + /* Inside \Q...\E everything is literal except \E */ + + if (inescq) + { + if (c == '\\' && ptr[1] == 'E') + { + inescq = FALSE; + ptr++; + continue; + } + else goto LONE_SINGLE_CHARACTER; + } + + /* Handle POSIX class names. Perl allows a negation extension of the + form [:^name:]. A square bracket that doesn't match the syntax is + treated as a literal. We also recognize the POSIX constructions + [.ch.] and [=ch=] ("collating elements") and fault them, as Perl + 5.6 and 5.8 do. */ + + if (c == '[' && + (ptr[1] == ':' || ptr[1] == '.' || ptr[1] == '=') && + check_posix_syntax(ptr, &tempptr, cd)) + { + BOOL local_negate = FALSE; + int posix_class, i; + register const uschar *cbits = cd->cbits; + + if (ptr[1] != ':') + { + *errorptr = ERR31; + goto FAILED; + } + + ptr += 2; + if (*ptr == '^') + { + local_negate = TRUE; + ptr++; + } + + posix_class = check_posix_name(ptr, tempptr - ptr); + if (posix_class < 0) + { + *errorptr = ERR30; + goto FAILED; + } + + /* If matching is caseless, upper and lower are converted to + alpha. This relies on the fact that the class table starts with + alpha, lower, upper as the first 3 entries. */ + + if ((options & PCRE_CASELESS) != 0 && posix_class <= 2) + posix_class = 0; + + /* Or into the map we are building up to 3 of the static class + tables, or their negations. The [:blank:] class sets up the same + chars as the [:space:] class (all white space). We remove the vertical + white space chars afterwards. */ + + posix_class *= 3; + for (i = 0; i < 3; i++) + { + BOOL isblank = strncmp((char *)ptr, "blank", 5) == 0; + int taboffset = posix_class_maps[posix_class + i]; + if (taboffset < 0) break; + if (local_negate) + { + for (c = 0; c < 32; c++) class[c] |= ~cbits[c+taboffset]; + if (isblank) class[1] |= 0x3c; + } + else + { + for (c = 0; c < 32; c++) class[c] |= cbits[c+taboffset]; + if (isblank) class[1] &= ~0x3c; + } + } + + ptr = tempptr + 1; + class_charcount = 10; /* Set > 1; assumes more than 1 per class */ + continue; /* End of POSIX syntax handling */ + } + + /* Backslash may introduce a single character, or it may introduce one + of the specials, which just set a flag. Escaped items are checked for + validity in the pre-compiling pass. The sequence \b is a special case. + Inside a class (and only there) it is treated as backspace. Elsewhere + it marks a word boundary. Other escapes have preset maps ready to + or into the one we are building. We assume they have more than one + character in them, so set class_charcount bigger than one. */ + + if (c == '\\') + { + c = check_escape(&ptr, errorptr, *brackets, options, TRUE, cd); + if (-c == ESC_b) c = '\b'; /* \b is backslash in a class */ + + if (-c == ESC_Q) /* Handle start of quoted string */ + { + if (ptr[1] == '\\' && ptr[2] == 'E') + { + ptr += 2; /* avoid empty string */ + } + else inescq = TRUE; + continue; + } + + else if (c < 0) + { + register const uschar *cbits = cd->cbits; + class_charcount = 10; /* Greater than 1 is what matters */ + switch (-c) + { + case ESC_d: + for (c = 0; c < 32; c++) class[c] |= cbits[c+cbit_digit]; + continue; + + case ESC_D: + for (c = 0; c < 32; c++) class[c] |= ~cbits[c+cbit_digit]; + continue; + + case ESC_w: + for (c = 0; c < 32; c++) class[c] |= cbits[c+cbit_word]; + continue; + + case ESC_W: + for (c = 0; c < 32; c++) class[c] |= ~cbits[c+cbit_word]; + continue; + + case ESC_s: + for (c = 0; c < 32; c++) class[c] |= cbits[c+cbit_space]; + class[1] &= ~0x08; /* Perl 5.004 onwards omits VT from \s */ + continue; + + case ESC_S: + for (c = 0; c < 32; c++) class[c] |= ~cbits[c+cbit_space]; + class[1] |= 0x08; /* Perl 5.004 onwards omits VT from \s */ + continue; + + /* Unrecognized escapes are faulted if PCRE is running in its + strict mode. By default, for compatibility with Perl, they are + treated as literals. */ + + default: + if ((options & PCRE_EXTRA) != 0) + { + *errorptr = ERR7; + goto FAILED; + } + c = *ptr; /* The final character */ + } + } + + /* Fall through if we have a single character (c >= 0). This may be + > 256 in UTF-8 mode. */ + + } /* End of backslash handling */ + + /* A single character may be followed by '-' to form a range. However, + Perl does not permit ']' to be the end of the range. A '-' character + here is treated as a literal. */ + + if (ptr[1] == '-' && ptr[2] != ']') + { + int d; + ptr += 2; + +#ifdef SUPPORT_UTF8 + if (utf8) + { /* Braces are required because the */ + GETCHARLEN(d, ptr, ptr); /* macro generates multiple statements */ + } + else +#endif + d = *ptr; + + /* The second part of a range can be a single-character escape, but + not any of the other escapes. Perl 5.6 treats a hyphen as a literal + in such circumstances. */ + + if (d == '\\') + { + const uschar *oldptr = ptr; + d = check_escape(&ptr, errorptr, *brackets, options, TRUE, cd); + + /* \b is backslash; any other special means the '-' was literal */ + + if (d < 0) + { + if (d == -ESC_b) d = '\b'; else + { + ptr = oldptr - 2; + goto LONE_SINGLE_CHARACTER; /* A few lines below */ + } + } + } + + /* Check that the two values are in the correct order */ + + if (d < c) + { + *errorptr = ERR8; + goto FAILED; + } + + /* If d is greater than 255, we can't just use the bit map, so set up + for the UTF-8 supporting class type. If we are not caseless, we can + just set up a single range. If we are caseless, the characters < 256 + are handled with a bitmap, in order to get the case-insensitive + handling. */ + +#ifdef SUPPORT_UTF8 + if (d > 255) + { + class_utf8 = TRUE; + *class_utf8data++ = XCL_RANGE; + if ((options & PCRE_CASELESS) == 0) + { + class_utf8data += ord2utf8(c, class_utf8data); + class_utf8data += ord2utf8(d, class_utf8data); + continue; /* Go get the next char in the class */ + } + class_utf8data += ord2utf8(256, class_utf8data); + class_utf8data += ord2utf8(d, class_utf8data); + d = 255; + /* Fall through */ + } +#endif + /* We use the bit map if the range is entirely < 255, or if part of it + is < 255 and matching is caseless. */ + + for (; c <= d; c++) + { + class[c/8] |= (1 << (c&7)); + if ((options & PCRE_CASELESS) != 0) + { + int uc = cd->fcc[c]; /* flip case */ + class[uc/8] |= (1 << (uc&7)); + } + class_charcount++; /* in case a one-char range */ + class_lastchar = c; + } + + continue; /* Go get the next char in the class */ + } + + /* Handle a lone single character - we can get here for a normal + non-escape char, or after \ that introduces a single character. */ + + LONE_SINGLE_CHARACTER: + + /* Handle a multibyte character */ + +#ifdef SUPPORT_UTF8 + if (utf8 && c > 255) + { + class_utf8 = TRUE; + *class_utf8data++ = XCL_SINGLE; + class_utf8data += ord2utf8(c, class_utf8data); + } + else +#endif + /* Handle a single-byte character */ + { + class [c/8] |= (1 << (c&7)); + if ((options & PCRE_CASELESS) != 0) + { + c = cd->fcc[c]; /* flip case */ + class[c/8] |= (1 << (c&7)); + } + class_charcount++; + class_lastchar = c; + } + } + + /* Loop until ']' reached; the check for end of string happens inside the + loop. This "while" is the end of the "do" above. */ + + while ((c = *(++ptr)) != ']' || inescq); + + /* If class_charcount is 1, we saw precisely one character with a value < + 256. In UTF-8 mode, we can optimize if there were no characters >= 256 and + the one character is < 128. In non-UTF-8 mode we can always optimize. + + The optimization throws away the bit map. We turn the item into a + 1-character OP_CHARS if it's positive, or OP_NOT if it's negative. Note + that OP_NOT does not support multibyte characters. In the positive case, it + can cause firstbyte to be set. Otherwise, there can be no first char if + this item is first, whatever repeat count may follow. In the case of + reqbyte, save the previous value for reinstating. */ + +#ifdef SUPPORT_UTF8 + if (class_charcount == 1 && + (!utf8 || + (!class_utf8 && class_lastchar < 128))) +#else + if (class_charcount == 1) +#endif + { + zeroreqbyte = reqbyte; + if (negate_class) + { + if (firstbyte == REQ_UNSET) firstbyte = REQ_NONE; + zerofirstbyte = firstbyte; + *code++ = OP_NOT; + } + else + { + if (firstbyte == REQ_UNSET) + { + zerofirstbyte = REQ_NONE; + firstbyte = class_lastchar | req_caseopt; + } + else + { + zerofirstbyte = firstbyte; + reqbyte = class_lastchar | req_caseopt | cd->req_varyopt; + } + *code++ = OP_CHARS; + *code++ = 1; + } + *code++ = class_lastchar; + break; /* End of class handling */ + } /* End of 1-byte optimization */ + + /* Otherwise, if this is the first thing in the branch, there can be no + first char setting, whatever the repeat count. Any reqbyte setting must + remain unchanged after any kind of repeat. */ + + if (firstbyte == REQ_UNSET) firstbyte = REQ_NONE; + zerofirstbyte = firstbyte; + zeroreqbyte = reqbyte; + + /* If there are characters with values > 255, we have to compile an + extended class, with its own opcode. If there are no characters < 256, + we can omit the bitmap. */ + +#ifdef SUPPORT_UTF8 + if (class_utf8) + { + *class_utf8data++ = XCL_END; /* Marks the end of extra data */ + *code++ = OP_XCLASS; + code += LINK_SIZE; + *code = negate_class? XCL_NOT : 0; + + /* If the map is required, install it, and move on to the end of + the extra data */ + + if (class_charcount > 0) + { + *code++ |= XCL_MAP; + memcpy(code, class, 32); + code = class_utf8data; + } + + /* If the map is not required, slide down the extra data. */ + + else + { + int len = class_utf8data - (code + 33); + memmove(code + 1, code + 33, len); + code += len + 1; + } + + /* Now fill in the complete length of the item */ + + PUT(previous, 1, code - previous); + break; /* End of class handling */ + } +#endif + + /* If there are no characters > 255, negate the 32-byte map if necessary, + and copy it into the code vector. If this is the first thing in the branch, + there can be no first char setting, whatever the repeat count. Any reqbyte + setting must remain unchanged after any kind of repeat. */ + + if (negate_class) + { + *code++ = OP_NCLASS; + for (c = 0; c < 32; c++) code[c] = ~class[c]; + } + else + { + *code++ = OP_CLASS; + memcpy(code, class, 32); + } + code += 32; + break; + + /* Various kinds of repeat */ + + case '{': + if (!is_counted_repeat(ptr+1, cd)) goto NORMAL_CHAR; + ptr = read_repeat_counts(ptr+1, &repeat_min, &repeat_max, errorptr, cd); + if (*errorptr != NULL) goto FAILED; + goto REPEAT; + + case '*': + repeat_min = 0; + repeat_max = -1; + goto REPEAT; + + case '+': + repeat_min = 1; + repeat_max = -1; + goto REPEAT; + + case '?': + repeat_min = 0; + repeat_max = 1; + + REPEAT: + if (previous == NULL) + { + *errorptr = ERR9; + goto FAILED; + } + + if (repeat_min == 0) + { + firstbyte = zerofirstbyte; /* Adjust for zero repeat */ + reqbyte = zeroreqbyte; /* Ditto */ + } + + /* Remember whether this is a variable length repeat */ + + reqvary = (repeat_min == repeat_max)? 0 : REQ_VARY; + + op_type = 0; /* Default single-char op codes */ + possessive_quantifier = FALSE; /* Default not possessive quantifier */ + + /* Save start of previous item, in case we have to move it up to make space + for an inserted OP_ONCE for the additional '+' extension. */ + + tempcode = previous; + + /* If the next character is '+', we have a possessive quantifier. This + implies greediness, whatever the setting of the PCRE_UNGREEDY option. + If the next character is '?' this is a minimizing repeat, by default, + but if PCRE_UNGREEDY is set, it works the other way round. We change the + repeat type to the non-default. */ + + if (ptr[1] == '+') + { + repeat_type = 0; /* Force greedy */ + possessive_quantifier = TRUE; + ptr++; + } + else if (ptr[1] == '?') + { + repeat_type = greedy_non_default; + ptr++; + } + else repeat_type = greedy_default; + + /* If previous was a recursion, we need to wrap it inside brackets so that + it can be replicated if necessary. */ + + if (*previous == OP_RECURSE) + { + memmove(previous + 1 + LINK_SIZE, previous, 1 + LINK_SIZE); + code += 1 + LINK_SIZE; + *previous = OP_BRA; + PUT(previous, 1, code - previous); + *code = OP_KET; + PUT(code, 1, code - previous); + code += 1 + LINK_SIZE; + } + + /* If previous was a string of characters, chop off the last one and use it + as the subject of the repeat. If there was only one character, we can + abolish the previous item altogether. If a one-char item has a minumum of + more than one, ensure that it is set in reqbyte - it might not be if a + sequence such as x{3} is the first thing in a branch because the x will + have gone into firstbyte instead. */ + + if (*previous == OP_CHARS) + { + /* Deal with UTF-8 characters that take up more than one byte. It's + easier to write this out separately than try to macrify it. Use c to + hold the length of the character in bytes, plus 0x80 to flag that it's a + length rather than a small character. */ + +#ifdef SUPPORT_UTF8 + if (utf8 && (code[-1] & 0x80) != 0) + { + uschar *lastchar = code - 1; + while((*lastchar & 0xc0) == 0x80) lastchar--; + c = code - lastchar; /* Length of UTF-8 character */ + memcpy(utf8_char, lastchar, c); /* Save the char */ + if (lastchar == previous + 2) /* There was only one character */ + { + code = previous; /* Abolish the previous item */ + } + else + { + previous[1] -= c; /* Adjust length of previous */ + code = lastchar; /* Lost char off the end */ + tempcode = code; /* Adjust position to be moved for '+' */ + } + c |= 0x80; /* Flag c as a length */ + } + else +#endif + + /* Handle the case of a single byte - either with no UTF8 support, or + with UTF-8 disabled, or for a UTF-8 character < 128. */ + + { + c = *(--code); + if (code == previous + 2) /* There was only one character */ + { + code = previous; /* Abolish the previous item */ + if (repeat_min > 1) reqbyte = c | req_caseopt | cd->req_varyopt; + } + else + { + previous[1]--; /* adjust length */ + tempcode = code; /* Adjust position to be moved for '+' */ + } + } + + goto OUTPUT_SINGLE_REPEAT; /* Code shared with single character types */ + } + + /* If previous was a single negated character ([^a] or similar), we use + one of the special opcodes, replacing it. The code is shared with single- + character repeats by setting opt_type to add a suitable offset into + repeat_type. OP_NOT is currently used only for single-byte chars. */ + + else if (*previous == OP_NOT) + { + op_type = OP_NOTSTAR - OP_STAR; /* Use "not" opcodes */ + c = previous[1]; + code = previous; + goto OUTPUT_SINGLE_REPEAT; + } + + /* If previous was a character type match (\d or similar), abolish it and + create a suitable repeat item. The code is shared with single-character + repeats by setting op_type to add a suitable offset into repeat_type. */ + + else if (*previous < OP_EODN) + { + op_type = OP_TYPESTAR - OP_STAR; /* Use type opcodes */ + c = *previous; + code = previous; + + OUTPUT_SINGLE_REPEAT: + + /* If the maximum is zero then the minimum must also be zero; Perl allows + this case, so we do too - by simply omitting the item altogether. */ + + if (repeat_max == 0) goto END_REPEAT; + + /* Combine the op_type with the repeat_type */ + + repeat_type += op_type; + + /* A minimum of zero is handled either as the special case * or ?, or as + an UPTO, with the maximum given. */ + + if (repeat_min == 0) + { + if (repeat_max == -1) *code++ = OP_STAR + repeat_type; + else if (repeat_max == 1) *code++ = OP_QUERY + repeat_type; + else + { + *code++ = OP_UPTO + repeat_type; + PUT2INC(code, 0, repeat_max); + } + } + + /* The case {1,} is handled as the special case + */ + + else if (repeat_min == 1 && repeat_max == -1) + *code++ = OP_PLUS + repeat_type; + + /* The case {n,n} is just an EXACT, while the general case {n,m} is + handled as an EXACT followed by an UPTO. An EXACT of 1 is optimized. */ + + else + { + if (repeat_min != 1) + { + *code++ = OP_EXACT + op_type; /* NB EXACT doesn't have repeat_type */ + PUT2INC(code, 0, repeat_min); + } + + /* If the mininum is 1 and the previous item was a character string, + we either have to put back the item that got cancelled if the string + length was 1, or add the character back onto the end of a longer + string. For a character type nothing need be done; it will just get + put back naturally. Note that the final character is always going to + get added below, so we leave code ready for its insertion. */ + + else if (*previous == OP_CHARS) + { + if (code == previous) code += 2; else + + /* In UTF-8 mode, a multibyte char has its length in c, with the 0x80 + bit set as a flag. The length will always be between 2 and 6. */ + +#ifdef SUPPORT_UTF8 + if (utf8 && c >= 128) previous[1] += c & 7; else +#endif + previous[1]++; + } + + /* For a single negated character we also have to put back the + item that got cancelled. At present this applies only to single byte + characters in any mode. */ + + else if (*previous == OP_NOT) code++; + + /* If the maximum is unlimited, insert an OP_STAR. Before doing so, + we have to insert the character for the previous code. In UTF-8 mode, + long characters have their length in c, with the 0x80 bit as a flag. */ + + if (repeat_max < 0) + { +#ifdef SUPPORT_UTF8 + if (utf8 && c >= 128) + { + memcpy(code, utf8_char, c & 7); + code += c & 7; + } + else +#endif + *code++ = c; + *code++ = OP_STAR + repeat_type; + } + + /* Else insert an UPTO if the max is greater than the min, again + preceded by the character, for the previously inserted code. */ + + else if (repeat_max != repeat_min) + { +#ifdef SUPPORT_UTF8 + if (utf8 && c >= 128) + { + memcpy(code, utf8_char, c & 7); + code += c & 7; + } + else +#endif + *code++ = c; + repeat_max -= repeat_min; + *code++ = OP_UPTO + repeat_type; + PUT2INC(code, 0, repeat_max); + } + } + + /* The character or character type itself comes last in all cases. */ + +#ifdef SUPPORT_UTF8 + if (utf8 && c >= 128) + { + memcpy(code, utf8_char, c & 7); + code += c & 7; + } + else +#endif + + *code++ = c; + } + + /* If previous was a character class or a back reference, we put the repeat + stuff after it, but just skip the item if the repeat was {0,0}. */ + + else if (*previous == OP_CLASS || + *previous == OP_NCLASS || +#ifdef SUPPORT_UTF8 + *previous == OP_XCLASS || +#endif + *previous == OP_REF) + { + if (repeat_max == 0) + { + code = previous; + goto END_REPEAT; + } + if (repeat_min == 0 && repeat_max == -1) + *code++ = OP_CRSTAR + repeat_type; + else if (repeat_min == 1 && repeat_max == -1) + *code++ = OP_CRPLUS + repeat_type; + else if (repeat_min == 0 && repeat_max == 1) + *code++ = OP_CRQUERY + repeat_type; + else + { + *code++ = OP_CRRANGE + repeat_type; + PUT2INC(code, 0, repeat_min); + if (repeat_max == -1) repeat_max = 0; /* 2-byte encoding for max */ + PUT2INC(code, 0, repeat_max); + } + } + + /* If previous was a bracket group, we may have to replicate it in certain + cases. */ + + else if (*previous >= OP_BRA || *previous == OP_ONCE || + *previous == OP_COND) + { + register int i; + int ketoffset = 0; + int len = code - previous; + uschar *bralink = NULL; + + /* If the maximum repeat count is unlimited, find the end of the bracket + by scanning through from the start, and compute the offset back to it + from the current code pointer. There may be an OP_OPT setting following + the final KET, so we can't find the end just by going back from the code + pointer. */ + + if (repeat_max == -1) + { + register uschar *ket = previous; + do ket += GET(ket, 1); while (*ket != OP_KET); + ketoffset = code - ket; + } + + /* The case of a zero minimum is special because of the need to stick + OP_BRAZERO in front of it, and because the group appears once in the + data, whereas in other cases it appears the minimum number of times. For + this reason, it is simplest to treat this case separately, as otherwise + the code gets far too messy. There are several special subcases when the + minimum is zero. */ + + if (repeat_min == 0) + { + /* If the maximum is also zero, we just omit the group from the output + altogether. */ + + if (repeat_max == 0) + { + code = previous; + goto END_REPEAT; + } + + /* If the maximum is 1 or unlimited, we just have to stick in the + BRAZERO and do no more at this point. */ + + if (repeat_max <= 1) + { + memmove(previous+1, previous, len); + code++; + *previous++ = OP_BRAZERO + repeat_type; + } + + /* If the maximum is greater than 1 and limited, we have to replicate + in a nested fashion, sticking OP_BRAZERO before each set of brackets. + The first one has to be handled carefully because it's the original + copy, which has to be moved up. The remainder can be handled by code + that is common with the non-zero minimum case below. We just have to + adjust the value or repeat_max, since one less copy is required. */ + + else + { + int offset; + memmove(previous + 2 + LINK_SIZE, previous, len); + code += 2 + LINK_SIZE; + *previous++ = OP_BRAZERO + repeat_type; + *previous++ = OP_BRA; + + /* We chain together the bracket offset fields that have to be + filled in later when the ends of the brackets are reached. */ + + offset = (bralink == NULL)? 0 : previous - bralink; + bralink = previous; + PUTINC(previous, 0, offset); + } + + repeat_max--; + } + + /* If the minimum is greater than zero, replicate the group as many + times as necessary, and adjust the maximum to the number of subsequent + copies that we need. If we set a first char from the group, and didn't + set a required char, copy the latter from the former. */ + + else + { + if (repeat_min > 1) + { + if (groupsetfirstbyte && reqbyte < 0) reqbyte = firstbyte; + for (i = 1; i < repeat_min; i++) + { + memcpy(code, previous, len); + code += len; + } + } + if (repeat_max > 0) repeat_max -= repeat_min; + } + + /* This code is common to both the zero and non-zero minimum cases. If + the maximum is limited, it replicates the group in a nested fashion, + remembering the bracket starts on a stack. In the case of a zero minimum, + the first one was set up above. In all cases the repeat_max now specifies + the number of additional copies needed. */ + + if (repeat_max >= 0) + { + for (i = repeat_max - 1; i >= 0; i--) + { + *code++ = OP_BRAZERO + repeat_type; + + /* All but the final copy start a new nesting, maintaining the + chain of brackets outstanding. */ + + if (i != 0) + { + int offset; + *code++ = OP_BRA; + offset = (bralink == NULL)? 0 : code - bralink; + bralink = code; + PUTINC(code, 0, offset); + } + + memcpy(code, previous, len); + code += len; + } + + /* Now chain through the pending brackets, and fill in their length + fields (which are holding the chain links pro tem). */ + + while (bralink != NULL) + { + int oldlinkoffset; + int offset = code - bralink + 1; + uschar *bra = code - offset; + oldlinkoffset = GET(bra, 1); + bralink = (oldlinkoffset == 0)? NULL : bralink - oldlinkoffset; + *code++ = OP_KET; + PUTINC(code, 0, offset); + PUT(bra, 1, offset); + } + } + + /* If the maximum is unlimited, set a repeater in the final copy. We + can't just offset backwards from the current code point, because we + don't know if there's been an options resetting after the ket. The + correct offset was computed above. */ + + else code[-ketoffset] = OP_KETRMAX + repeat_type; + } + + /* Else there's some kind of shambles */ + + else + { + *errorptr = ERR11; + goto FAILED; + } + + /* If the character following a repeat is '+', we wrap the entire repeated + item inside OP_ONCE brackets. This is just syntactic sugar, taken from + Sun's Java package. The repeated item starts at tempcode, not at previous, + which might be the first part of a string whose (former) last char we + repeated. However, we don't support '+' after a greediness '?'. */ + + if (possessive_quantifier) + { + int len = code - tempcode; + memmove(tempcode + 1+LINK_SIZE, tempcode, len); + code += 1 + LINK_SIZE; + len += 1 + LINK_SIZE; + tempcode[0] = OP_ONCE; + *code++ = OP_KET; + PUTINC(code, 0, len); + PUT(tempcode, 1, len); + } + + /* In all case we no longer have a previous item. We also set the + "follows varying string" flag for subsequently encountered reqbytes if + it isn't already set and we have just passed a varying length item. */ + + END_REPEAT: + previous = NULL; + cd->req_varyopt |= reqvary; + break; + + + /* Start of nested bracket sub-expression, or comment or lookahead or + lookbehind or option setting or condition. First deal with special things + that can come after a bracket; all are introduced by ?, and the appearance + of any of them means that this is not a referencing group. They were + checked for validity in the first pass over the string, so we don't have to + check for syntax errors here. */ + + case '(': + newoptions = options; + skipbytes = 0; + + if (*(++ptr) == '?') + { + int set, unset; + int *optset; + + switch (*(++ptr)) + { + case '#': /* Comment; skip to ket */ + ptr++; + while (*ptr != ')') ptr++; + continue; + + case ':': /* Non-extracting bracket */ + bravalue = OP_BRA; + ptr++; + break; + + case '(': + bravalue = OP_COND; /* Conditional group */ + + /* Condition to test for recursion */ + + if (ptr[1] == 'R') + { + code[1+LINK_SIZE] = OP_CREF; + PUT2(code, 2+LINK_SIZE, CREF_RECURSE); + skipbytes = 3; + ptr += 3; + } + + /* Condition to test for a numbered subpattern match. We know that + if a digit follows ( then there will just be digits until ) because + the syntax was checked in the first pass. */ + + else if ((digitab[ptr[1]] && ctype_digit) != 0) + { + int condref; /* Don't amalgamate; some compilers */ + condref = *(++ptr) - '0'; /* grumble at autoincrement in declaration */ + while (*(++ptr) != ')') condref = condref*10 + *ptr - '0'; + if (condref == 0) + { + *errorptr = ERR35; + goto FAILED; + } + ptr++; + code[1+LINK_SIZE] = OP_CREF; + PUT2(code, 2+LINK_SIZE, condref); + skipbytes = 3; + } + /* For conditions that are assertions, we just fall through, having + set bravalue above. */ + break; + + case '=': /* Positive lookahead */ + bravalue = OP_ASSERT; + ptr++; + break; + + case '!': /* Negative lookahead */ + bravalue = OP_ASSERT_NOT; + ptr++; + break; + + case '<': /* Lookbehinds */ + switch (*(++ptr)) + { + case '=': /* Positive lookbehind */ + bravalue = OP_ASSERTBACK; + ptr++; + break; + + case '!': /* Negative lookbehind */ + bravalue = OP_ASSERTBACK_NOT; + ptr++; + break; + } + break; + + case '>': /* One-time brackets */ + bravalue = OP_ONCE; + ptr++; + break; + + case 'C': /* Callout - may be followed by digits */ + *code++ = OP_CALLOUT; + { + int n = 0; + while ((digitab[*(++ptr)] & ctype_digit) != 0) + n = n * 10 + *ptr - '0'; + if (n > 255) + { + *errorptr = ERR38; + goto FAILED; + } + *code++ = n; + } + previous = NULL; + continue; + + case 'P': /* Named subpattern handling */ + if (*(++ptr) == '<') /* Definition */ + { + int i, namelen; + uschar *slot = cd->name_table; + const uschar *name; /* Don't amalgamate; some compilers */ + name = ++ptr; /* grumble at autoincrement in declaration */ + + while (*ptr++ != '>'); + namelen = ptr - name - 1; + + for (i = 0; i < cd->names_found; i++) + { + int crc = memcmp(name, slot+2, namelen); + if (crc == 0) + { + if (slot[2+namelen] == 0) + { + *errorptr = ERR43; + goto FAILED; + } + crc = -1; /* Current name is substring */ + } + if (crc < 0) + { + memmove(slot + cd->name_entry_size, slot, + (cd->names_found - i) * cd->name_entry_size); + break; + } + slot += cd->name_entry_size; + } + + PUT2(slot, 0, *brackets + 1); + memcpy(slot + 2, name, namelen); + slot[2+namelen] = 0; + cd->names_found++; + goto NUMBERED_GROUP; + } + + if (*ptr == '=' || *ptr == '>') /* Reference or recursion */ + { + int i, namelen; + int type = *ptr++; + const uschar *name = ptr; + uschar *slot = cd->name_table; + + while (*ptr != ')') ptr++; + namelen = ptr - name; + + for (i = 0; i < cd->names_found; i++) + { + if (strncmp((char *)name, (char *)slot+2, namelen) == 0) break; + slot += cd->name_entry_size; + } + if (i >= cd->names_found) + { + *errorptr = ERR15; + goto FAILED; + } + + recno = GET2(slot, 0); + + if (type == '>') goto HANDLE_RECURSION; /* A few lines below */ + + /* Back reference */ + + previous = code; + *code++ = OP_REF; + PUT2INC(code, 0, recno); + cd->backref_map |= (recno < 32)? (1 << recno) : 1; + if (recno > cd->top_backref) cd->top_backref = recno; + continue; + } + + /* Should never happen */ + break; + + case 'R': /* Pattern recursion */ + ptr++; /* Same as (?0) */ + /* Fall through */ + + /* Recursion or "subroutine" call */ + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + { + const uschar *called; + recno = 0; + while((digitab[*ptr] & ctype_digit) != 0) + recno = recno * 10 + *ptr++ - '0'; + + /* Come here from code above that handles a named recursion */ + + HANDLE_RECURSION: + + previous = code; + + /* Find the bracket that is being referenced. Temporarily end the + regex in case it doesn't exist. */ + + *code = OP_END; + called = (recno == 0)? + cd->start_code : find_bracket(cd->start_code, utf8, recno); + + if (called == NULL) + { + *errorptr = ERR15; + goto FAILED; + } + + /* If the subpattern is still open, this is a recursive call. We + check to see if this is a left recursion that could loop for ever, + and diagnose that case. */ + + if (GET(called, 1) == 0 && could_be_empty(called, code, bcptr, utf8)) + { + *errorptr = ERR40; + goto FAILED; + } + + /* Insert the recursion/subroutine item */ + + *code = OP_RECURSE; + PUT(code, 1, called - cd->start_code); + code += 1 + LINK_SIZE; + } + continue; + + /* Character after (? not specially recognized */ + + default: /* Option setting */ + set = unset = 0; + optset = &set; + + while (*ptr != ')' && *ptr != ':') + { + switch (*ptr++) + { + case '-': optset = &unset; break; + + case 'i': *optset |= PCRE_CASELESS; break; + case 'm': *optset |= PCRE_MULTILINE; break; + case 's': *optset |= PCRE_DOTALL; break; + case 'x': *optset |= PCRE_EXTENDED; break; + case 'U': *optset |= PCRE_UNGREEDY; break; + case 'X': *optset |= PCRE_EXTRA; break; + } + } + + /* Set up the changed option bits, but don't change anything yet. */ + + newoptions = (options | set) & (~unset); + + /* If the options ended with ')' this is not the start of a nested + group with option changes, so the options change at this level. Compile + code to change the ims options if this setting actually changes any of + them. We also pass the new setting back so that it can be put at the + start of any following branches, and when this group ends (if we are in + a group), a resetting item can be compiled. + + Note that if this item is right at the start of the pattern, the + options will have been abstracted and made global, so there will be no + change to compile. */ + + if (*ptr == ')') + { + if ((options & PCRE_IMS) != (newoptions & PCRE_IMS)) + { + *code++ = OP_OPT; + *code++ = newoptions & PCRE_IMS; + } + + /* Change options at this level, and pass them back for use + in subsequent branches. Reset the greedy defaults and the case + value for firstbyte and reqbyte. */ + + *optionsptr = options = newoptions; + greedy_default = ((newoptions & PCRE_UNGREEDY) != 0); + greedy_non_default = greedy_default ^ 1; + req_caseopt = ((options & PCRE_CASELESS) != 0)? REQ_CASELESS : 0; + + previous = NULL; /* This item can't be repeated */ + continue; /* It is complete */ + } + + /* If the options ended with ':' we are heading into a nested group + with possible change of options. Such groups are non-capturing and are + not assertions of any kind. All we need to do is skip over the ':'; + the newoptions value is handled below. */ + + bravalue = OP_BRA; + ptr++; + } + } + + /* If PCRE_NO_AUTO_CAPTURE is set, all unadorned brackets become + non-capturing and behave like (?:...) brackets */ + + else if ((options & PCRE_NO_AUTO_CAPTURE) != 0) + { + bravalue = OP_BRA; + } + + /* Else we have a referencing group; adjust the opcode. If the bracket + number is greater than EXTRACT_BASIC_MAX, we set the opcode one higher, and + arrange for the true number to follow later, in an OP_BRANUMBER item. */ + + else + { + NUMBERED_GROUP: + if (++(*brackets) > EXTRACT_BASIC_MAX) + { + bravalue = OP_BRA + EXTRACT_BASIC_MAX + 1; + code[1+LINK_SIZE] = OP_BRANUMBER; + PUT2(code, 2+LINK_SIZE, *brackets); + skipbytes = 3; + } + else bravalue = OP_BRA + *brackets; + } + + /* Process nested bracketed re. Assertions may not be repeated, but other + kinds can be. We copy code into a non-register variable in order to be able + to pass its address because some compilers complain otherwise. Pass in a + new setting for the ims options if they have changed. */ + + previous = (bravalue >= OP_ONCE)? code : NULL; + *code = bravalue; + tempcode = code; + tempreqvary = cd->req_varyopt; /* Save value before bracket */ + + if (!compile_regex( + newoptions, /* The complete new option state */ + options & PCRE_IMS, /* The previous ims option state */ + brackets, /* Extracting bracket count */ + &tempcode, /* Where to put code (updated) */ + &ptr, /* Input pointer (updated) */ + errorptr, /* Where to put an error message */ + (bravalue == OP_ASSERTBACK || + bravalue == OP_ASSERTBACK_NOT), /* TRUE if back assert */ + skipbytes, /* Skip over OP_COND/OP_BRANUMBER */ + &subfirstbyte, /* For possible first char */ + &subreqbyte, /* For possible last char */ + bcptr, /* Current branch chain */ + cd)) /* Tables block */ + goto FAILED; + + /* At the end of compiling, code is still pointing to the start of the + group, while tempcode has been updated to point past the end of the group + and any option resetting that may follow it. The pattern pointer (ptr) + is on the bracket. */ + + /* If this is a conditional bracket, check that there are no more than + two branches in the group. */ + + else if (bravalue == OP_COND) + { + uschar *tc = code; + condcount = 0; + + do { + condcount++; + tc += GET(tc,1); + } + while (*tc != OP_KET); + + if (condcount > 2) + { + *errorptr = ERR27; + goto FAILED; + } + + /* If there is just one branch, we must not make use of its firstbyte or + reqbyte, because this is equivalent to an empty second branch. */ + + if (condcount == 1) subfirstbyte = subreqbyte = REQ_NONE; + } + + /* Handle updating of the required and first characters. Update for normal + brackets of all kinds, and conditions with two branches (see code above). + If the bracket is followed by a quantifier with zero repeat, we have to + back off. Hence the definition of zeroreqbyte and zerofirstbyte outside the + main loop so that they can be accessed for the back off. */ + + zeroreqbyte = reqbyte; + zerofirstbyte = firstbyte; + groupsetfirstbyte = FALSE; + + if (bravalue >= OP_BRA || bravalue == OP_ONCE || bravalue == OP_COND) + { + /* If we have not yet set a firstbyte in this branch, take it from the + subpattern, remembering that it was set here so that a repeat of more + than one can replicate it as reqbyte if necessary. If the subpattern has + no firstbyte, set "none" for the whole branch. In both cases, a zero + repeat forces firstbyte to "none". */ + + if (firstbyte == REQ_UNSET) + { + if (subfirstbyte >= 0) + { + firstbyte = subfirstbyte; + groupsetfirstbyte = TRUE; + } + else firstbyte = REQ_NONE; + zerofirstbyte = REQ_NONE; + } + + /* If firstbyte was previously set, convert the subpattern's firstbyte + into reqbyte if there wasn't one, using the vary flag that was in + existence beforehand. */ + + else if (subfirstbyte >= 0 && subreqbyte < 0) + subreqbyte = subfirstbyte | tempreqvary; + + /* If the subpattern set a required byte (or set a first byte that isn't + really the first byte - see above), set it. */ + + if (subreqbyte >= 0) reqbyte = subreqbyte; + } + + /* For a forward assertion, we take the reqbyte, if set. This can be + helpful if the pattern that follows the assertion doesn't set a different + char. For example, it's useful for /(?=abcde).+/. We can't set firstbyte + for an assertion, however because it leads to incorrect effect for patterns + such as /(?=a)a.+/ when the "real" "a" would then become a reqbyte instead + of a firstbyte. This is overcome by a scan at the end if there's no + firstbyte, looking for an asserted first char. */ + + else if (bravalue == OP_ASSERT && subreqbyte >= 0) reqbyte = subreqbyte; + + /* Now update the main code pointer to the end of the group. */ + + code = tempcode; + + /* Error if hit end of pattern */ + + if (*ptr != ')') + { + *errorptr = ERR14; + goto FAILED; + } + break; + + /* Check \ for being a real metacharacter; if not, fall through and handle + it as a data character at the start of a string. Escape items are checked + for validity in the pre-compiling pass. */ + + case '\\': + tempptr = ptr; + c = check_escape(&ptr, errorptr, *brackets, options, FALSE, cd); + + /* Handle metacharacters introduced by \. For ones like \d, the ESC_ values + are arranged to be the negation of the corresponding OP_values. For the + back references, the values are ESC_REF plus the reference number. Only + back references and those types that consume a character may be repeated. + We can test for values between ESC_b and ESC_Z for the latter; this may + have to change if any new ones are ever created. */ + + if (c < 0) + { + if (-c == ESC_Q) /* Handle start of quoted string */ + { + if (ptr[1] == '\\' && ptr[2] == 'E') ptr += 2; /* avoid empty string */ + else inescq = TRUE; + continue; + } + + /* For metasequences that actually match a character, we disable the + setting of a first character if it hasn't already been set. */ + + if (firstbyte == REQ_UNSET && -c > ESC_b && -c < ESC_Z) + firstbyte = REQ_NONE; + + /* Set values to reset to if this is followed by a zero repeat. */ + + zerofirstbyte = firstbyte; + zeroreqbyte = reqbyte; + + /* Back references are handled specially */ + + if (-c >= ESC_REF) + { + int number = -c - ESC_REF; + previous = code; + *code++ = OP_REF; + PUT2INC(code, 0, number); + } + else + { + previous = (-c > ESC_b && -c < ESC_Z)? code : NULL; + *code++ = -c; + } + continue; + } + + /* Data character: reset and fall through */ + + ptr = tempptr; + c = '\\'; + + /* Handle a run of data characters until a metacharacter is encountered. + The first character is guaranteed not to be whitespace or # when the + extended flag is set. */ + + NORMAL_CHAR: + default: + previous = code; + *code = OP_CHARS; + code += 2; + length = 0; + + do + { + /* If in \Q...\E, check for the end; if not, we always have a literal */ + + if (inescq) + { + if (c == '\\' && ptr[1] == 'E') + { + inescq = FALSE; + ptr++; + } + else + { + *code++ = c; + length++; + } + continue; + } + + /* Skip white space and comments for /x patterns */ + + if ((options & PCRE_EXTENDED) != 0) + { + if ((cd->ctypes[c] & ctype_space) != 0) continue; + if (c == '#') + { + /* The space before the ; is to avoid a warning on a silly compiler + on the Macintosh. */ + while ((c = *(++ptr)) != 0 && c != NEWLINE) ; + if (c == 0) break; + continue; + } + } + + /* Backslash may introduce a data char or a metacharacter. Escaped items + are checked for validity in the pre-compiling pass. Stop the string + before a metaitem. */ + + if (c == '\\') + { + tempptr = ptr; + c = check_escape(&ptr, errorptr, *brackets, options, FALSE, cd); + if (c < 0) { ptr = tempptr; break; } + + /* If a character is > 127 in UTF-8 mode, we have to turn it into + two or more characters in the UTF-8 encoding. */ + +#ifdef SUPPORT_UTF8 + if (utf8 && c > 127) + { + uschar buffer[8]; + int len = ord2utf8(c, buffer); + for (c = 0; c < len; c++) *code++ = buffer[c]; + length += len; + continue; + } +#endif + } + + /* Ordinary character or single-char escape */ + + *code++ = c; + length++; + } + + /* This "while" is the end of the "do" above. */ + + while (length < MAXLIT && (cd->ctypes[c = *(++ptr)] & ctype_meta) == 0); + + /* Update the first and last requirements. These are always bytes, even in + UTF-8 mode. However, there is a special case to be considered when there + are only one or two characters. Because this gets messy in UTF-8 mode, the + code is kept separate. When we get here "length" contains the number of + bytes. */ + +#ifdef SUPPORT_UTF8 + if (utf8 && length > 1) + { + uschar *t = previous + 3; /* After this code, t */ + while (t < code && (*t & 0xc0) == 0x80) t++; /* follows the 1st char */ + + /* Handle the case when there is only one multibyte character. It must + have at least two bytes because of the "length > 1" test above. */ + + if (t == code) + { + /* If no previous first byte, set it from this character, but revert to + none on a zero repeat. */ + + if (firstbyte == REQ_UNSET) + { + zerofirstbyte = REQ_NONE; + firstbyte = previous[2]; + } + + /* Otherwise, leave the first byte value alone, and don't change it on + a zero repeat */ + + else zerofirstbyte = firstbyte; + + /* In both cases, a zero repeat resets the previous required byte */ + + zeroreqbyte = reqbyte; + } + + /* Handle the case when there is more than one character. These may be + single-byte or multibyte characters */ + + else + { + t = code - 1; /* After this code, t is at the */ + while ((*t & 0xc0) == 0x80) t--; /* start of the last character */ + + /* If no previous first byte, set it from the first character, and + retain it on a zero repeat (of the last character). The required byte + is reset on a zero repeat, either to the byte before the last + character, unless this is the first byte of the string. In that case, + it reverts to its previous value. */ + + if (firstbyte == REQ_UNSET) + { + zerofirstbyte = firstbyte = previous[2] | req_caseopt; + zeroreqbyte = (t - 1 == previous + 2)? + reqbyte : t[-1] | req_caseopt | cd->req_varyopt; + } + + /* If there was a previous first byte, leave it alone, and don't change + it on a zero repeat. The required byte is reset on a zero repeat to the + byte before the last character. */ + + else + { + zerofirstbyte = firstbyte; + zeroreqbyte = t[-1] | req_caseopt | cd->req_varyopt; + } + } + + /* In all cases (we know length > 1), the new required byte is the last + byte of the string. */ + + reqbyte = code[-1] | req_caseopt | cd->req_varyopt; + } + + else /* End of UTF-8 coding */ +#endif + + /* This is the code for non-UTF-8 operation, either without UTF-8 support, + or when UTF-8 is not enabled. */ + + { + /* firstbyte was not previously set; take it from this string */ + + if (firstbyte == REQ_UNSET) + { + if (length == 1) + { + zerofirstbyte = REQ_NONE; + firstbyte = previous[2] | req_caseopt; + zeroreqbyte = reqbyte; + } + else + { + zerofirstbyte = firstbyte = previous[2] | req_caseopt; + zeroreqbyte = (length > 2)? + (code[-2] | req_caseopt | cd->req_varyopt) : reqbyte; + reqbyte = code[-1] | req_caseopt | cd->req_varyopt; + } + } + + /* firstbyte was previously set */ + + else + { + zerofirstbyte = firstbyte; + zeroreqbyte = (length == 1)? reqbyte : + code[-2] | req_caseopt | cd->req_varyopt; + reqbyte = code[-1] | req_caseopt | cd->req_varyopt; + } + } + + /* Set the length in the data vector, and advance to the next state. */ + + previous[1] = length; + if (length < MAXLIT) ptr--; + break; + } + } /* end of big loop */ + +/* Control never reaches here by falling through, only by a goto for all the +error states. Pass back the position in the pattern so that it can be displayed +to the user for diagnosing the error. */ + +FAILED: +*ptrptr = ptr; +return FALSE; +} + + + + +/************************************************* +* Compile sequence of alternatives * +*************************************************/ + +/* On entry, ptr is pointing past the bracket character, but on return +it points to the closing bracket, or vertical bar, or end of string. +The code variable is pointing at the byte into which the BRA operator has been +stored. If the ims options are changed at the start (for a (?ims: group) or +during any branch, we need to insert an OP_OPT item at the start of every +following branch to ensure they get set correctly at run time, and also pass +the new options into every subsequent branch compile. + +Argument: + options option bits, including any changes for this subpattern + oldims previous settings of ims option bits + brackets -> int containing the number of extracting brackets used + codeptr -> the address of the current code pointer + ptrptr -> the address of the current pattern pointer + errorptr -> pointer to error message + lookbehind TRUE if this is a lookbehind assertion + skipbytes skip this many bytes at start (for OP_COND, OP_BRANUMBER) + firstbyteptr place to put the first required character, or a negative number + reqbyteptr place to put the last required character, or a negative number + bcptr pointer to the chain of currently open branches + cd points to the data block with tables pointers etc. + +Returns: TRUE on success +*/ + +static BOOL +compile_regex(int options, int oldims, int *brackets, uschar **codeptr, + const uschar **ptrptr, const char **errorptr, BOOL lookbehind, int skipbytes, + int *firstbyteptr, int *reqbyteptr, branch_chain *bcptr, compile_data *cd) +{ +const uschar *ptr = *ptrptr; +uschar *code = *codeptr; +uschar *last_branch = code; +uschar *start_bracket = code; +uschar *reverse_count = NULL; +int firstbyte, reqbyte; +int branchfirstbyte, branchreqbyte; +branch_chain bc; + +bc.outer = bcptr; +bc.current = code; + +firstbyte = reqbyte = REQ_UNSET; + +/* Offset is set zero to mark that this bracket is still open */ + +PUT(code, 1, 0); +code += 1 + LINK_SIZE + skipbytes; + +/* Loop for each alternative branch */ + +for (;;) + { + /* Handle a change of ims options at the start of the branch */ + + if ((options & PCRE_IMS) != oldims) + { + *code++ = OP_OPT; + *code++ = options & PCRE_IMS; + } + + /* Set up dummy OP_REVERSE if lookbehind assertion */ + + if (lookbehind) + { + *code++ = OP_REVERSE; + reverse_count = code; + PUTINC(code, 0, 0); + } + + /* Now compile the branch */ + + if (!compile_branch(&options, brackets, &code, &ptr, errorptr, + &branchfirstbyte, &branchreqbyte, &bc, cd)) + { + *ptrptr = ptr; + return FALSE; + } + + /* If this is the first branch, the firstbyte and reqbyte values for the + branch become the values for the regex. */ + + if (*last_branch != OP_ALT) + { + firstbyte = branchfirstbyte; + reqbyte = branchreqbyte; + } + + /* If this is not the first branch, the first char and reqbyte have to + match the values from all the previous branches, except that if the previous + value for reqbyte didn't have REQ_VARY set, it can still match, and we set + REQ_VARY for the regex. */ + + else + { + /* If we previously had a firstbyte, but it doesn't match the new branch, + we have to abandon the firstbyte for the regex, but if there was previously + no reqbyte, it takes on the value of the old firstbyte. */ + + if (firstbyte >= 0 && firstbyte != branchfirstbyte) + { + if (reqbyte < 0) reqbyte = firstbyte; + firstbyte = REQ_NONE; + } + + /* If we (now or from before) have no firstbyte, a firstbyte from the + branch becomes a reqbyte if there isn't a branch reqbyte. */ + + if (firstbyte < 0 && branchfirstbyte >= 0 && branchreqbyte < 0) + branchreqbyte = branchfirstbyte; + + /* Now ensure that the reqbytes match */ + + if ((reqbyte & ~REQ_VARY) != (branchreqbyte & ~REQ_VARY)) + reqbyte = REQ_NONE; + else reqbyte |= branchreqbyte; /* To "or" REQ_VARY */ + } + + /* If lookbehind, check that this branch matches a fixed-length string, + and put the length into the OP_REVERSE item. Temporarily mark the end of + the branch with OP_END. */ + + if (lookbehind) + { + int length; + *code = OP_END; + length = find_fixedlength(last_branch, options); + DPRINTF(("fixed length = %d\n", length)); + if (length < 0) + { + *errorptr = (length == -2)? ERR36 : ERR25; + *ptrptr = ptr; + return FALSE; + } + PUT(reverse_count, 0, length); + } + + /* Reached end of expression, either ')' or end of pattern. Go back through + the alternative branches and reverse the chain of offsets, with the field in + the BRA item now becoming an offset to the first alternative. If there are + no alternatives, it points to the end of the group. The length in the + terminating ket is always the length of the whole bracketed item. If any of + the ims options were changed inside the group, compile a resetting op-code + following, except at the very end of the pattern. Return leaving the pointer + at the terminating char. */ + + if (*ptr != '|') + { + int length = code - last_branch; + do + { + int prev_length = GET(last_branch, 1); + PUT(last_branch, 1, length); + length = prev_length; + last_branch -= length; + } + while (length > 0); + + /* Fill in the ket */ + + *code = OP_KET; + PUT(code, 1, code - start_bracket); + code += 1 + LINK_SIZE; + + /* Resetting option if needed */ + + if ((options & PCRE_IMS) != oldims && *ptr == ')') + { + *code++ = OP_OPT; + *code++ = oldims; + } + + /* Set values to pass back */ + + *codeptr = code; + *ptrptr = ptr; + *firstbyteptr = firstbyte; + *reqbyteptr = reqbyte; + return TRUE; + } + + /* Another branch follows; insert an "or" node. Its length field points back + to the previous branch while the bracket remains open. At the end the chain + is reversed. It's done like this so that the start of the bracket has a + zero offset until it is closed, making it possible to detect recursion. */ + + *code = OP_ALT; + PUT(code, 1, code - last_branch); + bc.current = last_branch = code; + code += 1 + LINK_SIZE; + ptr++; + } +/* Control never reaches here */ +} + + + + +/************************************************* +* Check for anchored expression * +*************************************************/ + +/* Try to find out if this is an anchored regular expression. Consider each +alternative branch. If they all start with OP_SOD or OP_CIRC, or with a bracket +all of whose alternatives start with OP_SOD or OP_CIRC (recurse ad lib), then +it's anchored. However, if this is a multiline pattern, then only OP_SOD +counts, since OP_CIRC can match in the middle. + +We can also consider a regex to be anchored if OP_SOM starts all its branches. +This is the code for \G, which means "match at start of match position, taking +into account the match offset". + +A branch is also implicitly anchored if it starts with .* and DOTALL is set, +because that will try the rest of the pattern at all possible matching points, +so there is no point trying again.... er .... + +.... except when the .* appears inside capturing parentheses, and there is a +subsequent back reference to those parentheses. We haven't enough information +to catch that case precisely. + +At first, the best we could do was to detect when .* was in capturing brackets +and the highest back reference was greater than or equal to that level. +However, by keeping a bitmap of the first 31 back references, we can catch some +of the more common cases more precisely. + +Arguments: + code points to start of expression (the bracket) + options points to the options setting + bracket_map a bitmap of which brackets we are inside while testing; this + handles up to substring 31; after that we just have to take + the less precise approach + backref_map the back reference bitmap + +Returns: TRUE or FALSE +*/ + +static BOOL +is_anchored(register const uschar *code, int *options, unsigned int bracket_map, + unsigned int backref_map) +{ +do { + const uschar *scode = + first_significant_code(code + 1+LINK_SIZE, options, PCRE_MULTILINE); + register int op = *scode; + + /* Capturing brackets */ + + if (op > OP_BRA) + { + int new_map; + op -= OP_BRA; + if (op > EXTRACT_BASIC_MAX) op = GET2(scode, 2+LINK_SIZE); + new_map = bracket_map | ((op < 32)? (1 << op) : 1); + if (!is_anchored(scode, options, new_map, backref_map)) return FALSE; + } + + /* Other brackets */ + + else if (op == OP_BRA || op == OP_ASSERT || op == OP_ONCE || op == OP_COND) + { + if (!is_anchored(scode, options, bracket_map, backref_map)) return FALSE; + } + + /* .* is not anchored unless DOTALL is set and it isn't in brackets that + are or may be referenced. */ + + else if ((op == OP_TYPESTAR || op == OP_TYPEMINSTAR) && + (*options & PCRE_DOTALL) != 0) + { + if (scode[1] != OP_ANY || (bracket_map & backref_map) != 0) return FALSE; + } + + /* Check for explicit anchoring */ + + else if (op != OP_SOD && op != OP_SOM && + ((*options & PCRE_MULTILINE) != 0 || op != OP_CIRC)) + return FALSE; + code += GET(code, 1); + } +while (*code == OP_ALT); /* Loop for each alternative */ +return TRUE; +} + + + +/************************************************* +* Check for starting with ^ or .* * +*************************************************/ + +/* This is called to find out if every branch starts with ^ or .* so that +"first char" processing can be done to speed things up in multiline +matching and for non-DOTALL patterns that start with .* (which must start at +the beginning or after \n). As in the case of is_anchored() (see above), we +have to take account of back references to capturing brackets that contain .* +because in that case we can't make the assumption. + +Arguments: + code points to start of expression (the bracket) + bracket_map a bitmap of which brackets we are inside while testing; this + handles up to substring 31; after that we just have to take + the less precise approach + backref_map the back reference bitmap + +Returns: TRUE or FALSE +*/ + +static BOOL +is_startline(const uschar *code, unsigned int bracket_map, + unsigned int backref_map) +{ +do { + const uschar *scode = first_significant_code(code + 1+LINK_SIZE, NULL, 0); + register int op = *scode; + + /* Capturing brackets */ + + if (op > OP_BRA) + { + int new_map; + op -= OP_BRA; + if (op > EXTRACT_BASIC_MAX) op = GET2(scode, 2+LINK_SIZE); + new_map = bracket_map | ((op < 32)? (1 << op) : 1); + if (!is_startline(scode, new_map, backref_map)) return FALSE; + } + + /* Other brackets */ + + else if (op == OP_BRA || op == OP_ASSERT || op == OP_ONCE || op == OP_COND) + { if (!is_startline(scode, bracket_map, backref_map)) return FALSE; } + + /* .* is not anchored unless DOTALL is set and it isn't in brackets that + may be referenced. */ + + else if (op == OP_TYPESTAR || op == OP_TYPEMINSTAR) + { + if (scode[1] != OP_ANY || (bracket_map & backref_map) != 0) return FALSE; + } + + /* Check for explicit circumflex */ + + else if (op != OP_CIRC) return FALSE; + code += GET(code, 1); + } +while (*code == OP_ALT); /* Loop for each alternative */ +return TRUE; +} + + + +/************************************************* +* Check for asserted fixed first char * +*************************************************/ + +/* During compilation, the "first char" settings from forward assertions are +discarded, because they can cause conflicts with actual literals that follow. +However, if we end up without a first char setting for an unanchored pattern, +it is worth scanning the regex to see if there is an initial asserted first +char. If all branches start with the same asserted char, or with a bracket all +of whose alternatives start with the same asserted char (recurse ad lib), then +we return that char, otherwise -1. + +Arguments: + code points to start of expression (the bracket) + options pointer to the options (used to check casing changes) + inassert TRUE if in an assertion + +Returns: -1 or the fixed first char +*/ + +static int +find_firstassertedchar(const uschar *code, int *options, BOOL inassert) +{ +register int c = -1; +do { + int d; + const uschar *scode = + first_significant_code(code + 1+LINK_SIZE, options, PCRE_CASELESS); + register int op = *scode; + + if (op >= OP_BRA) op = OP_BRA; + + switch(op) + { + default: + return -1; + + case OP_BRA: + case OP_ASSERT: + case OP_ONCE: + case OP_COND: + if ((d = find_firstassertedchar(scode, options, op == OP_ASSERT)) < 0) + return -1; + if (c < 0) c = d; else if (c != d) return -1; + break; + + case OP_EXACT: /* Fall through */ + scode++; + + case OP_CHARS: /* Fall through */ + scode++; + + case OP_PLUS: + case OP_MINPLUS: + if (!inassert) return -1; + if (c < 0) + { + c = scode[1]; + if ((*options & PCRE_CASELESS) != 0) c |= REQ_CASELESS; + } + else if (c != scode[1]) return -1; + break; + } + + code += GET(code, 1); + } +while (*code == OP_ALT); +return c; +} + + + + +/************************************************* +* Compile a Regular Expression * +*************************************************/ + +/* This function takes a string and returns a pointer to a block of store +holding a compiled version of the expression. + +Arguments: + pattern the regular expression + options various option bits + errorptr pointer to pointer to error text + erroroffset ptr offset in pattern where error was detected + tables pointer to character tables or NULL + +Returns: pointer to compiled data block, or NULL on error, + with errorptr and erroroffset set +*/ + +pcre * +pcre_compile(const char *pattern, int options, const char **errorptr, + int *erroroffset, const unsigned char *tables) +{ +real_pcre *re; +int length = 1 + LINK_SIZE; /* For initial BRA plus length */ +int runlength; +int c, firstbyte, reqbyte; +int bracount = 0; +int branch_extra = 0; +int branch_newextra; +int item_count = -1; +int name_count = 0; +int max_name_size = 0; +#ifdef SUPPORT_UTF8 +int lastcharlength = 0; +BOOL utf8; +BOOL class_utf8; +#endif +BOOL inescq = FALSE; +unsigned int brastackptr = 0; +size_t size; +uschar *code; +const uschar *codestart; +const uschar *ptr; +compile_data compile_block; +int brastack[BRASTACK_SIZE]; +uschar bralenstack[BRASTACK_SIZE]; + +/* We can't pass back an error message if errorptr is NULL; I guess the best we +can do is just return NULL. */ + +if (errorptr == NULL) return NULL; +*errorptr = NULL; + +/* However, we can give a message for this error */ + +if (erroroffset == NULL) + { + *errorptr = ERR16; + return NULL; + } +*erroroffset = 0; + +/* Can't support UTF8 unless PCRE has been compiled to include the code. */ + +#ifdef SUPPORT_UTF8 +utf8 = (options & PCRE_UTF8) != 0; +#else +if ((options & PCRE_UTF8) != 0) + { + *errorptr = ERR32; + return NULL; + } +#endif + +if ((options & ~PUBLIC_OPTIONS) != 0) + { + *errorptr = ERR17; + return NULL; + } + +/* Set up pointers to the individual character tables */ + +if (tables == NULL) tables = pcre_default_tables; +compile_block.lcc = tables + lcc_offset; +compile_block.fcc = tables + fcc_offset; +compile_block.cbits = tables + cbits_offset; +compile_block.ctypes = tables + ctypes_offset; + +/* Maximum back reference and backref bitmap. This is updated for numeric +references during the first pass, but for named references during the actual +compile pass. The bitmap records up to 31 back references to help in deciding +whether (.*) can be treated as anchored or not. */ + +compile_block.top_backref = 0; +compile_block.backref_map = 0; + +/* Reflect pattern for debugging output */ + +DPRINTF(("------------------------------------------------------------------\n")); +DPRINTF(("%s\n", pattern)); + +/* The first thing to do is to make a pass over the pattern to compute the +amount of store required to hold the compiled code. This does not have to be +perfect as long as errors are overestimates. At the same time we can detect any +flag settings right at the start, and extract them. Make an attempt to correct +for any counted white space if an "extended" flag setting appears late in the +pattern. We can't be so clever for #-comments. */ + +ptr = (const uschar *)(pattern - 1); +while ((c = *(++ptr)) != 0) + { + int min, max; + int class_optcount; + int bracket_length; + int duplength; + + /* If we are inside a \Q...\E sequence, all chars are literal */ + + if (inescq) goto NORMAL_CHAR; + + /* Otherwise, first check for ignored whitespace and comments */ + + if ((options & PCRE_EXTENDED) != 0) + { + if ((compile_block.ctypes[c] & ctype_space) != 0) continue; + if (c == '#') + { + /* The space before the ; is to avoid a warning on a silly compiler + on the Macintosh. */ + while ((c = *(++ptr)) != 0 && c != NEWLINE) ; + if (c == 0) break; + continue; + } + } + + item_count++; /* Is zero for the first non-comment item */ + + switch(c) + { + /* A backslashed item may be an escaped "normal" character or a + character type. For a "normal" character, put the pointers and + character back so that tests for whitespace etc. in the input + are done correctly. */ + + case '\\': + { + const uschar *save_ptr = ptr; + c = check_escape(&ptr, errorptr, bracount, options, FALSE, &compile_block); + if (*errorptr != NULL) goto PCRE_ERROR_RETURN; + if (c >= 0) + { + ptr = save_ptr; + c = '\\'; + goto NORMAL_CHAR; + } + } + + /* If \Q, enter "literal" mode */ + + if (-c == ESC_Q) + { + inescq = TRUE; + continue; + } + + /* Other escapes need one byte, and are of length one for repeats */ + + length++; +#ifdef SUPPORT_UTF8 + lastcharlength = 1; +#endif + + /* A back reference needs an additional 2 bytes, plus either one or 5 + bytes for a repeat. We also need to keep the value of the highest + back reference. */ + + if (c <= -ESC_REF) + { + int refnum = -c - ESC_REF; + compile_block.backref_map |= (refnum < 32)? (1 << refnum) : 1; + if (refnum > compile_block.top_backref) + compile_block.top_backref = refnum; + length += 2; /* For single back reference */ + if (ptr[1] == '{' && is_counted_repeat(ptr+2, &compile_block)) + { + ptr = read_repeat_counts(ptr+2, &min, &max, errorptr, &compile_block); + if (*errorptr != NULL) goto PCRE_ERROR_RETURN; + if ((min == 0 && (max == 1 || max == -1)) || + (min == 1 && max == -1)) + length++; + else length += 5; + if (ptr[1] == '?') ptr++; + } + } + continue; + + case '^': /* Single-byte metacharacters */ + case '.': + case '$': + length++; +#ifdef SUPPORT_UTF8 + lastcharlength = 1; +#endif + continue; + + case '*': /* These repeats won't be after brackets; */ + case '+': /* those are handled separately */ + case '?': + length++; + goto POSESSIVE; /* A few lines below */ + + /* This covers the cases of braced repeats after a single char, metachar, + class, or back reference. */ + + case '{': + if (!is_counted_repeat(ptr+1, &compile_block)) goto NORMAL_CHAR; + ptr = read_repeat_counts(ptr+1, &min, &max, errorptr, &compile_block); + if (*errorptr != NULL) goto PCRE_ERROR_RETURN; + + /* These special cases just insert one extra opcode */ + + if ((min == 0 && (max == 1 || max == -1)) || + (min == 1 && max == -1)) + length++; + + /* These cases might insert additional copies of a preceding character. */ + + else + { +#ifdef SUPPORT_UTF8 + /* In UTF-8 mode, we should find the length in lastcharlength */ + if (utf8) + { + if (min != 1) + { + length -= lastcharlength; /* Uncount the original char or metachar */ + if (min > 0) length += 3 + lastcharlength; + } + length += lastcharlength + ((max > 0)? 3 : 1); + } + else +#endif + + /* Not UTF-8 mode: all characters are one byte */ + { + if (min != 1) + { + length--; /* Uncount the original char or metachar */ + if (min > 0) length += 4; + } + + length += (max > 0)? 4 : 2; + } + } + + if (ptr[1] == '?') ptr++; /* Needs no extra length */ + + POSESSIVE: /* Test for possessive quantifier */ + if (ptr[1] == '+') + { + ptr++; + length += 2 + 2*LINK_SIZE; /* Allow for atomic brackets */ + } + continue; + + /* An alternation contains an offset to the next branch or ket. If any ims + options changed in the previous branch(es), and/or if we are in a + lookbehind assertion, extra space will be needed at the start of the + branch. This is handled by branch_extra. */ + + case '|': + length += 1 + LINK_SIZE + branch_extra; + continue; + + /* A character class uses 33 characters provided that all the character + values are less than 256. Otherwise, it uses a bit map for low valued + characters, and individual items for others. Don't worry about character + types that aren't allowed in classes - they'll get picked up during the + compile. A character class that contains only one single-byte character + uses 2 or 3 bytes, depending on whether it is negated or not. Notice this + where we can. (In UTF-8 mode we can do this only for chars < 128.) */ + + case '[': + class_optcount = 0; + +#ifdef SUPPORT_UTF8 + class_utf8 = FALSE; +#endif + + if (*(++ptr) == '^') ptr++; + + /* Written as a "do" so that an initial ']' is taken as data */ + + if (*ptr != 0) do + { + /* Inside \Q...\E everything is literal except \E */ + + if (inescq) + { + if (*ptr != '\\' || ptr[1] != 'E') goto NON_SPECIAL_CHARACTER; + inescq = FALSE; + ptr += 1; + continue; + } + + /* Outside \Q...\E, check for escapes */ + + if (*ptr == '\\') + { +#ifdef SUPPORT_UTF8 + int prevchar = ptr[-1]; +#endif + int ch = check_escape(&ptr, errorptr, bracount, options, TRUE, + &compile_block); + if (*errorptr != NULL) goto PCRE_ERROR_RETURN; + + /* \b is backspace inside a class */ + + if (-ch == ESC_b) ch = '\b'; + + /* \Q enters quoting mode */ + + if (-ch == ESC_Q) + { + inescq = TRUE; + continue; + } + + /* Handle escapes that turn into characters */ + + if (ch >= 0) + { +#ifdef SUPPORT_UTF8 + if (utf8) + { + if (ch > 127) class_optcount = 10; /* Ensure > 1 */ + if (ch > 255) + { + uschar buffer[6]; + if (!class_utf8) + { + class_utf8 = TRUE; + length += LINK_SIZE + 1 + 1; + } + length += 1 + ord2utf8(ch, buffer); + + /* If this wide character is preceded by '-', add an extra 2 to + the length in case the previous character was < 128, because in + this case the whole range will be put into the list. */ + + if (prevchar == '-') length += 2; + } + } +#endif + class_optcount++; /* for possible optimization */ + } + else class_optcount = 10; /* \d, \s etc; make sure > 1 */ + } + + /* Check the syntax for POSIX stuff. The bits we actually handle are + checked during the real compile phase. */ + + else if (*ptr == '[' && check_posix_syntax(ptr, &ptr, &compile_block)) + { + ptr++; + class_optcount = 10; /* Make sure > 1 */ + } + + /* Anything else just increments the possible optimization count. If + there are wide characters, we are going to have to use an XCLASS. */ + + else + { + NON_SPECIAL_CHARACTER: + class_optcount++; + +#ifdef SUPPORT_UTF8 + if (utf8) + { + int ch; + int extra = 0; + GETCHARLEN(ch, ptr, extra); + if (ch > 127) class_optcount = 10; /* No optimization possible */ + if (ch > 255) + { + if (!class_utf8) + { + class_utf8 = TRUE; + length += LINK_SIZE + 1 + 1; + } + length += 2 + extra; + + /* If this wide character is preceded by '-', add an extra 2 to + the length in case the previous character was < 128, because in + this case the whole range will be put into the list. */ + + if (ptr[-1] == '-') length += 2; + + /* Advance to the end of this character */ + + ptr += extra; + } + } +#endif + } + } + while (*(++ptr) != 0 && (inescq || *ptr != ']')); /* Concludes "do" above */ + + if (*ptr == 0) /* Missing terminating ']' */ + { + *errorptr = ERR6; + goto PCRE_ERROR_RETURN; + } + + /* We can optimize when there was only one optimizable character. Repeats + for positive and negated single one-byte chars are handled by the general + code. Here, we handle repeats for the class opcodes. */ + + if (class_optcount == 1) length += 3; else + { + length += 33; + + /* A repeat needs either 1 or 5 bytes. */ + + if (*ptr != 0 && ptr[1] == '{' && is_counted_repeat(ptr+2, &compile_block)) + { + ptr = read_repeat_counts(ptr+2, &min, &max, errorptr, &compile_block); + if (*errorptr != NULL) goto PCRE_ERROR_RETURN; + if ((min == 0 && (max == 1 || max == -1)) || + (min == 1 && max == -1)) + length++; + else length += 5; + if (ptr[1] == '?') ptr++; + } + } + continue; + + /* Brackets may be genuine groups or special things */ + + case '(': + branch_newextra = 0; + bracket_length = 1 + LINK_SIZE; + + /* Handle special forms of bracket, which all start (? */ + + if (ptr[1] == '?') + { + int set, unset; + int *optset; + + switch (c = ptr[2]) + { + /* Skip over comments entirely */ + case '#': + ptr += 3; + while (*ptr != 0 && *ptr != ')') ptr++; + if (*ptr == 0) + { + *errorptr = ERR18; + goto PCRE_ERROR_RETURN; + } + continue; + + /* Non-referencing groups and lookaheads just move the pointer on, and + then behave like a non-special bracket, except that they don't increment + the count of extracting brackets. Ditto for the "once only" bracket, + which is in Perl from version 5.005. */ + + case ':': + case '=': + case '!': + case '>': + ptr += 2; + break; + + /* (?R) specifies a recursive call to the regex, which is an extension + to provide the facility which can be obtained by (?p{perl-code}) in + Perl 5.6. In Perl 5.8 this has become (??{perl-code}). + + From PCRE 4.00, items such as (?3) specify subroutine-like "calls" to + the appropriate numbered brackets. This includes both recursive and + non-recursive calls. (?R) is now synonymous with (?0). */ + + case 'R': + ptr++; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + ptr += 2; + if (c != 'R') + while ((digitab[*(++ptr)] & ctype_digit) != 0); + if (*ptr != ')') + { + *errorptr = ERR29; + goto PCRE_ERROR_RETURN; + } + length += 1 + LINK_SIZE; + + /* If this item is quantified, it will get wrapped inside brackets so + as to use the code for quantified brackets. We jump down and use the + code that handles this for real brackets. */ + + if (ptr[1] == '+' || ptr[1] == '*' || ptr[1] == '?' || ptr[1] == '{') + { + length += 2 + 2 * LINK_SIZE; /* to make bracketed */ + duplength = 5 + 3 * LINK_SIZE; + goto HANDLE_QUANTIFIED_BRACKETS; + } + continue; + + /* (?C) is an extension which provides "callout" - to provide a bit of + the functionality of the Perl (?{...}) feature. An optional number may + follow (default is zero). */ + + case 'C': + ptr += 2; + while ((digitab[*(++ptr)] & ctype_digit) != 0); + if (*ptr != ')') + { + *errorptr = ERR39; + goto PCRE_ERROR_RETURN; + } + length += 2; + continue; + + /* Named subpatterns are an extension copied from Python */ + + case 'P': + ptr += 3; + if (*ptr == '<') + { + const uschar *p; /* Don't amalgamate; some compilers */ + p = ++ptr; /* grumble at autoincrement in declaration */ + while ((compile_block.ctypes[*ptr] & ctype_word) != 0) ptr++; + if (*ptr != '>') + { + *errorptr = ERR42; + goto PCRE_ERROR_RETURN; + } + name_count++; + if (ptr - p > max_name_size) max_name_size = (ptr - p); + break; + } + + if (*ptr == '=' || *ptr == '>') + { + while ((compile_block.ctypes[*(++ptr)] & ctype_word) != 0); + if (*ptr != ')') + { + *errorptr = ERR42; + goto PCRE_ERROR_RETURN; + } + break; + } + + /* Unknown character after (?P */ + + *errorptr = ERR41; + goto PCRE_ERROR_RETURN; + + /* Lookbehinds are in Perl from version 5.005 */ + + case '<': + ptr += 3; + if (*ptr == '=' || *ptr == '!') + { + branch_newextra = 1 + LINK_SIZE; + length += 1 + LINK_SIZE; /* For the first branch */ + break; + } + *errorptr = ERR24; + goto PCRE_ERROR_RETURN; + + /* Conditionals are in Perl from version 5.005. The bracket must either + be followed by a number (for bracket reference) or by an assertion + group, or (a PCRE extension) by 'R' for a recursion test. */ + + case '(': + if (ptr[3] == 'R' && ptr[4] == ')') + { + ptr += 4; + length += 3; + } + else if ((digitab[ptr[3]] & ctype_digit) != 0) + { + ptr += 4; + length += 3; + while ((digitab[*ptr] & ctype_digit) != 0) ptr++; + if (*ptr != ')') + { + *errorptr = ERR26; + goto PCRE_ERROR_RETURN; + } + } + else /* An assertion must follow */ + { + ptr++; /* Can treat like ':' as far as spacing is concerned */ + if (ptr[2] != '?' || + (ptr[3] != '=' && ptr[3] != '!' && ptr[3] != '<') ) + { + ptr += 2; /* To get right offset in message */ + *errorptr = ERR28; + goto PCRE_ERROR_RETURN; + } + } + break; + + /* Else loop checking valid options until ) is met. Anything else is an + error. If we are without any brackets, i.e. at top level, the settings + act as if specified in the options, so massage the options immediately. + This is for backward compatibility with Perl 5.004. */ + + default: + set = unset = 0; + optset = &set; + ptr += 2; + + for (;; ptr++) + { + c = *ptr; + switch (c) + { + case 'i': + *optset |= PCRE_CASELESS; + continue; + + case 'm': + *optset |= PCRE_MULTILINE; + continue; + + case 's': + *optset |= PCRE_DOTALL; + continue; + + case 'x': + *optset |= PCRE_EXTENDED; + continue; + + case 'X': + *optset |= PCRE_EXTRA; + continue; + + case 'U': + *optset |= PCRE_UNGREEDY; + continue; + + case '-': + optset = &unset; + continue; + + /* A termination by ')' indicates an options-setting-only item; if + this is at the very start of the pattern (indicated by item_count + being zero), we use it to set the global options. This is helpful + when analyzing the pattern for first characters, etc. Otherwise + nothing is done here and it is handled during the compiling + process. + + [Historical note: Up to Perl 5.8, options settings at top level + were always global settings, wherever they appeared in the pattern. + That is, they were equivalent to an external setting. From 5.8 + onwards, they apply only to what follows (which is what you might + expect).] */ + + case ')': + if (item_count == 0) + { + options = (options | set) & (~unset); + set = unset = 0; /* To save length */ + item_count--; /* To allow for several */ + } + + /* Fall through */ + + /* A termination by ':' indicates the start of a nested group with + the given options set. This is again handled at compile time, but + we must allow for compiled space if any of the ims options are + set. We also have to allow for resetting space at the end of + the group, which is why 4 is added to the length and not just 2. + If there are several changes of options within the same group, this + will lead to an over-estimate on the length, but this shouldn't + matter very much. We also have to allow for resetting options at + the start of any alternations, which we do by setting + branch_newextra to 2. Finally, we record whether the case-dependent + flag ever changes within the regex. This is used by the "required + character" code. */ + + case ':': + if (((set|unset) & PCRE_IMS) != 0) + { + length += 4; + branch_newextra = 2; + if (((set|unset) & PCRE_CASELESS) != 0) options |= PCRE_ICHANGED; + } + goto END_OPTIONS; + + /* Unrecognized option character */ + + default: + *errorptr = ERR12; + goto PCRE_ERROR_RETURN; + } + } + + /* If we hit a closing bracket, that's it - this is a freestanding + option-setting. We need to ensure that branch_extra is updated if + necessary. The only values branch_newextra can have here are 0 or 2. + If the value is 2, then branch_extra must either be 2 or 5, depending + on whether this is a lookbehind group or not. */ + + END_OPTIONS: + if (c == ')') + { + if (branch_newextra == 2 && + (branch_extra == 0 || branch_extra == 1+LINK_SIZE)) + branch_extra += branch_newextra; + continue; + } + + /* If options were terminated by ':' control comes here. Fall through + to handle the group below. */ + } + } + + /* Extracting brackets must be counted so we can process escapes in a + Perlish way. If the number exceeds EXTRACT_BASIC_MAX we are going to + need an additional 3 bytes of store per extracting bracket. However, if + PCRE_NO_AUTO)CAPTURE is set, unadorned brackets become non-capturing, so we + must leave the count alone (it will aways be zero). */ + + else if ((options & PCRE_NO_AUTO_CAPTURE) == 0) + { + bracount++; + if (bracount > EXTRACT_BASIC_MAX) bracket_length += 3; + } + + /* Save length for computing whole length at end if there's a repeat that + requires duplication of the group. Also save the current value of + branch_extra, and start the new group with the new value. If non-zero, this + will either be 2 for a (?imsx: group, or 3 for a lookbehind assertion. */ + + if (brastackptr >= sizeof(brastack)/sizeof(int)) + { + *errorptr = ERR19; + goto PCRE_ERROR_RETURN; + } + + bralenstack[brastackptr] = branch_extra; + branch_extra = branch_newextra; + + brastack[brastackptr++] = length; + length += bracket_length; + continue; + + /* Handle ket. Look for subsequent max/min; for certain sets of values we + have to replicate this bracket up to that many times. If brastackptr is + 0 this is an unmatched bracket which will generate an error, but take care + not to try to access brastack[-1] when computing the length and restoring + the branch_extra value. */ + + case ')': + length += 1 + LINK_SIZE; + if (brastackptr > 0) + { + duplength = length - brastack[--brastackptr]; + branch_extra = bralenstack[brastackptr]; + } + else duplength = 0; + + /* The following code is also used when a recursion such as (?3) is + followed by a quantifier, because in that case, it has to be wrapped inside + brackets so that the quantifier works. The value of duplength must be + set before arrival. */ + + HANDLE_QUANTIFIED_BRACKETS: + + /* Leave ptr at the final char; for read_repeat_counts this happens + automatically; for the others we need an increment. */ + + if ((c = ptr[1]) == '{' && is_counted_repeat(ptr+2, &compile_block)) + { + ptr = read_repeat_counts(ptr+2, &min, &max, errorptr, &compile_block); + if (*errorptr != NULL) goto PCRE_ERROR_RETURN; + } + else if (c == '*') { min = 0; max = -1; ptr++; } + else if (c == '+') { min = 1; max = -1; ptr++; } + else if (c == '?') { min = 0; max = 1; ptr++; } + else { min = 1; max = 1; } + + /* If the minimum is zero, we have to allow for an OP_BRAZERO before the + group, and if the maximum is greater than zero, we have to replicate + maxval-1 times; each replication acquires an OP_BRAZERO plus a nesting + bracket set. */ + + if (min == 0) + { + length++; + if (max > 0) length += (max - 1) * (duplength + 3 + 2*LINK_SIZE); + } + + /* When the minimum is greater than zero, we have to replicate up to + minval-1 times, with no additions required in the copies. Then, if there + is a limited maximum we have to replicate up to maxval-1 times allowing + for a BRAZERO item before each optional copy and nesting brackets for all + but one of the optional copies. */ + + else + { + length += (min - 1) * duplength; + if (max > min) /* Need this test as max=-1 means no limit */ + length += (max - min) * (duplength + 3 + 2*LINK_SIZE) + - (2 + 2*LINK_SIZE); + } + + /* Allow space for once brackets for "possessive quantifier" */ + + if (ptr[1] == '+') + { + ptr++; + length += 2 + 2*LINK_SIZE; + } + continue; + + /* Non-special character. For a run of such characters the length required + is the number of characters + 2, except that the maximum run length is + MAXLIT. We won't get a skipped space or a non-data escape or the start of a + # comment as the first character, so the length can't be zero. */ + + NORMAL_CHAR: + default: + length += 2; + runlength = 0; + do + { +#ifdef SUPPORT_UTF8 + lastcharlength = 1; /* Need length of last char for UTF-8 repeats */ +#endif + + /* If in a \Q...\E sequence, check for end; otherwise it's a literal */ + if (inescq) + { + if (c == '\\' && ptr[1] == 'E') + { + inescq = FALSE; + ptr++; + } + else runlength++; + continue; + } + + /* Skip whitespace and comments for /x */ + + if ((options & PCRE_EXTENDED) != 0) + { + if ((compile_block.ctypes[c] & ctype_space) != 0) continue; + if (c == '#') + { + /* The space before the ; is to avoid a warning on a silly compiler + on the Macintosh. */ + while ((c = *(++ptr)) != 0 && c != NEWLINE) ; + continue; + } + } + + /* Backslash may introduce a data char or a metacharacter; stop the + string before the latter. */ + + if (c == '\\') + { + const uschar *saveptr = ptr; + c = check_escape(&ptr, errorptr, bracount, options, FALSE, + &compile_block); + if (*errorptr != NULL) goto PCRE_ERROR_RETURN; + if (c < 0) { ptr = saveptr; break; } + + /* In UTF-8 mode, add on the number of additional bytes needed to + encode this character, and save the total length in case this is a + final char that is repeated. */ + +#ifdef SUPPORT_UTF8 + if (utf8 && c > 127) + { + int i; + for (i = 0; i < sizeof(utf8_table1)/sizeof(int); i++) + if (c <= utf8_table1[i]) break; + runlength += i; + lastcharlength += i; + } +#endif + } + + /* Ordinary character or single-char escape */ + + runlength++; + } + + /* This "while" is the end of the "do" above. */ + + while (runlength < MAXLIT && + (compile_block.ctypes[c = *(++ptr)] & ctype_meta) == 0); + + /* If we hit a meta-character, back off to point to it */ + + if (runlength < MAXLIT) ptr--; + + /* If the last char in the string is a UTF-8 multibyte character, we must + set lastcharlength correctly. If it was specified as an escape, this will + already have been done above. However, we also have to support in-line + UTF-8 characters, so check backwards from where we are. */ + +#ifdef SUPPORT_UTF8 + if (utf8) + { + const uschar *lastptr = ptr - 1; + if ((*lastptr & 0x80) != 0) + { + while((*lastptr & 0xc0) == 0x80) lastptr--; + lastcharlength = ptr - lastptr; + } + } +#endif + + length += runlength; + continue; + } + } + +length += 2 + LINK_SIZE; /* For final KET and END */ + +if (length > MAX_PATTERN_SIZE) + { + *errorptr = ERR20; + return NULL; + } + +/* Compute the size of data block needed and get it, either from malloc or +externally provided function. */ + +size = length + sizeof(real_pcre) + name_count * (max_name_size + 3); +re = (real_pcre *)(pcre_malloc)(size); + +if (re == NULL) + { + *errorptr = ERR21; + return NULL; + } + +/* Put in the magic number, and save the size, options, and table pointer */ + +re->magic_number = MAGIC_NUMBER; +re->size = size; +re->options = options; +re->tables = tables; +re->name_entry_size = max_name_size + 3; +re->name_count = name_count; + +/* The starting points of the name/number translation table and of the code are +passed around in the compile data block. */ + +compile_block.names_found = 0; +compile_block.name_entry_size = max_name_size + 3; +compile_block.name_table = (uschar *)re + sizeof(real_pcre); +codestart = compile_block.name_table + re->name_entry_size * re->name_count; +compile_block.start_code = codestart; +compile_block.req_varyopt = 0; + +/* Set up a starting, non-extracting bracket, then compile the expression. On +error, *errorptr will be set non-NULL, so we don't need to look at the result +of the function here. */ + +ptr = (const uschar *)pattern; +code = (uschar *)codestart; +*code = OP_BRA; +bracount = 0; +(void)compile_regex(options, options & PCRE_IMS, &bracount, &code, &ptr, + errorptr, FALSE, 0, &firstbyte, &reqbyte, NULL, &compile_block); +re->top_bracket = bracount; +re->top_backref = compile_block.top_backref; + +/* If not reached end of pattern on success, there's an excess bracket. */ + +if (*errorptr == NULL && *ptr != 0) *errorptr = ERR22; + +/* Fill in the terminating state and check for disastrous overflow, but +if debugging, leave the test till after things are printed out. */ + +*code++ = OP_END; + +#ifndef DEBUG +if (code - codestart > length) *errorptr = ERR23; +#endif + +/* Give an error if there's back reference to a non-existent capturing +subpattern. */ + +if (re->top_backref > re->top_bracket) *errorptr = ERR15; + +/* Failed to compile, or error while post-processing */ + +if (*errorptr != NULL) + { + (pcre_free)(re); + PCRE_ERROR_RETURN: + *erroroffset = ptr - (const uschar *)pattern; + return NULL; + } + +/* If the anchored option was not passed, set the flag if we can determine that +the pattern is anchored by virtue of ^ characters or \A or anything else (such +as starting with .* when DOTALL is set). + +Otherwise, if we know what the first character has to be, save it, because that +speeds up unanchored matches no end. If not, see if we can set the +PCRE_STARTLINE flag. This is helpful for multiline matches when all branches +start with ^. and also when all branches start with .* for non-DOTALL matches. +*/ + +if ((options & PCRE_ANCHORED) == 0) + { + int temp_options = options; + if (is_anchored(codestart, &temp_options, 0, compile_block.backref_map)) + re->options |= PCRE_ANCHORED; + else + { + if (firstbyte < 0) + firstbyte = find_firstassertedchar(codestart, &temp_options, FALSE); + if (firstbyte >= 0) /* Remove caseless flag for non-caseable chars */ + { + int ch = firstbyte & 255; + re->first_byte = ((firstbyte & REQ_CASELESS) != 0 && + compile_block.fcc[ch] == ch)? ch : firstbyte; + re->options |= PCRE_FIRSTSET; + } + else if (is_startline(codestart, 0, compile_block.backref_map)) + re->options |= PCRE_STARTLINE; + } + } + +/* For an anchored pattern, we use the "required byte" only if it follows a +variable length item in the regex. Remove the caseless flag for non-caseable +chars. */ + +if (reqbyte >= 0 && + ((re->options & PCRE_ANCHORED) == 0 || (reqbyte & REQ_VARY) != 0)) + { + int ch = reqbyte & 255; + re->req_byte = ((reqbyte & REQ_CASELESS) != 0 && + compile_block.fcc[ch] == ch)? (reqbyte & ~REQ_CASELESS) : reqbyte; + re->options |= PCRE_REQCHSET; + } + +/* Print out the compiled data for debugging */ + +#ifdef DEBUG + +printf("Length = %d top_bracket = %d top_backref = %d\n", + length, re->top_bracket, re->top_backref); + +if (re->options != 0) + { + printf("%s%s%s%s%s%s%s%s%s\n", + ((re->options & PCRE_ANCHORED) != 0)? "anchored " : "", + ((re->options & PCRE_CASELESS) != 0)? "caseless " : "", + ((re->options & PCRE_ICHANGED) != 0)? "case state changed " : "", + ((re->options & PCRE_EXTENDED) != 0)? "extended " : "", + ((re->options & PCRE_MULTILINE) != 0)? "multiline " : "", + ((re->options & PCRE_DOTALL) != 0)? "dotall " : "", + ((re->options & PCRE_DOLLAR_ENDONLY) != 0)? "endonly " : "", + ((re->options & PCRE_EXTRA) != 0)? "extra " : "", + ((re->options & PCRE_UNGREEDY) != 0)? "ungreedy " : ""); + } + +if ((re->options & PCRE_FIRSTSET) != 0) + { + int ch = re->first_byte & 255; + char *caseless = ((re->first_byte & REQ_CASELESS) == 0)? "" : " (caseless)"; + if (isprint(ch)) printf("First char = %c%s\n", ch, caseless); + else printf("First char = \\x%02x%s\n", ch, caseless); + } + +if ((re->options & PCRE_REQCHSET) != 0) + { + int ch = re->req_byte & 255; + char *caseless = ((re->req_byte & REQ_CASELESS) == 0)? "" : " (caseless)"; + if (isprint(ch)) printf("Req char = %c%s\n", ch, caseless); + else printf("Req char = \\x%02x%s\n", ch, caseless); + } + +print_internals(re, stdout); + +/* This check is done here in the debugging case so that the code that +was compiled can be seen. */ + +if (code - codestart > length) + { + *errorptr = ERR23; + (pcre_free)(re); + *erroroffset = ptr - (uschar *)pattern; + return NULL; + } +#endif + +return (pcre *)re; +} + + + +/************************************************* +* Match a back-reference * +*************************************************/ + +/* If a back reference hasn't been set, the length that is passed is greater +than the number of characters left in the string, so the match fails. + +Arguments: + offset index into the offset vector + eptr points into the subject + length length to be matched + md points to match data block + ims the ims flags + +Returns: TRUE if matched +*/ + +static BOOL +match_ref(int offset, register const uschar *eptr, int length, match_data *md, + unsigned long int ims) +{ +const uschar *p = md->start_subject + md->offset_vector[offset]; + +#ifdef DEBUG +if (eptr >= md->end_subject) + printf("matching subject "); +else + { + printf("matching subject "); + pchars(eptr, length, TRUE, md); + } +printf(" against backref "); +pchars(p, length, FALSE, md); +printf("\n"); +#endif + +/* Always fail if not enough characters left */ + +if (length > md->end_subject - eptr) return FALSE; + +/* Separate the caselesss case for speed */ + +if ((ims & PCRE_CASELESS) != 0) + { + while (length-- > 0) + if (md->lcc[*p++] != md->lcc[*eptr++]) return FALSE; + } +else + { while (length-- > 0) if (*p++ != *eptr++) return FALSE; } + +return TRUE; +} + + +#ifdef SUPPORT_UTF8 +/************************************************* +* Match character against an XCLASS * +*************************************************/ + +/* This function is called from within the XCLASS code below, to match a +character against an extended class which might match values > 255. + +Arguments: + c the character + data points to the flag byte of the XCLASS data + +Returns: TRUE if character matches, else FALSE +*/ + +static BOOL +match_xclass(int c, const uschar *data) +{ +int t; +BOOL negated = (*data & XCL_NOT) != 0; + +/* Character values < 256 are matched against a bitmap, if one is present. If +not, we still carry on, because there may be ranges that start below 256 in the +additional data. */ + +if (c < 256) + { + if ((*data & XCL_MAP) != 0 && (data[1 + c/8] & (1 << (c&7))) != 0) + return !negated; /* char found */ + } + +/* Now match against the list of large chars or ranges that end with a large +char. First skip the bit map if present. */ + +if ((*data++ & XCL_MAP) != 0) data += 32; + +while ((t = *data++) != XCL_END) + { + int x, y; + GETCHARINC(x, data); + if (t == XCL_SINGLE) + { + if (c == x) return !negated; + } + else + { + GETCHARINC(y, data); + if (c >= x && c <= y) return !negated; + } + } + +return negated; /* char was not found */ +} +#endif + + + + +/************************************************* +* Match from current position * +*************************************************/ + +/* On entry ecode points to the first opcode, and eptr to the first character +in the subject string, while eptrb holds the value of eptr at the start of the +last bracketed group - used for breaking infinite loops matching zero-length +strings. This function is called recursively in many circumstances. Whenever it +returns a negative (error) response, the outer incarnation must also return the +same response. + +Performance note: It might be tempting to extract commonly used fields from the +md structure (e.g. utf8, end_subject) into individual variables to improve +performance. Tests using gcc on a SPARC disproved this; in the first case, it +made performance worse. + +Arguments: + eptr pointer in subject + ecode position in code + offset_top current top pointer + md pointer to "static" info for the match + ims current /i, /m, and /s options + eptrb pointer to chain of blocks containing eptr at start of + brackets - for testing for empty matches + flags can contain + match_condassert - this is an assertion condition + match_isgroup - this is the start of a bracketed group + +Returns: MATCH_MATCH if matched ) these values are >= 0 + MATCH_NOMATCH if failed to match ) + a negative PCRE_ERROR_xxx value if aborted by an error condition + (e.g. stopped by recursion limit) +*/ + +static int +match(register const uschar *eptr, register const uschar *ecode, + int offset_top, match_data *md, unsigned long int ims, eptrblock *eptrb, + int flags) +{ +unsigned long int original_ims = ims; /* Save for resetting on ')' */ +register int rrc; +eptrblock newptrb; + +if (md->match_call_count++ >= md->match_limit) return PCRE_ERROR_MATCHLIMIT; + +/* At the start of a bracketed group, add the current subject pointer to the +stack of such pointers, to be re-instated at the end of the group when we hit +the closing ket. When match() is called in other circumstances, we don't add to +the stack. */ + +if ((flags & match_isgroup) != 0) + { + newptrb.prev = eptrb; + newptrb.saved_eptr = eptr; + eptrb = &newptrb; + } + +/* Now start processing the operations. */ + +for (;;) + { + int op = (int)*ecode; + int min, max, ctype; + register int i; + register int c; + BOOL minimize = FALSE; + + /* Opening capturing bracket. If there is space in the offset vector, save + the current subject position in the working slot at the top of the vector. We + mustn't change the current values of the data slot, because they may be set + from a previous iteration of this group, and be referred to by a reference + inside the group. + + If the bracket fails to match, we need to restore this value and also the + values of the final offsets, in case they were set by a previous iteration of + the same bracket. + + If there isn't enough space in the offset vector, treat this as if it were a + non-capturing bracket. Don't worry about setting the flag for the error case + here; that is handled in the code for KET. */ + + if (op > OP_BRA) + { + int offset; + int number = op - OP_BRA; + + /* For extended extraction brackets (large number), we have to fish out the + number from a dummy opcode at the start. */ + + if (number > EXTRACT_BASIC_MAX) + number = GET2(ecode, 2+LINK_SIZE); + offset = number << 1; + +#ifdef DEBUG + printf("start bracket %d subject=", number); + pchars(eptr, 16, TRUE, md); + printf("\n"); +#endif + + if (offset < md->offset_max) + { + int save_offset1 = md->offset_vector[offset]; + int save_offset2 = md->offset_vector[offset+1]; + int save_offset3 = md->offset_vector[md->offset_end - number]; + int save_capture_last = md->capture_last; + + DPRINTF(("saving %d %d %d\n", save_offset1, save_offset2, save_offset3)); + md->offset_vector[md->offset_end - number] = eptr - md->start_subject; + + do + { + if ((rrc = match(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, + eptrb, match_isgroup)) != MATCH_NOMATCH) return rrc; + md->capture_last = save_capture_last; + ecode += GET(ecode, 1); + } + while (*ecode == OP_ALT); + + DPRINTF(("bracket %d failed\n", number)); + + md->offset_vector[offset] = save_offset1; + md->offset_vector[offset+1] = save_offset2; + md->offset_vector[md->offset_end - number] = save_offset3; + + return MATCH_NOMATCH; + } + + /* Insufficient room for saving captured contents */ + + else op = OP_BRA; + } + + /* Other types of node can be handled by a switch */ + + switch(op) + { + case OP_BRA: /* Non-capturing bracket: optimized */ + DPRINTF(("start bracket 0\n")); + do + { + if ((rrc = match(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, eptrb, + match_isgroup)) != MATCH_NOMATCH) return rrc; + ecode += GET(ecode, 1); + } + while (*ecode == OP_ALT); + DPRINTF(("bracket 0 failed\n")); + return MATCH_NOMATCH; + + /* Conditional group: compilation checked that there are no more than + two branches. If the condition is false, skipping the first branch takes us + past the end if there is only one branch, but that's OK because that is + exactly what going to the ket would do. */ + + case OP_COND: + if (ecode[LINK_SIZE+1] == OP_CREF) /* Condition extract or recurse test */ + { + int offset = GET2(ecode, LINK_SIZE+2) << 1; /* Doubled ref number */ + BOOL condition = (offset == CREF_RECURSE * 2)? + (md->recursive != NULL) : + (offset < offset_top && md->offset_vector[offset] >= 0); + return match(eptr, ecode + (condition? + (LINK_SIZE + 4) : (LINK_SIZE + 1 + GET(ecode, 1))), + offset_top, md, ims, eptrb, match_isgroup); + } + + /* The condition is an assertion. Call match() to evaluate it - setting + the final argument TRUE causes it to stop at the end of an assertion. */ + + else + { + if ((rrc = match(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, NULL, + match_condassert | match_isgroup)) == MATCH_MATCH) + { + ecode += 1 + LINK_SIZE + GET(ecode, LINK_SIZE+2); + while (*ecode == OP_ALT) ecode += GET(ecode, 1); + } + else if (rrc != MATCH_NOMATCH) return rrc; + else ecode += GET(ecode, 1); + return match(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, eptrb, + match_isgroup); + } + /* Control never reaches here */ + + /* Skip over conditional reference or large extraction number data if + encountered. */ + + case OP_CREF: + case OP_BRANUMBER: + ecode += 3; + break; + + /* End of the pattern. If we are in a recursion, we should restore the + offsets appropriately and continue from after the call. */ + + case OP_END: + if (md->recursive != NULL && md->recursive->group_num == 0) + { + recursion_info *rec = md->recursive; + DPRINTF(("Hit the end in a (?0) recursion\n")); + md->recursive = rec->prev; + memmove(md->offset_vector, rec->offset_save, + rec->saved_max * sizeof(int)); + md->start_match = rec->save_start; + ims = original_ims; + ecode = rec->after_call; + break; + } + + /* Otherwise, if PCRE_NOTEMPTY is set, fail if we have matched an empty + string - backtracking will then try other alternatives, if any. */ + + if (md->notempty && eptr == md->start_match) return MATCH_NOMATCH; + md->end_match_ptr = eptr; /* Record where we ended */ + md->end_offset_top = offset_top; /* and how many extracts were taken */ + return MATCH_MATCH; + + /* Change option settings */ + + case OP_OPT: + ims = ecode[1]; + ecode += 2; + DPRINTF(("ims set to %02lx\n", ims)); + break; + + /* Assertion brackets. Check the alternative branches in turn - the + matching won't pass the KET for an assertion. If any one branch matches, + the assertion is true. Lookbehind assertions have an OP_REVERSE item at the + start of each branch to move the current point backwards, so the code at + this level is identical to the lookahead case. */ + + case OP_ASSERT: + case OP_ASSERTBACK: + do + { + if ((rrc = match(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, NULL, + match_isgroup)) == MATCH_MATCH) break; + if (rrc != MATCH_NOMATCH) return rrc; + ecode += GET(ecode, 1); + } + while (*ecode == OP_ALT); + if (*ecode == OP_KET) return MATCH_NOMATCH; + + /* If checking an assertion for a condition, return MATCH_MATCH. */ + + if ((flags & match_condassert) != 0) return MATCH_MATCH; + + /* Continue from after the assertion, updating the offsets high water + mark, since extracts may have been taken during the assertion. */ + + do ecode += GET(ecode,1); while (*ecode == OP_ALT); + ecode += 1 + LINK_SIZE; + offset_top = md->end_offset_top; + continue; + + /* Negative assertion: all branches must fail to match */ + + case OP_ASSERT_NOT: + case OP_ASSERTBACK_NOT: + do + { + if ((rrc = match(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, NULL, + match_isgroup)) == MATCH_MATCH) return MATCH_NOMATCH; + if (rrc != MATCH_NOMATCH) return rrc; + ecode += GET(ecode,1); + } + while (*ecode == OP_ALT); + + if ((flags & match_condassert) != 0) return MATCH_MATCH; + + ecode += 1 + LINK_SIZE; + continue; + + /* Move the subject pointer back. This occurs only at the start of + each branch of a lookbehind assertion. If we are too close to the start to + move back, this match function fails. When working with UTF-8 we move + back a number of characters, not bytes. */ + + case OP_REVERSE: +#ifdef SUPPORT_UTF8 + if (md->utf8) + { + c = GET(ecode,1); + for (i = 0; i < c; i++) + { + eptr--; + if (eptr < md->start_subject) return MATCH_NOMATCH; + BACKCHAR(eptr) + } + } + else +#endif + + /* No UTF-8 support, or not in UTF-8 mode: count is byte count */ + + { + eptr -= GET(ecode,1); + if (eptr < md->start_subject) return MATCH_NOMATCH; + } + + /* Skip to next op code */ + + ecode += 1 + LINK_SIZE; + break; + + /* The callout item calls an external function, if one is provided, passing + details of the match so far. This is mainly for debugging, though the + function is able to force a failure. */ + + case OP_CALLOUT: + if (pcre_callout != NULL) + { + pcre_callout_block cb; + cb.version = 0; /* Version 0 of the callout block */ + cb.callout_number = ecode[1]; + cb.offset_vector = md->offset_vector; + cb.subject = (const char *)md->start_subject; + cb.subject_length = md->end_subject - md->start_subject; + cb.start_match = md->start_match - md->start_subject; + cb.current_position = eptr - md->start_subject; + cb.capture_top = offset_top/2; + cb.capture_last = md->capture_last; + cb.callout_data = md->callout_data; + if ((rrc = (*pcre_callout)(&cb)) > 0) return MATCH_NOMATCH; + if (rrc < 0) return rrc; + } + ecode += 2; + break; + + /* Recursion either matches the current regex, or some subexpression. The + offset data is the offset to the starting bracket from the start of the + whole pattern. However, it is possible that a BRAZERO was inserted before + this bracket after we took the offset - we just skip it if encountered. + + If there are any capturing brackets started but not finished, we have to + save their starting points and reinstate them after the recursion. However, + we don't know how many such there are (offset_top records the completed + total) so we just have to save all the potential data. There may be up to + 65535 such values, which is too large to put on the stack, but using malloc + for small numbers seems expensive. As a compromise, the stack is used when + there are no more than REC_STACK_SAVE_MAX values to store; otherwise malloc + is used. A problem is what to do if the malloc fails ... there is no way of + returning to the top level with an error. Save the top REC_STACK_SAVE_MAX + values on the stack, and accept that the rest may be wrong. + + There are also other values that have to be saved. We use a chained + sequence of blocks that actually live on the stack. Thanks to Robin Houston + for the original version of this logic. */ + + case OP_RECURSE: + { + int stacksave[REC_STACK_SAVE_MAX]; + recursion_info new_recursive; + const uschar *callpat = md->start_code + GET(ecode, 1); + + if (*callpat == OP_BRAZERO) callpat++; + + new_recursive.group_num = *callpat - OP_BRA; + + /* For extended extraction brackets (large number), we have to fish out + the number from a dummy opcode at the start. */ + + if (new_recursive.group_num > EXTRACT_BASIC_MAX) + new_recursive.group_num = GET2(callpat, 2+LINK_SIZE); + + /* Add to "recursing stack" */ + + new_recursive.prev = md->recursive; + md->recursive = &new_recursive; + + /* Find where to continue from afterwards */ + + ecode += 1 + LINK_SIZE; + new_recursive.after_call = ecode; + + /* Now save the offset data. */ + + new_recursive.saved_max = md->offset_end; + if (new_recursive.saved_max <= REC_STACK_SAVE_MAX) + new_recursive.offset_save = stacksave; + else + { + new_recursive.offset_save = + (int *)(pcre_malloc)(new_recursive.saved_max * sizeof(int)); + if (new_recursive.offset_save == NULL) return PCRE_ERROR_NOMEMORY; + } + + memcpy(new_recursive.offset_save, md->offset_vector, + new_recursive.saved_max * sizeof(int)); + new_recursive.save_start = md->start_match; + md->start_match = eptr; + + /* OK, now we can do the recursion. For each top-level alternative we + restore the offset and recursion data. */ + + DPRINTF(("Recursing into group %d\n", new_recursive.group_num)); + do + { + if ((rrc = match(eptr, callpat + 1 + LINK_SIZE, offset_top, md, ims, + eptrb, match_isgroup)) == MATCH_MATCH) + { + md->recursive = new_recursive.prev; + if (new_recursive.offset_save != stacksave) + (pcre_free)(new_recursive.offset_save); + return MATCH_MATCH; + } + else if (rrc != MATCH_NOMATCH) return rrc; + + md->recursive = &new_recursive; + memcpy(md->offset_vector, new_recursive.offset_save, + new_recursive.saved_max * sizeof(int)); + callpat += GET(callpat, 1); + } + while (*callpat == OP_ALT); + + DPRINTF(("Recursion didn't match\n")); + md->recursive = new_recursive.prev; + if (new_recursive.offset_save != stacksave) + (pcre_free)(new_recursive.offset_save); + return MATCH_NOMATCH; + } + /* Control never reaches here */ + + /* "Once" brackets are like assertion brackets except that after a match, + the point in the subject string is not moved back. Thus there can never be + a move back into the brackets. Friedl calls these "atomic" subpatterns. + Check the alternative branches in turn - the matching won't pass the KET + for this kind of subpattern. If any one branch matches, we carry on as at + the end of a normal bracket, leaving the subject pointer. */ + + case OP_ONCE: + { + const uschar *prev = ecode; + const uschar *saved_eptr = eptr; + + do + { + if ((rrc = match(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, + eptrb, match_isgroup)) == MATCH_MATCH) break; + if (rrc != MATCH_NOMATCH) return rrc; + ecode += GET(ecode,1); + } + while (*ecode == OP_ALT); + + /* If hit the end of the group (which could be repeated), fail */ + + if (*ecode != OP_ONCE && *ecode != OP_ALT) return MATCH_NOMATCH; + + /* Continue as from after the assertion, updating the offsets high water + mark, since extracts may have been taken. */ + + do ecode += GET(ecode,1); while (*ecode == OP_ALT); + + offset_top = md->end_offset_top; + eptr = md->end_match_ptr; + + /* For a non-repeating ket, just continue at this level. This also + happens for a repeating ket if no characters were matched in the group. + This is the forcible breaking of infinite loops as implemented in Perl + 5.005. If there is an options reset, it will get obeyed in the normal + course of events. */ + + if (*ecode == OP_KET || eptr == saved_eptr) + { + ecode += 1+LINK_SIZE; + break; + } + + /* The repeating kets try the rest of the pattern or restart from the + preceding bracket, in the appropriate order. We need to reset any options + that changed within the bracket before re-running it, so check the next + opcode. */ + + if (ecode[1+LINK_SIZE] == OP_OPT) + { + ims = (ims & ~PCRE_IMS) | ecode[4]; + DPRINTF(("ims set to %02lx at group repeat\n", ims)); + } + + if (*ecode == OP_KETRMIN) + { + if ((rrc = match(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, + eptrb, 0)) != MATCH_NOMATCH) return rrc; + if ((rrc = match(eptr, prev, offset_top, md, ims, eptrb, + match_isgroup)) != MATCH_NOMATCH) return rrc; + } + else /* OP_KETRMAX */ + { + if ((rrc = match(eptr, prev, offset_top, md, ims, eptrb, + match_isgroup)) != MATCH_NOMATCH) return rrc; + if ((rrc = match(eptr, ecode + 1+LINK_SIZE, offset_top, md, ims, eptrb, + 0)) != MATCH_NOMATCH) return rrc; + } + } + return MATCH_NOMATCH; + + /* An alternation is the end of a branch; scan along to find the end of the + bracketed group and go to there. */ + + case OP_ALT: + do ecode += GET(ecode,1); while (*ecode == OP_ALT); + break; + + /* BRAZERO and BRAMINZERO occur just before a bracket group, indicating + that it may occur zero times. It may repeat infinitely, or not at all - + i.e. it could be ()* or ()? in the pattern. Brackets with fixed upper + repeat limits are compiled as a number of copies, with the optional ones + preceded by BRAZERO or BRAMINZERO. */ + + case OP_BRAZERO: + { + const uschar *next = ecode+1; + if ((rrc = match(eptr, next, offset_top, md, ims, eptrb, match_isgroup)) + != MATCH_NOMATCH) return rrc; + do next += GET(next,1); while (*next == OP_ALT); + ecode = next + 1+LINK_SIZE; + } + break; + + case OP_BRAMINZERO: + { + const uschar *next = ecode+1; + do next += GET(next,1); while (*next == OP_ALT); + if ((rrc = match(eptr, next + 1+LINK_SIZE, offset_top, md, ims, eptrb, + match_isgroup)) != MATCH_NOMATCH) return rrc; + ecode++; + } + break; + + /* End of a group, repeated or non-repeating. If we are at the end of + an assertion "group", stop matching and return MATCH_MATCH, but record the + current high water mark for use by positive assertions. Do this also + for the "once" (not-backup up) groups. */ + + case OP_KET: + case OP_KETRMIN: + case OP_KETRMAX: + { + const uschar *prev = ecode - GET(ecode, 1); + const uschar *saved_eptr = eptrb->saved_eptr; + + eptrb = eptrb->prev; /* Back up the stack of bracket start pointers */ + + if (*prev == OP_ASSERT || *prev == OP_ASSERT_NOT || + *prev == OP_ASSERTBACK || *prev == OP_ASSERTBACK_NOT || + *prev == OP_ONCE) + { + md->end_match_ptr = eptr; /* For ONCE */ + md->end_offset_top = offset_top; + return MATCH_MATCH; + } + + /* In all other cases except a conditional group we have to check the + group number back at the start and if necessary complete handling an + extraction by setting the offsets and bumping the high water mark. */ + + if (*prev != OP_COND) + { + int offset; + int number = *prev - OP_BRA; + + /* For extended extraction brackets (large number), we have to fish out + the number from a dummy opcode at the start. */ + + if (number > EXTRACT_BASIC_MAX) number = GET2(prev, 2+LINK_SIZE); + offset = number << 1; + +#ifdef DEBUG + printf("end bracket %d", number); + printf("\n"); +#endif + + /* Test for a numbered group. This includes groups called as a result + of recursion. Note that whole-pattern recursion is coded as a recurse + into group 0, so it won't be picked up here. Instead, we catch it when + the OP_END is reached. */ + + if (number > 0) + { + md->capture_last = number; + if (offset >= md->offset_max) md->offset_overflow = TRUE; else + { + md->offset_vector[offset] = + md->offset_vector[md->offset_end - number]; + md->offset_vector[offset+1] = eptr - md->start_subject; + if (offset_top <= offset) offset_top = offset + 2; + } + + /* Handle a recursively called group. Restore the offsets + appropriately and continue from after the call. */ + + if (md->recursive != NULL && md->recursive->group_num == number) + { + recursion_info *rec = md->recursive; + DPRINTF(("Recursion (%d) succeeded - continuing\n", number)); + md->recursive = rec->prev; + md->start_match = rec->save_start; + memcpy(md->offset_vector, rec->offset_save, + rec->saved_max * sizeof(int)); + ecode = rec->after_call; + ims = original_ims; + break; + } + } + } + + /* Reset the value of the ims flags, in case they got changed during + the group. */ + + ims = original_ims; + DPRINTF(("ims reset to %02lx\n", ims)); + + /* For a non-repeating ket, just continue at this level. This also + happens for a repeating ket if no characters were matched in the group. + This is the forcible breaking of infinite loops as implemented in Perl + 5.005. If there is an options reset, it will get obeyed in the normal + course of events. */ + + if (*ecode == OP_KET || eptr == saved_eptr) + { + ecode += 1 + LINK_SIZE; + break; + } + + /* The repeating kets try the rest of the pattern or restart from the + preceding bracket, in the appropriate order. */ + + if (*ecode == OP_KETRMIN) + { + if ((rrc = match(eptr, ecode + 1+LINK_SIZE, offset_top, md, ims, eptrb, + 0)) != MATCH_NOMATCH) return rrc; + if ((rrc = match(eptr, prev, offset_top, md, ims, eptrb, + match_isgroup)) != MATCH_NOMATCH) return rrc; + } + else /* OP_KETRMAX */ + { + if ((rrc = match(eptr, prev, offset_top, md, ims, eptrb, + match_isgroup)) != MATCH_NOMATCH) return rrc; + if ((rrc = match(eptr, ecode + 1+LINK_SIZE, offset_top, md, ims, eptrb, + 0)) != MATCH_NOMATCH) return rrc; + } + } + return MATCH_NOMATCH; + + /* Start of subject unless notbol, or after internal newline if multiline */ + + case OP_CIRC: + if (md->notbol && eptr == md->start_subject) return MATCH_NOMATCH; + if ((ims & PCRE_MULTILINE) != 0) + { + if (eptr != md->start_subject && eptr[-1] != NEWLINE) + return MATCH_NOMATCH; + ecode++; + break; + } + /* ... else fall through */ + + /* Start of subject assertion */ + + case OP_SOD: + if (eptr != md->start_subject) return MATCH_NOMATCH; + ecode++; + break; + + /* Start of match assertion */ + + case OP_SOM: + if (eptr != md->start_subject + md->start_offset) return MATCH_NOMATCH; + ecode++; + break; + + /* Assert before internal newline if multiline, or before a terminating + newline unless endonly is set, else end of subject unless noteol is set. */ + + case OP_DOLL: + if ((ims & PCRE_MULTILINE) != 0) + { + if (eptr < md->end_subject) + { if (*eptr != NEWLINE) return MATCH_NOMATCH; } + else + { if (md->noteol) return MATCH_NOMATCH; } + ecode++; + break; + } + else + { + if (md->noteol) return MATCH_NOMATCH; + if (!md->endonly) + { + if (eptr < md->end_subject - 1 || + (eptr == md->end_subject - 1 && *eptr != NEWLINE)) + return MATCH_NOMATCH; + ecode++; + break; + } + } + /* ... else fall through */ + + /* End of subject assertion (\z) */ + + case OP_EOD: + if (eptr < md->end_subject) return MATCH_NOMATCH; + ecode++; + break; + + /* End of subject or ending \n assertion (\Z) */ + + case OP_EODN: + if (eptr < md->end_subject - 1 || + (eptr == md->end_subject - 1 && *eptr != NEWLINE)) return MATCH_NOMATCH; + ecode++; + break; + + /* Word boundary assertions */ + + case OP_NOT_WORD_BOUNDARY: + case OP_WORD_BOUNDARY: + { + BOOL prev_is_word, cur_is_word; + + /* Find out if the previous and current characters are "word" characters. + It takes a bit more work in UTF-8 mode. Characters > 255 are assumed to + be "non-word" characters. */ + +#ifdef SUPPORT_UTF8 + if (md->utf8) + { + if (eptr == md->start_subject) prev_is_word = FALSE; else + { + const uschar *lastptr = eptr - 1; + while((*lastptr & 0xc0) == 0x80) lastptr--; + GETCHAR(c, lastptr); + prev_is_word = c < 256 && (md->ctypes[c] & ctype_word) != 0; + } + if (eptr >= md->end_subject) cur_is_word = FALSE; else + { + GETCHAR(c, eptr); + cur_is_word = c < 256 && (md->ctypes[c] & ctype_word) != 0; + } + } + else +#endif + + /* More streamlined when not in UTF-8 mode */ + + { + prev_is_word = (eptr != md->start_subject) && + ((md->ctypes[eptr[-1]] & ctype_word) != 0); + cur_is_word = (eptr < md->end_subject) && + ((md->ctypes[*eptr] & ctype_word) != 0); + } + + /* Now see if the situation is what we want */ + + if ((*ecode++ == OP_WORD_BOUNDARY)? + cur_is_word == prev_is_word : cur_is_word != prev_is_word) + return MATCH_NOMATCH; + } + break; + + /* Match a single character type; inline for speed */ + + case OP_ANY: + if ((ims & PCRE_DOTALL) == 0 && eptr < md->end_subject && *eptr == NEWLINE) + return MATCH_NOMATCH; + if (eptr++ >= md->end_subject) return MATCH_NOMATCH; +#ifdef SUPPORT_UTF8 + if (md->utf8) + while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++; +#endif + ecode++; + break; + + /* Match a single byte, even in UTF-8 mode. This opcode really does match + any byte, even newline, independent of the setting of PCRE_DOTALL. */ + + case OP_ANYBYTE: + if (eptr++ >= md->end_subject) return MATCH_NOMATCH; + ecode++; + break; + + case OP_NOT_DIGIT: + if (eptr >= md->end_subject) return MATCH_NOMATCH; + GETCHARINCTEST(c, eptr); + if ( +#ifdef SUPPORT_UTF8 + c < 256 && +#endif + (md->ctypes[c] & ctype_digit) != 0 + ) + return MATCH_NOMATCH; + ecode++; + break; + + case OP_DIGIT: + if (eptr >= md->end_subject) return MATCH_NOMATCH; + GETCHARINCTEST(c, eptr); + if ( +#ifdef SUPPORT_UTF8 + c >= 256 || +#endif + (md->ctypes[c] & ctype_digit) == 0 + ) + return MATCH_NOMATCH; + ecode++; + break; + + case OP_NOT_WHITESPACE: + if (eptr >= md->end_subject) return MATCH_NOMATCH; + GETCHARINCTEST(c, eptr); + if ( +#ifdef SUPPORT_UTF8 + c < 256 && +#endif + (md->ctypes[c] & ctype_space) != 0 + ) + return MATCH_NOMATCH; + ecode++; + break; + + case OP_WHITESPACE: + if (eptr >= md->end_subject) return MATCH_NOMATCH; + GETCHARINCTEST(c, eptr); + if ( +#ifdef SUPPORT_UTF8 + c >= 256 || +#endif + (md->ctypes[c] & ctype_space) == 0 + ) + return MATCH_NOMATCH; + ecode++; + break; + + case OP_NOT_WORDCHAR: + if (eptr >= md->end_subject) return MATCH_NOMATCH; + GETCHARINCTEST(c, eptr); + if ( +#ifdef SUPPORT_UTF8 + c < 256 && +#endif + (md->ctypes[c] & ctype_word) != 0 + ) + return MATCH_NOMATCH; + ecode++; + break; + + case OP_WORDCHAR: + if (eptr >= md->end_subject) return MATCH_NOMATCH; + GETCHARINCTEST(c, eptr); + if ( +#ifdef SUPPORT_UTF8 + c >= 256 || +#endif + (md->ctypes[c] & ctype_word) == 0 + ) + return MATCH_NOMATCH; + ecode++; + break; + + /* Match a back reference, possibly repeatedly. Look past the end of the + item to see if there is repeat information following. The code is similar + to that for character classes, but repeated for efficiency. Then obey + similar code to character type repeats - written out again for speed. + However, if the referenced string is the empty string, always treat + it as matched, any number of times (otherwise there could be infinite + loops). */ + + case OP_REF: + { + int length; + int offset = GET2(ecode, 1) << 1; /* Doubled ref number */ + ecode += 3; /* Advance past item */ + + /* If the reference is unset, set the length to be longer than the amount + of subject left; this ensures that every attempt at a match fails. We + can't just fail here, because of the possibility of quantifiers with zero + minima. */ + + length = (offset >= offset_top || md->offset_vector[offset] < 0)? + md->end_subject - eptr + 1 : + md->offset_vector[offset+1] - md->offset_vector[offset]; + + /* Set up for repetition, or handle the non-repeated case */ + + switch (*ecode) + { + case OP_CRSTAR: + case OP_CRMINSTAR: + case OP_CRPLUS: + case OP_CRMINPLUS: + case OP_CRQUERY: + case OP_CRMINQUERY: + c = *ecode++ - OP_CRSTAR; + minimize = (c & 1) != 0; + min = rep_min[c]; /* Pick up values from tables; */ + max = rep_max[c]; /* zero for max => infinity */ + if (max == 0) max = INT_MAX; + break; + + case OP_CRRANGE: + case OP_CRMINRANGE: + minimize = (*ecode == OP_CRMINRANGE); + min = GET2(ecode, 1); + max = GET2(ecode, 3); + if (max == 0) max = INT_MAX; + ecode += 5; + break; + + default: /* No repeat follows */ + if (!match_ref(offset, eptr, length, md, ims)) return MATCH_NOMATCH; + eptr += length; + continue; /* With the main loop */ + } + + /* If the length of the reference is zero, just continue with the + main loop. */ + + if (length == 0) continue; + + /* First, ensure the minimum number of matches are present. We get back + the length of the reference string explicitly rather than passing the + address of eptr, so that eptr can be a register variable. */ + + for (i = 1; i <= min; i++) + { + if (!match_ref(offset, eptr, length, md, ims)) return MATCH_NOMATCH; + eptr += length; + } + + /* If min = max, continue at the same level without recursion. + They are not both allowed to be zero. */ + + if (min == max) continue; + + /* If minimizing, keep trying and advancing the pointer */ + + if (minimize) + { + for (i = min;; i++) + { + if ((rrc = match(eptr, ecode, offset_top, md, ims, eptrb, 0)) != + MATCH_NOMATCH) return rrc; + if (i >= max || !match_ref(offset, eptr, length, md, ims)) + return MATCH_NOMATCH; + eptr += length; + } + /* Control never gets here */ + } + + /* If maximizing, find the longest string and work backwards */ + + else + { + const uschar *pp = eptr; + for (i = min; i < max; i++) + { + if (!match_ref(offset, eptr, length, md, ims)) break; + eptr += length; + } + while (eptr >= pp) + { + if ((rrc = match(eptr, ecode, offset_top, md, ims, eptrb, 0)) != + MATCH_NOMATCH) return rrc; + eptr -= length; + } + return MATCH_NOMATCH; + } + } + /* Control never gets here */ + + + + /* Match a bit-mapped character class, possibly repeatedly. This op code is + used when all the characters in the class have values in the range 0-255. + The only difference between OP_CLASS and OP_NCLASS occurs when a data + character outside the range is encountered. + + First, look past the end of the item to see if there is repeat information + following. Then obey similar code to character type repeats - written out + again for speed. */ + + case OP_NCLASS: + case OP_CLASS: + { + const uschar *data = ecode + 1; /* Save for matching */ + ecode += 33; /* Advance past the item */ + + switch (*ecode) + { + case OP_CRSTAR: + case OP_CRMINSTAR: + case OP_CRPLUS: + case OP_CRMINPLUS: + case OP_CRQUERY: + case OP_CRMINQUERY: + c = *ecode++ - OP_CRSTAR; + minimize = (c & 1) != 0; + min = rep_min[c]; /* Pick up values from tables; */ + max = rep_max[c]; /* zero for max => infinity */ + if (max == 0) max = INT_MAX; + break; + + case OP_CRRANGE: + case OP_CRMINRANGE: + minimize = (*ecode == OP_CRMINRANGE); + min = GET2(ecode, 1); + max = GET2(ecode, 3); + if (max == 0) max = INT_MAX; + ecode += 5; + break; + + default: /* No repeat follows */ + min = max = 1; + break; + } + + /* First, ensure the minimum number of matches are present. */ + +#ifdef SUPPORT_UTF8 + /* UTF-8 mode */ + if (md->utf8) + { + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) return MATCH_NOMATCH; + GETCHARINC(c, eptr); + if (c > 255) + { + if (op == OP_CLASS) return MATCH_NOMATCH; + } + else + { + if ((data[c/8] & (1 << (c&7))) == 0) return MATCH_NOMATCH; + } + } + } + else +#endif + /* Not UTF-8 mode */ + { + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) return MATCH_NOMATCH; + c = *eptr++; + if ((data[c/8] & (1 << (c&7))) == 0) return MATCH_NOMATCH; + } + } + + /* If max == min we can continue with the main loop without the + need to recurse. */ + + if (min == max) continue; + + /* If minimizing, keep testing the rest of the expression and advancing + the pointer while it matches the class. */ + + if (minimize) + { +#ifdef SUPPORT_UTF8 + /* UTF-8 mode */ + if (md->utf8) + { + for (i = min;; i++) + { + if ((rrc = match(eptr, ecode, offset_top, md, ims, eptrb, 0)) != + MATCH_NOMATCH) return rrc; + if (i >= max || eptr >= md->end_subject) return MATCH_NOMATCH; + GETCHARINC(c, eptr); + if (c > 255) + { + if (op == OP_CLASS) return MATCH_NOMATCH; + } + else + { + if ((data[c/8] & (1 << (c&7))) == 0) return MATCH_NOMATCH; + } + } + } + else +#endif + /* Not UTF-8 mode */ + { + for (i = min;; i++) + { + if ((rrc = match(eptr, ecode, offset_top, md, ims, eptrb, 0)) != + MATCH_NOMATCH) return rrc; + if (i >= max || eptr >= md->end_subject) return MATCH_NOMATCH; + c = *eptr++; + if ((data[c/8] & (1 << (c&7))) == 0) return MATCH_NOMATCH; + } + } + /* Control never gets here */ + } + + /* If maximizing, find the longest possible run, then work backwards. */ + + else + { + const uschar *pp = eptr; + +#ifdef SUPPORT_UTF8 + /* UTF-8 mode */ + if (md->utf8) + { + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) break; + GETCHARLEN(c, eptr, len); + if (c > 255) + { + if (op == OP_CLASS) break; + } + else + { + if ((data[c/8] & (1 << (c&7))) == 0) break; + } + eptr += len; + } + for (;;) + { + if ((rrc = match(eptr, ecode, offset_top, md, ims, eptrb, 0)) != + MATCH_NOMATCH) return rrc; + if (eptr-- == pp) break; /* Stop if tried at original pos */ + BACKCHAR(eptr); + } + } + else +#endif + /* Not UTF-8 mode */ + { + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject) break; + c = *eptr; + if ((data[c/8] & (1 << (c&7))) == 0) break; + eptr++; + } + while (eptr >= pp) + { + if ((rrc = match(eptr--, ecode, offset_top, md, ims, eptrb, 0)) != + MATCH_NOMATCH) return rrc; + } + } + + return MATCH_NOMATCH; + } + } + /* Control never gets here */ + + + /* Match an extended character class. This opcode is encountered only + in UTF-8 mode, because that's the only time it is compiled. */ + +#ifdef SUPPORT_UTF8 + case OP_XCLASS: + { + const uschar *data = ecode + 1 + LINK_SIZE; /* Save for matching */ + ecode += GET(ecode, 1); /* Advance past the item */ + + switch (*ecode) + { + case OP_CRSTAR: + case OP_CRMINSTAR: + case OP_CRPLUS: + case OP_CRMINPLUS: + case OP_CRQUERY: + case OP_CRMINQUERY: + c = *ecode++ - OP_CRSTAR; + minimize = (c & 1) != 0; + min = rep_min[c]; /* Pick up values from tables; */ + max = rep_max[c]; /* zero for max => infinity */ + if (max == 0) max = INT_MAX; + break; + + case OP_CRRANGE: + case OP_CRMINRANGE: + minimize = (*ecode == OP_CRMINRANGE); + min = GET2(ecode, 1); + max = GET2(ecode, 3); + if (max == 0) max = INT_MAX; + ecode += 5; + break; + + default: /* No repeat follows */ + min = max = 1; + break; + } + + /* First, ensure the minimum number of matches are present. */ + + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) return MATCH_NOMATCH; + GETCHARINC(c, eptr); + if (!match_xclass(c, data)) return MATCH_NOMATCH; + } + + /* If max == min we can continue with the main loop without the + need to recurse. */ + + if (min == max) continue; + + /* If minimizing, keep testing the rest of the expression and advancing + the pointer while it matches the class. */ + + if (minimize) + { + for (i = min;; i++) + { + if ((rrc = match(eptr, ecode, offset_top, md, ims, eptrb, 0)) != + MATCH_NOMATCH) return rrc; + if (i >= max || eptr >= md->end_subject) return MATCH_NOMATCH; + GETCHARINC(c, eptr); + if (!match_xclass(c, data)) return MATCH_NOMATCH; + } + /* Control never gets here */ + } + + /* If maximizing, find the longest possible run, then work backwards. */ + + else + { + const uschar *pp = eptr; + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) break; + GETCHARLEN(c, eptr, len); + if (!match_xclass(c, data)) break; + eptr += len; + } + for(;;) + { + if ((rrc = match(eptr, ecode, offset_top, md, ims, eptrb, 0)) != + MATCH_NOMATCH) return rrc; + if (eptr-- == pp) break; /* Stop if tried at original pos */ + BACKCHAR(eptr) + } + return MATCH_NOMATCH; + } + + /* Control never gets here */ + } +#endif /* End of XCLASS */ + + /* Match a run of characters */ + + case OP_CHARS: + { + register int length = ecode[1]; + ecode += 2; + +#ifdef DEBUG /* Sigh. Some compilers never learn. */ + if (eptr >= md->end_subject) + printf("matching subject against pattern "); + else + { + printf("matching subject "); + pchars(eptr, length, TRUE, md); + printf(" against pattern "); + } + pchars(ecode, length, FALSE, md); + printf("\n"); +#endif + + if (length > md->end_subject - eptr) return MATCH_NOMATCH; + if ((ims & PCRE_CASELESS) != 0) + { + while (length-- > 0) + if (md->lcc[*ecode++] != md->lcc[*eptr++]) + return MATCH_NOMATCH; + } + else + { + while (length-- > 0) if (*ecode++ != *eptr++) return MATCH_NOMATCH; + } + } + break; + + /* Match a single character repeatedly; different opcodes share code. */ + + case OP_EXACT: + min = max = GET2(ecode, 1); + ecode += 3; + goto REPEATCHAR; + + case OP_UPTO: + case OP_MINUPTO: + min = 0; + max = GET2(ecode, 1); + minimize = *ecode == OP_MINUPTO; + ecode += 3; + goto REPEATCHAR; + + case OP_STAR: + case OP_MINSTAR: + case OP_PLUS: + case OP_MINPLUS: + case OP_QUERY: + case OP_MINQUERY: + c = *ecode++ - OP_STAR; + minimize = (c & 1) != 0; + min = rep_min[c]; /* Pick up values from tables; */ + max = rep_max[c]; /* zero for max => infinity */ + if (max == 0) max = INT_MAX; + + /* Common code for all repeated single-character matches. We can give + up quickly if there are fewer than the minimum number of characters left in + the subject. */ + + REPEATCHAR: +#ifdef SUPPORT_UTF8 + if (md->utf8) + { + int len = 1; + const uschar *charptr = ecode; + GETCHARLEN(c, ecode, len); + if (min * len > md->end_subject - eptr) return MATCH_NOMATCH; + ecode += len; + + /* Handle multibyte character matching specially here. There is no + support for any kind of casing for multibyte characters. */ + + if (len > 1) + { + for (i = 1; i <= min; i++) + { + if (memcmp(eptr, charptr, len) != 0) return MATCH_NOMATCH; + eptr += len; + } + + if (min == max) continue; + + if (minimize) + { + for (i = min;; i++) + { + if ((rrc = match(eptr, ecode, offset_top, md, ims, eptrb, 0)) != + MATCH_NOMATCH) return rrc; + if (i >= max || + eptr >= md->end_subject || + memcmp(eptr, charptr, len) != 0) + return MATCH_NOMATCH; + eptr += len; + } + /* Control never gets here */ + } + else + { + const uschar *pp = eptr; + for (i = min; i < max; i++) + { + if (eptr > md->end_subject - len || + memcmp(eptr, charptr, len) != 0) + break; + eptr += len; + } + while (eptr >= pp) + { + if ((rrc = match(eptr, ecode, offset_top, md, ims, eptrb, 0)) != + MATCH_NOMATCH) return rrc; + eptr -= len; + } + return MATCH_NOMATCH; + } + /* Control never gets here */ + } + + /* If the length of a UTF-8 character is 1, we fall through here, and + obey the code as for non-UTF-8 characters below, though in this case the + value of c will always be < 128. */ + } + else +#endif + + /* When not in UTF-8 mode, load a single-byte character. */ + { + if (min > md->end_subject - eptr) return MATCH_NOMATCH; + c = *ecode++; + } + + /* The value of c at this point is always less than 256, though we may or + may not be in UTF-8 mode. The code is duplicated for the caseless and + caseful cases, for speed, since matching characters is likely to be quite + common. First, ensure the minimum number of matches are present. If min = + max, continue at the same level without recursing. Otherwise, if + minimizing, keep trying the rest of the expression and advancing one + matching character if failing, up to the maximum. Alternatively, if + maximizing, find the maximum number of characters and work backwards. */ + + DPRINTF(("matching %c{%d,%d} against subject %.*s\n", c, min, max, + max, eptr)); + + if ((ims & PCRE_CASELESS) != 0) + { + c = md->lcc[c]; + for (i = 1; i <= min; i++) + if (c != md->lcc[*eptr++]) return MATCH_NOMATCH; + if (min == max) continue; + if (minimize) + { + for (i = min;; i++) + { + if ((rrc = match(eptr, ecode, offset_top, md, ims, eptrb, 0)) != + MATCH_NOMATCH) return rrc; + if (i >= max || eptr >= md->end_subject || + c != md->lcc[*eptr++]) + return MATCH_NOMATCH; + } + /* Control never gets here */ + } + else + { + const uschar *pp = eptr; + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject || c != md->lcc[*eptr]) break; + eptr++; + } + while (eptr >= pp) + if ((rrc = match(eptr--, ecode, offset_top, md, ims, eptrb, 0)) != + MATCH_NOMATCH) return rrc; + return MATCH_NOMATCH; + } + /* Control never gets here */ + } + + /* Caseful comparisons (includes all multi-byte characters) */ + + else + { + for (i = 1; i <= min; i++) if (c != *eptr++) return MATCH_NOMATCH; + if (min == max) continue; + if (minimize) + { + for (i = min;; i++) + { + if ((rrc = match(eptr, ecode, offset_top, md, ims, eptrb, 0)) != + MATCH_NOMATCH) return rrc; + if (i >= max || eptr >= md->end_subject || c != *eptr++) + return MATCH_NOMATCH; + } + /* Control never gets here */ + } + else + { + const uschar *pp = eptr; + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject || c != *eptr) break; + eptr++; + } + while (eptr >= pp) + if ((rrc = match(eptr--, ecode, offset_top, md, ims, eptrb, 0)) != + MATCH_NOMATCH) return rrc; + return MATCH_NOMATCH; + } + } + /* Control never gets here */ + + /* Match a negated single one-byte character. The character we are + checking can be multibyte. */ + + case OP_NOT: + if (eptr >= md->end_subject) return MATCH_NOMATCH; + ecode++; + GETCHARINCTEST(c, eptr); + if ((ims & PCRE_CASELESS) != 0) + { +#ifdef SUPPORT_UTF8 + if (c < 256) +#endif + c = md->lcc[c]; + if (md->lcc[*ecode++] == c) return MATCH_NOMATCH; + } + else + { + if (*ecode++ == c) return MATCH_NOMATCH; + } + break; + + /* Match a negated single one-byte character repeatedly. This is almost a + repeat of the code for a repeated single character, but I haven't found a + nice way of commoning these up that doesn't require a test of the + positive/negative option for each character match. Maybe that wouldn't add + very much to the time taken, but character matching *is* what this is all + about... */ + + case OP_NOTEXACT: + min = max = GET2(ecode, 1); + ecode += 3; + goto REPEATNOTCHAR; + + case OP_NOTUPTO: + case OP_NOTMINUPTO: + min = 0; + max = GET2(ecode, 1); + minimize = *ecode == OP_NOTMINUPTO; + ecode += 3; + goto REPEATNOTCHAR; + + case OP_NOTSTAR: + case OP_NOTMINSTAR: + case OP_NOTPLUS: + case OP_NOTMINPLUS: + case OP_NOTQUERY: + case OP_NOTMINQUERY: + c = *ecode++ - OP_NOTSTAR; + minimize = (c & 1) != 0; + min = rep_min[c]; /* Pick up values from tables; */ + max = rep_max[c]; /* zero for max => infinity */ + if (max == 0) max = INT_MAX; + + /* Common code for all repeated single-character (less than 255) matches. + We can give up quickly if there are fewer than the minimum number of + characters left in the subject. */ + + REPEATNOTCHAR: + if (min > md->end_subject - eptr) return MATCH_NOMATCH; + c = *ecode++; + + /* The code is duplicated for the caseless and caseful cases, for speed, + since matching characters is likely to be quite common. First, ensure the + minimum number of matches are present. If min = max, continue at the same + level without recursing. Otherwise, if minimizing, keep trying the rest of + the expression and advancing one matching character if failing, up to the + maximum. Alternatively, if maximizing, find the maximum number of + characters and work backwards. */ + + DPRINTF(("negative matching %c{%d,%d} against subject %.*s\n", c, min, max, + max, eptr)); + + if ((ims & PCRE_CASELESS) != 0) + { + c = md->lcc[c]; + +#ifdef SUPPORT_UTF8 + /* UTF-8 mode */ + if (md->utf8) + { + register int d; + for (i = 1; i <= min; i++) + { + GETCHARINC(d, eptr); + if (d < 256) d = md->lcc[d]; + if (c == d) return MATCH_NOMATCH; + } + } + else +#endif + + /* Not UTF-8 mode */ + { + for (i = 1; i <= min; i++) + if (c == md->lcc[*eptr++]) return MATCH_NOMATCH; + } + + if (min == max) continue; + + if (minimize) + { +#ifdef SUPPORT_UTF8 + /* UTF-8 mode */ + if (md->utf8) + { + register int d; + for (i = min;; i++) + { + if ((rrc = match(eptr, ecode, offset_top, md, ims, eptrb, 0)) != + MATCH_NOMATCH) return rrc; + GETCHARINC(d, eptr); + if (d < 256) d = md->lcc[d]; + if (i >= max || eptr >= md->end_subject || c == d) + return MATCH_NOMATCH; + } + } + else +#endif + /* Not UTF-8 mode */ + { + for (i = min;; i++) + { + if ((rrc = match(eptr, ecode, offset_top, md, ims, eptrb, 0)) != + MATCH_NOMATCH) return rrc; + if (i >= max || eptr >= md->end_subject || c == md->lcc[*eptr++]) + return MATCH_NOMATCH; + } + } + /* Control never gets here */ + } + + /* Maximize case */ + + else + { + const uschar *pp = eptr; + +#ifdef SUPPORT_UTF8 + /* UTF-8 mode */ + if (md->utf8) + { + register int d; + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) break; + GETCHARLEN(d, eptr, len); + if (d < 256) d = md->lcc[d]; + if (c == d) break; + eptr += len; + } + for(;;) + { + if ((rrc = match(eptr, ecode, offset_top, md, ims, eptrb, 0)) != + MATCH_NOMATCH) return rrc; + if (eptr-- == pp) break; /* Stop if tried at original pos */ + BACKCHAR(eptr); + } + } + else +#endif + /* Not UTF-8 mode */ + { + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject || c == md->lcc[*eptr]) break; + eptr++; + } + while (eptr >= pp) + { + if ((rrc = match(eptr, ecode, offset_top, md, ims, eptrb, 0)) != + MATCH_NOMATCH) return rrc; + eptr--; + } + } + + return MATCH_NOMATCH; + } + /* Control never gets here */ + } + + /* Caseful comparisons */ + + else + { +#ifdef SUPPORT_UTF8 + /* UTF-8 mode */ + if (md->utf8) + { + register int d; + for (i = 1; i <= min; i++) + { + GETCHARINC(d, eptr); + if (c == d) return MATCH_NOMATCH; + } + } + else +#endif + /* Not UTF-8 mode */ + { + for (i = 1; i <= min; i++) + if (c == *eptr++) return MATCH_NOMATCH; + } + + if (min == max) continue; + + if (minimize) + { +#ifdef SUPPORT_UTF8 + /* UTF-8 mode */ + if (md->utf8) + { + register int d; + for (i = min;; i++) + { + if ((rrc = match(eptr, ecode, offset_top, md, ims, eptrb, 0)) != + MATCH_NOMATCH) return rrc; + GETCHARINC(d, eptr); + if (i >= max || eptr >= md->end_subject || c == d) + return MATCH_NOMATCH; + } + } + else +#endif + /* Not UTF-8 mode */ + { + for (i = min;; i++) + { + if ((rrc = match(eptr, ecode, offset_top, md, ims, eptrb, 0)) != + MATCH_NOMATCH) return rrc; + if (i >= max || eptr >= md->end_subject || c == *eptr++) + return MATCH_NOMATCH; + } + } + /* Control never gets here */ + } + + /* Maximize case */ + + else + { + const uschar *pp = eptr; + +#ifdef SUPPORT_UTF8 + /* UTF-8 mode */ + if (md->utf8) + { + register int d; + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) break; + GETCHARLEN(d, eptr, len); + if (c == d) break; + eptr += len; + } + for(;;) + { + if ((rrc = match(eptr, ecode, offset_top, md, ims, eptrb, 0)) != + MATCH_NOMATCH) return rrc; + if (eptr-- == pp) break; /* Stop if tried at original pos */ + BACKCHAR(eptr); + } + } + else +#endif + /* Not UTF-8 mode */ + { + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject || c == *eptr) break; + eptr++; + } + while (eptr >= pp) + { + if ((rrc = match(eptr, ecode, offset_top, md, ims, eptrb, 0)) != + MATCH_NOMATCH) return rrc; + eptr--; + } + } + + return MATCH_NOMATCH; + } + } + /* Control never gets here */ + + /* Match a single character type repeatedly; several different opcodes + share code. This is very similar to the code for single characters, but we + repeat it in the interests of efficiency. */ + + case OP_TYPEEXACT: + min = max = GET2(ecode, 1); + minimize = TRUE; + ecode += 3; + goto REPEATTYPE; + + case OP_TYPEUPTO: + case OP_TYPEMINUPTO: + min = 0; + max = GET2(ecode, 1); + minimize = *ecode == OP_TYPEMINUPTO; + ecode += 3; + goto REPEATTYPE; + + case OP_TYPESTAR: + case OP_TYPEMINSTAR: + case OP_TYPEPLUS: + case OP_TYPEMINPLUS: + case OP_TYPEQUERY: + case OP_TYPEMINQUERY: + c = *ecode++ - OP_TYPESTAR; + minimize = (c & 1) != 0; + min = rep_min[c]; /* Pick up values from tables; */ + max = rep_max[c]; /* zero for max => infinity */ + if (max == 0) max = INT_MAX; + + /* Common code for all repeated single character type matches. Note that + in UTF-8 mode, '.' matches a character of any length, but for the other + character types, the valid characters are all one-byte long. */ + + REPEATTYPE: + ctype = *ecode++; /* Code for the character type */ + + /* First, ensure the minimum number of matches are present. Use inline + code for maximizing the speed, and do the type test once at the start + (i.e. keep it out of the loop). Also we can test that there are at least + the minimum number of bytes before we start. This isn't as effective in + UTF-8 mode, but it does no harm. Separate the UTF-8 code completely as that + is tidier. */ + + if (min > md->end_subject - eptr) return MATCH_NOMATCH; + if (min > 0) + { +#ifdef SUPPORT_UTF8 + if (md->utf8) switch(ctype) + { + case OP_ANY: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject || + (*eptr++ == NEWLINE && (ims & PCRE_DOTALL) == 0)) + return MATCH_NOMATCH; + while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++; + } + break; + + case OP_ANYBYTE: + eptr += min; + break; + + case OP_NOT_DIGIT: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) return MATCH_NOMATCH; + GETCHARINC(c, eptr); + if (c < 256 && (md->ctypes[c] & ctype_digit) != 0) + return MATCH_NOMATCH; + } + break; + + case OP_DIGIT: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject || + *eptr >= 128 || (md->ctypes[*eptr++] & ctype_digit) == 0) + return MATCH_NOMATCH; + /* No need to skip more bytes - we know it's a 1-byte character */ + } + break; + + case OP_NOT_WHITESPACE: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject || + (*eptr < 128 && (md->ctypes[*eptr++] & ctype_space) != 0)) + return MATCH_NOMATCH; + while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++; + } + break; + + case OP_WHITESPACE: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject || + *eptr >= 128 || (md->ctypes[*eptr++] & ctype_space) == 0) + return MATCH_NOMATCH; + /* No need to skip more bytes - we know it's a 1-byte character */ + } + break; + + case OP_NOT_WORDCHAR: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject || + (*eptr < 128 && (md->ctypes[*eptr++] & ctype_word) != 0)) + return MATCH_NOMATCH; + while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++; + } + break; + + case OP_WORDCHAR: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject || + *eptr >= 128 || (md->ctypes[*eptr++] & ctype_word) == 0) + return MATCH_NOMATCH; + /* No need to skip more bytes - we know it's a 1-byte character */ + } + break; + } + else +#endif + + /* Code for the non-UTF-8 case for minimum matching */ + + switch(ctype) + { + case OP_ANY: + if ((ims & PCRE_DOTALL) == 0) + { + for (i = 1; i <= min; i++) + if (*eptr++ == NEWLINE) return MATCH_NOMATCH; + } + else eptr += min; + break; + + case OP_ANYBYTE: + eptr += min; + break; + + case OP_NOT_DIGIT: + for (i = 1; i <= min; i++) + if ((md->ctypes[*eptr++] & ctype_digit) != 0) return MATCH_NOMATCH; + break; + + case OP_DIGIT: + for (i = 1; i <= min; i++) + if ((md->ctypes[*eptr++] & ctype_digit) == 0) return MATCH_NOMATCH; + break; + + case OP_NOT_WHITESPACE: + for (i = 1; i <= min; i++) + if ((md->ctypes[*eptr++] & ctype_space) != 0) return MATCH_NOMATCH; + break; + + case OP_WHITESPACE: + for (i = 1; i <= min; i++) + if ((md->ctypes[*eptr++] & ctype_space) == 0) return MATCH_NOMATCH; + break; + + case OP_NOT_WORDCHAR: + for (i = 1; i <= min; i++) + if ((md->ctypes[*eptr++] & ctype_word) != 0) + return MATCH_NOMATCH; + break; + + case OP_WORDCHAR: + for (i = 1; i <= min; i++) + if ((md->ctypes[*eptr++] & ctype_word) == 0) + return MATCH_NOMATCH; + break; + } + } + + /* If min = max, continue at the same level without recursing */ + + if (min == max) continue; + + /* If minimizing, we have to test the rest of the pattern before each + subsequent match. Again, separate the UTF-8 case for speed. */ + + if (minimize) + { +#ifdef SUPPORT_UTF8 + /* UTF-8 mode */ + if (md->utf8) + { + for (i = min;; i++) + { + if ((rrc = match(eptr, ecode, offset_top, md, ims, eptrb, 0)) != + MATCH_NOMATCH) return rrc; + if (i >= max || eptr >= md->end_subject) return MATCH_NOMATCH; + + GETCHARINC(c, eptr); + switch(ctype) + { + case OP_ANY: + if ((ims & PCRE_DOTALL) == 0 && c == NEWLINE) return MATCH_NOMATCH; + break; + + case OP_ANYBYTE: + break; + + case OP_NOT_DIGIT: + if (c < 256 && (md->ctypes[c] & ctype_digit) != 0) + return MATCH_NOMATCH; + break; + + case OP_DIGIT: + if (c >= 256 || (md->ctypes[c] & ctype_digit) == 0) + return MATCH_NOMATCH; + break; + + case OP_NOT_WHITESPACE: + if (c < 256 && (md->ctypes[c] & ctype_space) != 0) + return MATCH_NOMATCH; + break; + + case OP_WHITESPACE: + if (c >= 256 || (md->ctypes[c] & ctype_space) == 0) + return MATCH_NOMATCH; + break; + + case OP_NOT_WORDCHAR: + if (c < 256 && (md->ctypes[c] & ctype_word) != 0) + return MATCH_NOMATCH; + break; + + case OP_WORDCHAR: + if (c >= 256 && (md->ctypes[c] & ctype_word) == 0) + return MATCH_NOMATCH; + break; + } + } + } + else +#endif + /* Not UTF-8 mode */ + { + for (i = min;; i++) + { + if ((rrc = match(eptr, ecode, offset_top, md, ims, eptrb, 0)) != + MATCH_NOMATCH) return rrc; + if (i >= max || eptr >= md->end_subject) return MATCH_NOMATCH; + c = *eptr++; + switch(ctype) + { + case OP_ANY: + if ((ims & PCRE_DOTALL) == 0 && c == NEWLINE) return MATCH_NOMATCH; + break; + + case OP_ANYBYTE: + break; + + case OP_NOT_DIGIT: + if ((md->ctypes[c] & ctype_digit) != 0) return MATCH_NOMATCH; + break; + + case OP_DIGIT: + if ((md->ctypes[c] & ctype_digit) == 0) return MATCH_NOMATCH; + break; + + case OP_NOT_WHITESPACE: + if ((md->ctypes[c] & ctype_space) != 0) return MATCH_NOMATCH; + break; + + case OP_WHITESPACE: + if ((md->ctypes[c] & ctype_space) == 0) return MATCH_NOMATCH; + break; + + case OP_NOT_WORDCHAR: + if ((md->ctypes[c] & ctype_word) != 0) return MATCH_NOMATCH; + break; + + case OP_WORDCHAR: + if ((md->ctypes[c] & ctype_word) == 0) return MATCH_NOMATCH; + break; + } + } + } + /* Control never gets here */ + } + + /* If maximizing it is worth using inline code for speed, doing the type + test once at the start (i.e. keep it out of the loop). Again, keep the + UTF-8 stuff separate. */ + + else + { + const uschar *pp = eptr; + +#ifdef SUPPORT_UTF8 + /* UTF-8 mode */ + + if (md->utf8) + { + switch(ctype) + { + case OP_ANY: + + /* Special code is required for UTF8, but when the maximum is unlimited + we don't need it, so we repeat the non-UTF8 code. This is probably + worth it, because .* is quite a common idiom. */ + + if (max < INT_MAX) + { + if ((ims & PCRE_DOTALL) == 0) + { + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject || *eptr == NEWLINE) break; + eptr++; + while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++; + } + } + else + { + for (i = min; i < max; i++) + { + eptr++; + while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++; + } + } + } + + /* Handle unlimited UTF-8 repeat */ + + else + { + if ((ims & PCRE_DOTALL) == 0) + { + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject || *eptr == NEWLINE) break; + eptr++; + } + break; + } + else + { + c = max - min; + if (c > md->end_subject - eptr) c = md->end_subject - eptr; + eptr += c; + } + } + break; + + /* The byte case is the same as non-UTF8 */ + + case OP_ANYBYTE: + c = max - min; + if (c > md->end_subject - eptr) c = md->end_subject - eptr; + eptr += c; + break; + + case OP_NOT_DIGIT: + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) break; + GETCHARLEN(c, eptr, len); + if (c < 256 && (md->ctypes[c] & ctype_digit) != 0) break; + eptr+= len; + } + break; + + case OP_DIGIT: + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) break; + GETCHARLEN(c, eptr, len); + if (c >= 256 ||(md->ctypes[c] & ctype_digit) == 0) break; + eptr+= len; + } + break; + + case OP_NOT_WHITESPACE: + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) break; + GETCHARLEN(c, eptr, len); + if (c < 256 && (md->ctypes[c] & ctype_space) != 0) break; + eptr+= len; + } + break; + + case OP_WHITESPACE: + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) break; + GETCHARLEN(c, eptr, len); + if (c >= 256 ||(md->ctypes[c] & ctype_space) == 0) break; + eptr+= len; + } + break; + + case OP_NOT_WORDCHAR: + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) break; + GETCHARLEN(c, eptr, len); + if (c < 256 && (md->ctypes[c] & ctype_word) != 0) break; + eptr+= len; + } + break; + + case OP_WORDCHAR: + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) break; + GETCHARLEN(c, eptr, len); + if (c >= 256 || (md->ctypes[c] & ctype_word) == 0) break; + eptr+= len; + } + break; + } + + /* eptr is now past the end of the maximum run */ + + for(;;) + { + if ((rrc = match(eptr, ecode, offset_top, md, ims, eptrb, 0)) != + MATCH_NOMATCH) return rrc; + if (eptr-- == pp) break; /* Stop if tried at original pos */ + BACKCHAR(eptr); + } + } + else +#endif + + /* Not UTF-8 mode */ + { + switch(ctype) + { + case OP_ANY: + if ((ims & PCRE_DOTALL) == 0) + { + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject || *eptr == NEWLINE) break; + eptr++; + } + break; + } + /* For DOTALL case, fall through and treat as \C */ + + case OP_ANYBYTE: + c = max - min; + if (c > md->end_subject - eptr) c = md->end_subject - eptr; + eptr += c; + break; + + case OP_NOT_DIGIT: + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_digit) != 0) + break; + eptr++; + } + break; + + case OP_DIGIT: + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_digit) == 0) + break; + eptr++; + } + break; + + case OP_NOT_WHITESPACE: + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_space) != 0) + break; + eptr++; + } + break; + + case OP_WHITESPACE: + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_space) == 0) + break; + eptr++; + } + break; + + case OP_NOT_WORDCHAR: + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_word) != 0) + break; + eptr++; + } + break; + + case OP_WORDCHAR: + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_word) == 0) + break; + eptr++; + } + break; + } + + /* eptr is now past the end of the maximum run */ + + while (eptr >= pp) + { + if ((rrc = match(eptr--, ecode, offset_top, md, ims, eptrb, 0)) != + MATCH_NOMATCH) return rrc; + } + } + + /* Get here if we can't make it match with any permitted repetitions */ + + return MATCH_NOMATCH; + } + /* Control never gets here */ + + /* There's been some horrible disaster. Since all codes > OP_BRA are + for capturing brackets, and there shouldn't be any gaps between 0 and + OP_BRA, arrival here can only mean there is something seriously wrong + in the code above or the OP_xxx definitions. */ + + default: + DPRINTF(("Unknown opcode %d\n", *ecode)); + return PCRE_ERROR_UNKNOWN_NODE; + } + + /* Do not stick any code in here without much thought; it is assumed + that "continue" in the code above comes out to here to repeat the main + loop. */ + + } /* End of main loop */ +/* Control never reaches here */ +} + + + + +/************************************************* +* Execute a Regular Expression * +*************************************************/ + +/* This function applies a compiled re to a subject string and picks out +portions of the string if it matches. Two elements in the vector are set for +each substring: the offsets to the start and end of the substring. + +Arguments: + external_re points to the compiled expression + extra_data points to extra data or is NULL + subject points to the subject string + length length of subject string (may contain binary zeros) + start_offset where to start in the subject string + options option bits + offsets points to a vector of ints to be filled in with offsets + offsetcount the number of elements in the vector + +Returns: > 0 => success; value is the number of elements filled in + = 0 => success, but offsets is not big enough + -1 => failed to match + < -1 => some kind of unexpected problem +*/ + +int +pcre_exec(const pcre *external_re, const pcre_extra *extra_data, + const char *subject, int length, int start_offset, int options, int *offsets, + int offsetcount) +{ +int rc, resetcount, ocount; +int first_byte = -1; +int req_byte = -1; +int req_byte2 = -1; +unsigned long int ims = 0; +BOOL using_temporary_offsets = FALSE; +BOOL anchored; +BOOL startline; +BOOL first_byte_caseless = FALSE; +BOOL req_byte_caseless = FALSE; +match_data match_block; +const uschar *start_bits = NULL; +const uschar *start_match = (const uschar *)subject + start_offset; +const uschar *end_subject; +const uschar *req_byte_ptr = start_match - 1; +const pcre_study_data *study; +const real_pcre *re = (const real_pcre *)external_re; + +/* Plausibility checks */ + +if ((options & ~PUBLIC_EXEC_OPTIONS) != 0) return PCRE_ERROR_BADOPTION; +if (re == NULL || subject == NULL || + (offsets == NULL && offsetcount > 0)) return PCRE_ERROR_NULL; + +/* Fish out the optional data from the extra_data structure, first setting +the default values. */ + +study = NULL; +match_block.match_limit = MATCH_LIMIT; +match_block.callout_data = NULL; + +if (extra_data != NULL) + { + register unsigned int flags = extra_data->flags; + if ((flags & PCRE_EXTRA_STUDY_DATA) != 0) + study = extra_data->study_data; + if ((flags & PCRE_EXTRA_MATCH_LIMIT) != 0) + match_block.match_limit = extra_data->match_limit; + if ((flags & PCRE_EXTRA_CALLOUT_DATA) != 0) + match_block.callout_data = extra_data->callout_data; + } + +/* Now we have re supposedly pointing to the regex */ + +if (re->magic_number != MAGIC_NUMBER) return PCRE_ERROR_BADMAGIC; + +anchored = ((re->options | options) & PCRE_ANCHORED) != 0; +startline = (re->options & PCRE_STARTLINE) != 0; + +match_block.start_code = + (const uschar *)re + sizeof(real_pcre) + re->name_count * re->name_entry_size; +match_block.start_subject = (const uschar *)subject; +match_block.start_offset = start_offset; +match_block.end_subject = match_block.start_subject + length; +end_subject = match_block.end_subject; + +match_block.endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0; +match_block.utf8 = (re->options & PCRE_UTF8) != 0; + +match_block.notbol = (options & PCRE_NOTBOL) != 0; +match_block.noteol = (options & PCRE_NOTEOL) != 0; +match_block.notempty = (options & PCRE_NOTEMPTY) != 0; + +match_block.recursive = NULL; /* No recursion at top level */ + +match_block.lcc = re->tables + lcc_offset; +match_block.ctypes = re->tables + ctypes_offset; + +/* The ims options can vary during the matching as a result of the presence +of (?ims) items in the pattern. They are kept in a local variable so that +restoring at the exit of a group is easy. */ + +ims = re->options & (PCRE_CASELESS|PCRE_MULTILINE|PCRE_DOTALL); + +/* If the expression has got more back references than the offsets supplied can +hold, we get a temporary bit of working store to use during the matching. +Otherwise, we can use the vector supplied, rounding down its size to a multiple +of 3. */ + +ocount = offsetcount - (offsetcount % 3); + +if (re->top_backref > 0 && re->top_backref >= ocount/3) + { + ocount = re->top_backref * 3 + 3; + match_block.offset_vector = (int *)(pcre_malloc)(ocount * sizeof(int)); + if (match_block.offset_vector == NULL) return PCRE_ERROR_NOMEMORY; + using_temporary_offsets = TRUE; + DPRINTF(("Got memory to hold back references\n")); + } +else match_block.offset_vector = offsets; + +match_block.offset_end = ocount; +match_block.offset_max = (2*ocount)/3; +match_block.offset_overflow = FALSE; +match_block.capture_last = -1; + +/* Compute the minimum number of offsets that we need to reset each time. Doing +this makes a huge difference to execution time when there aren't many brackets +in the pattern. */ + +resetcount = 2 + re->top_bracket * 2; +if (resetcount > offsetcount) resetcount = ocount; + +/* Reset the working variable associated with each extraction. These should +never be used unless previously set, but they get saved and restored, and so we +initialize them to avoid reading uninitialized locations. */ + +if (match_block.offset_vector != NULL) + { + register int *iptr = match_block.offset_vector + ocount; + register int *iend = iptr - resetcount/2 + 1; + while (--iptr >= iend) *iptr = -1; + } + +/* Set up the first character to match, if available. The first_byte value is +never set for an anchored regular expression, but the anchoring may be forced +at run time, so we have to test for anchoring. The first char may be unset for +an unanchored pattern, of course. If there's no first char and the pattern was +studied, there may be a bitmap of possible first characters. */ + +if (!anchored) + { + if ((re->options & PCRE_FIRSTSET) != 0) + { + first_byte = re->first_byte & 255; + if ((first_byte_caseless = ((re->first_byte & REQ_CASELESS) != 0)) == TRUE) + first_byte = match_block.lcc[first_byte]; + } + else + if (!startline && study != NULL && + (study->options & PCRE_STUDY_MAPPED) != 0) + start_bits = study->start_bits; + } + +/* For anchored or unanchored matches, there may be a "last known required +character" set. */ + +if ((re->options & PCRE_REQCHSET) != 0) + { + req_byte = re->req_byte & 255; + req_byte_caseless = (re->req_byte & REQ_CASELESS) != 0; + req_byte2 = (re->tables + fcc_offset)[req_byte]; /* case flipped */ + } + +/* Loop for handling unanchored repeated matching attempts; for anchored regexs +the loop runs just once. */ + +do + { + register int *iptr = match_block.offset_vector; + register int *iend = iptr + resetcount; + + /* Reset the maximum number of extractions we might see. */ + + while (iptr < iend) *iptr++ = -1; + + /* Advance to a unique first char if possible */ + + if (first_byte >= 0) + { + if (first_byte_caseless) + while (start_match < end_subject && + match_block.lcc[*start_match] != first_byte) + start_match++; + else + while (start_match < end_subject && *start_match != first_byte) + start_match++; + } + + /* Or to just after \n for a multiline match if possible */ + + else if (startline) + { + if (start_match > match_block.start_subject + start_offset) + { + while (start_match < end_subject && start_match[-1] != NEWLINE) + start_match++; + } + } + + /* Or to a non-unique first char after study */ + + else if (start_bits != NULL) + { + while (start_match < end_subject) + { + register int c = *start_match; + if ((start_bits[c/8] & (1 << (c&7))) == 0) start_match++; else break; + } + } + +#ifdef DEBUG /* Sigh. Some compilers never learn. */ + printf(">>>> Match against: "); + pchars(start_match, end_subject - start_match, TRUE, &match_block); + printf("\n"); +#endif + + /* If req_byte is set, we know that that character must appear in the subject + for the match to succeed. If the first character is set, req_byte must be + later in the subject; otherwise the test starts at the match point. This + optimization can save a huge amount of backtracking in patterns with nested + unlimited repeats that aren't going to match. Writing separate code for + cased/caseless versions makes it go faster, as does using an autoincrement + and backing off on a match. + + HOWEVER: when the subject string is very, very long, searching to its end can + take a long time, and give bad performance on quite ordinary patterns. This + showed up when somebody was matching /^C/ on a 32-megabyte string... so we + don't do this when the string is sufficiently long. */ + + if (req_byte >= 0 && end_subject - start_match < REQ_BYTE_MAX) + { + register const uschar *p = start_match + ((first_byte >= 0)? 1 : 0); + + /* We don't need to repeat the search if we haven't yet reached the + place we found it at last time. */ + + if (p > req_byte_ptr) + { + if (req_byte_caseless) + { + while (p < end_subject) + { + register int pp = *p++; + if (pp == req_byte || pp == req_byte2) { p--; break; } + } + } + else + { + while (p < end_subject) + { + if (*p++ == req_byte) { p--; break; } + } + } + + /* If we can't find the required character, break the matching loop */ + + if (p >= end_subject) break; + + /* If we have found the required character, save the point where we + found it, so that we don't search again next time round the loop if + the start hasn't passed this character yet. */ + + req_byte_ptr = p; + } + } + + /* When a match occurs, substrings will be set for all internal extractions; + we just need to set up the whole thing as substring 0 before returning. If + there were too many extractions, set the return code to zero. In the case + where we had to get some local store to hold offsets for backreferences, copy + those back references that we can. In this case there need not be overflow + if certain parts of the pattern were not used. */ + + match_block.start_match = start_match; + match_block.match_call_count = 0; + + rc = match(start_match, match_block.start_code, 2, &match_block, ims, NULL, + match_isgroup); + + if (rc == MATCH_NOMATCH) + { + start_match++; +#ifdef SUPPORT_UTF8 + if (match_block.utf8) + while((*start_match & 0xc0) == 0x80) start_match++; +#endif + continue; + } + + if (rc != MATCH_MATCH) + { + DPRINTF((">>>> error: returning %d\n", rc)); + return rc; + } + + /* We have a match! Copy the offset information from temporary store if + necessary */ + + if (using_temporary_offsets) + { + if (offsetcount >= 4) + { + memcpy(offsets + 2, match_block.offset_vector + 2, + (offsetcount - 2) * sizeof(int)); + DPRINTF(("Copied offsets from temporary memory\n")); + } + if (match_block.end_offset_top > offsetcount) + match_block.offset_overflow = TRUE; + + DPRINTF(("Freeing temporary memory\n")); + (pcre_free)(match_block.offset_vector); + } + + rc = match_block.offset_overflow? 0 : match_block.end_offset_top/2; + + if (offsetcount < 2) rc = 0; else + { + offsets[0] = start_match - match_block.start_subject; + offsets[1] = match_block.end_match_ptr - match_block.start_subject; + } + + DPRINTF((">>>> returning %d\n", rc)); + return rc; + } + +/* This "while" is the end of the "do" above */ + +while (!anchored && start_match <= end_subject); + +if (using_temporary_offsets) + { + DPRINTF(("Freeing temporary memory\n")); + (pcre_free)(match_block.offset_vector); + } + +DPRINTF((">>>> returning PCRE_ERROR_NOMATCH\n")); + +return PCRE_ERROR_NOMATCH; +} + +/* End of pcre.c */ diff --git a/lc-continuity/mk4/continuity/pcre/pcre.def b/lc-continuity/mk4/continuity/pcre/pcre.def new file mode 100644 index 0000000000000000000000000000000000000000..4f6c4bff40da31438f388da1268b4aa9854c7297 --- /dev/null +++ b/lc-continuity/mk4/continuity/pcre/pcre.def @@ -0,0 +1,22 @@ +EXPORTS + +pcre_malloc DATA +pcre_free DATA + +pcre_compile +pcre_copy_substring +pcre_exec +pcre_get_substring +pcre_get_substring_list +pcre_free_substring +pcre_free_substring_list +pcre_info +pcre_fullinfo +pcre_maketables +pcre_study +pcre_version + +regcomp +regexec +regerror +regfree diff --git a/lc-continuity/mk4/continuity/pcre/pcre.in b/lc-continuity/mk4/continuity/pcre/pcre.in new file mode 100644 index 0000000000000000000000000000000000000000..2aa44b90a743ea99636febd6ae193588b9e8797c --- /dev/null +++ b/lc-continuity/mk4/continuity/pcre/pcre.in @@ -0,0 +1,184 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* Copyright (c) 1997-2003 University of Cambridge */ + +#ifndef _PCRE_H +#define _PCRE_H + +/* The file pcre.h is build by "configure". Do not edit it; instead +make changes to pcre.in. */ + +#define PCRE_MAJOR @PCRE_MAJOR@ +#define PCRE_MINOR @PCRE_MINOR@ +#define PCRE_DATE @PCRE_DATE@ + +/* Win32 uses DLL by default */ + +#ifdef _WIN32 +# ifdef PCRE_DEFINITION +# ifdef DLL_EXPORT +# define PCRE_DATA_SCOPE __declspec(dllexport) +# endif +# else +# ifndef PCRE_STATIC +# define PCRE_DATA_SCOPE __declspec(dllimport) +# endif +# endif +#endif +#ifndef PCRE_DATA_SCOPE +# define PCRE_DATA_SCOPE extern +#endif + +/* Have to include stdlib.h in order to ensure that size_t is defined; +it is needed here for malloc. */ + +#include + +/* Allow for C++ users */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Options */ + +#define PCRE_CASELESS 0x0001 +#define PCRE_MULTILINE 0x0002 +#define PCRE_DOTALL 0x0004 +#define PCRE_EXTENDED 0x0008 +#define PCRE_ANCHORED 0x0010 +#define PCRE_DOLLAR_ENDONLY 0x0020 +#define PCRE_EXTRA 0x0040 +#define PCRE_NOTBOL 0x0080 +#define PCRE_NOTEOL 0x0100 +#define PCRE_UNGREEDY 0x0200 +#define PCRE_NOTEMPTY 0x0400 +#define PCRE_UTF8 0x0800 +#define PCRE_NO_AUTO_CAPTURE 0x1000 + +/* Exec-time and get/set-time error codes */ + +#define PCRE_ERROR_NOMATCH (-1) +#define PCRE_ERROR_NULL (-2) +#define PCRE_ERROR_BADOPTION (-3) +#define PCRE_ERROR_BADMAGIC (-4) +#define PCRE_ERROR_UNKNOWN_NODE (-5) +#define PCRE_ERROR_NOMEMORY (-6) +#define PCRE_ERROR_NOSUBSTRING (-7) +#define PCRE_ERROR_MATCHLIMIT (-8) +#define PCRE_ERROR_CALLOUT (-9) /* Never used by PCRE itself */ + +/* Request types for pcre_fullinfo() */ + +#define PCRE_INFO_OPTIONS 0 +#define PCRE_INFO_SIZE 1 +#define PCRE_INFO_CAPTURECOUNT 2 +#define PCRE_INFO_BACKREFMAX 3 +#define PCRE_INFO_FIRSTBYTE 4 +#define PCRE_INFO_FIRSTCHAR 4 /* For backwards compatibility */ +#define PCRE_INFO_FIRSTTABLE 5 +#define PCRE_INFO_LASTLITERAL 6 +#define PCRE_INFO_NAMEENTRYSIZE 7 +#define PCRE_INFO_NAMECOUNT 8 +#define PCRE_INFO_NAMETABLE 9 +#define PCRE_INFO_STUDYSIZE 10 + +/* Request types for pcre_config() */ + +#define PCRE_CONFIG_UTF8 0 +#define PCRE_CONFIG_NEWLINE 1 +#define PCRE_CONFIG_LINK_SIZE 2 +#define PCRE_CONFIG_POSIX_MALLOC_THRESHOLD 3 +#define PCRE_CONFIG_MATCH_LIMIT 4 + +/* Bit flags for the pcre_extra structure */ + +#define PCRE_EXTRA_STUDY_DATA 0x0001 +#define PCRE_EXTRA_MATCH_LIMIT 0x0002 +#define PCRE_EXTRA_CALLOUT_DATA 0x0004 + +/* Types */ + +struct real_pcre; /* declaration; the definition is private */ +typedef struct real_pcre pcre; + +/* The structure for passing additional data to pcre_exec(). This is defined in +such as way as to be extensible. */ + +typedef struct pcre_extra { + unsigned long int flags; /* Bits for which fields are set */ + void *study_data; /* Opaque data from pcre_study() */ + unsigned long int match_limit; /* Maximum number of calls to match() */ + void *callout_data; /* Data passed back in callouts */ +} pcre_extra; + +/* The structure for passing out data via the pcre_callout_function. We use a +structure so that new fields can be added on the end in future versions, +without changing the API of the function, thereby allowing old clients to work +without modification. */ + +typedef struct pcre_callout_block { + int version; /* Identifies version of block */ + /* ------------------------ Version 0 ------------------------------- */ + int callout_number; /* Number compiled into pattern */ + int *offset_vector; /* The offset vector */ + const char *subject; /* The subject being matched */ + int subject_length; /* The length of the subject */ + int start_match; /* Offset to start of this match attempt */ + int current_position; /* Where we currently are */ + int capture_top; /* Max current capture */ + int capture_last; /* Most recently closed capture */ + void *callout_data; /* Data passed in with the call */ + /* ------------------------------------------------------------------ */ +} pcre_callout_block; + +/* Indirection for store get and free functions. These can be set to +alternative malloc/free functions if required. There is also an optional +callout function that is triggered by the (?) regex item. Some magic is +required for Win32 DLL; it is null on other OS. For Virtual Pascal, these +have to be different again. */ + +#ifndef VPCOMPAT +PCRE_DATA_SCOPE void *(*pcre_malloc)(size_t); +PCRE_DATA_SCOPE void (*pcre_free)(void *); +PCRE_DATA_SCOPE int (*pcre_callout)(pcre_callout_block *); +#else /* VPCOMPAT */ +extern void *pcre_malloc(size_t); +extern void pcre_free(void *); +extern int pcre_callout(pcre_callout_block *); +#endif /* VPCOMPAT */ + +/* Exported PCRE functions */ + +extern pcre *pcre_compile(const char *, int, const char **, + int *, const unsigned char *); +extern int pcre_config(int, void *); +extern int pcre_copy_named_substring(const pcre *, const char *, + int *, int, const char *, char *, int); +extern int pcre_copy_substring(const char *, int *, int, int, + char *, int); +extern int pcre_exec(const pcre *, const pcre_extra *, + const char *, int, int, int, int *, int); +extern void pcre_free_substring(const char *); +extern void pcre_free_substring_list(const char **); +extern int pcre_fullinfo(const pcre *, const pcre_extra *, int, + void *); +extern int pcre_get_named_substring(const pcre *, const char *, + int *, int, const char *, const char **); +extern int pcre_get_stringnumber(const pcre *, const char *); +extern int pcre_get_substring(const char *, int *, int, int, + const char **); +extern int pcre_get_substring_list(const char *, int *, int, + const char ***); +extern int pcre_info(const pcre *, int *, int *); +extern const unsigned char *pcre_maketables(void); +extern pcre_extra *pcre_study(const pcre *, int, const char **); +extern const char *pcre_version(void); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* End of pcre.h */ diff --git a/lc-continuity/mk4/continuity/pcre/pcredemo.c b/lc-continuity/mk4/continuity/pcre/pcredemo.c new file mode 100644 index 0000000000000000000000000000000000000000..2cfa4923499b7dfca4930663646d6ba242672a8c --- /dev/null +++ b/lc-continuity/mk4/continuity/pcre/pcredemo.c @@ -0,0 +1,329 @@ +/************************************************* +* PCRE DEMONSTRATION PROGRAM * +*************************************************/ + +/* + * This is a demonstration program to illustrate the most straightforward + * ways of calling the PCRE regular expression library from a C program. See + * the pcresample documentation for a short discussion. + * + * Compile thuswise: gcc -Wall pcredemo.c -I/opt/local/include -L/opt/local/lib + * \ -R/opt/local/lib -lpcre + * + * Replace "/opt/local/include" and "/opt/local/lib" with wherever the include + * and library files for PCRE are installed on your system. Only some + * operating systems (e.g. Solaris) use the -R option. + */ + + +#include +#include +#include + +#define OVECCOUNT 30 /* should be a multiple of 3 */ + + +int main(int argc, char **argv) +{ + pcre *re; + const char *error; + char *pattern; + char *subject; + unsigned char *name_table; + int erroffset; + int find_all; + int namecount; + int name_entry_size; + int ovector[OVECCOUNT]; + int subject_length; + int rc, i; + + + /************************************************************************* + * First, sort out the command line. There is only one possible option at * + * the moment, "-g" to request repeated matching to find all occurrences, * + * like Perl's /g option. We set the variable find_all non-zero if it is * + * present. Apart from that, there must be exactly two arguments. * + *************************************************************************/ + + find_all = 0; + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-g") == 0) + find_all = 1; + else + break; + } + + /* + * After the options, we require exactly two arguments, which are the + * pattern, and the subject string. + */ + + if (argc - i != 2) { + printf("Two arguments required: a regex and a subject string\n"); + return 1; + } + pattern = argv[i]; + subject = argv[i + 1]; + subject_length = (int) strlen(subject); + + + /************************************************************************* + * Now we are going to compile the regular expression pattern, and handle * + * and errors that are detected. * + *************************************************************************/ + + re = pcre_compile( + pattern, /* the pattern */ + 0, /* default options */ + &error, /* for error message */ + &erroffset,/* for error offset */ + NULL); /* use default character tables */ + + /* Compilation failed: print the error message and exit */ + + if (re == NULL) { + printf("PCRE compilation failed at offset %d: %s\n", erroffset, error); + return 1; + } + /************************************************************************* + * If the compilation succeeded, we call PCRE again, in order to do a * + * pattern match against the subject string. This just does ONE match. If * + * further matching is needed, it will be done below. * + *************************************************************************/ + + rc = pcre_exec( + re, /* the compiled pattern */ + NULL, /* no extra data - we didn't study the + * pattern */ + subject, /* the subject string */ + subject_length, /* the length of the subject */ + 0, /* start at offset 0 in the subject */ + 0, /* default options */ + ovector, /* output vector for substring information */ + OVECCOUNT); /* number of elements in the output vector */ + + /* Matching failed: handle error cases */ + + if (rc < 0) { + switch (rc) { + case PCRE_ERROR_NOMATCH: + printf("No match\n"); + break; + /* + * Handle other special cases if you like + */ + default: + printf("Matching error %d\n", rc); + break; + } + return 1; + } + /* Match succeded */ + + printf("\nMatch succeeded at offset %d\n", ovector[0]); + + + /************************************************************************* + * We have found the first match within the subject string. If the output * + * vector wasn't big enough, set its size to the maximum. Then output any * + * substrings that were captured. * + *************************************************************************/ + + /* The output vector wasn't big enough */ + + if (rc == 0) { + rc = OVECCOUNT / 3; + printf("ovector only has room for %d captured substrings\n", rc - 1); + } + /* + * Show substrings stored in the output vector by number. Obviously, in a + * real application you might want to do things other than print them. + */ + + for (i = 0; i < rc; i++) { + char *substring_start = subject + ovector[2 * i]; + int substring_length = ovector[2 * i + 1] - ovector[2 * i]; + printf("%2d: %.*s\n", i, substring_length, substring_start); + } + + + /************************************************************************* + * That concludes the basic part of this demonstration program. We have * + * compiled a pattern, and performed a single match. The code that follows* + * first shows how to access named substrings, and then how to code for * + * repeated matches on the same subject. * + *************************************************************************/ + + /* + * See if there are any named substrings, and if so, show them by name. + * First we have to extract the count of named parentheses from the + * pattern. + */ + + (void) pcre_fullinfo( + re, /* the compiled pattern */ + NULL, /* no extra data - we didn't study the + * pattern */ + PCRE_INFO_NAMECOUNT, /* number of named substrings */ + &namecount); /* where to put the answer */ + + if (namecount <= 0) + printf("No named substrings\n"); + else { + unsigned char *tabptr; + printf("Named substrings\n"); + + /* + * Before we can access the substrings, we must extract the table for + * translating names to numbers, and the size of each entry in the + * table. + */ + + (void) pcre_fullinfo( + re, /* the compiled pattern */ + NULL,/* no extra data - we didn't study the + * pattern */ + PCRE_INFO_NAMETABLE, /* address of the table */ + &name_table); /* where to put the answer */ + + (void) pcre_fullinfo( + re, /* the compiled pattern */ + NULL,/* no extra data - we didn't study the + * pattern */ + PCRE_INFO_NAMEENTRYSIZE, /* size of each entry in + * the table */ + &name_entry_size); /* where to put the answer */ + + /* + * Now we can scan the table and, for each entry, print the number, the + * name, and the substring itself. + */ + + tabptr = name_table; + for (i = 0; i < namecount; i++) { + int n = (tabptr[0] << 8) | tabptr[1]; + printf("(%d) %*s: %.*s\n", n, name_entry_size - 3, tabptr + 2, + ovector[2 * n + 1] - ovector[2 * n], subject + ovector[2 * n]); + tabptr += name_entry_size; + } + } + + + /************************************************************************* + * If the "-g" option was given on the command line, we want to continue * + * to search for additional matches in the subject string, in a similar * + * way to the /g option in Perl. This turns out to be trickier than you * + * might think because of the possibility of matching an empty string. * + * What happens is as follows: * + * * + * If the previous match was NOT for an empty string, we can just start * + * the next match at the end of the previous one. * + * * + * If the previous match WAS for an empty string, we can't do that, as it * + * would lead to an infinite loop. Instead, a special call of pcre_exec() * + * is made with the PCRE_NOTEMPTY and PCRE_ANCHORED flags set. The first * + * of these tells PCRE that an empty string is not a valid match; other * + * possibilities must be tried. The second flag restricts PCRE to one * + * match attempt at the initial string position. If this match succeeds, * + * an alternative to the empty string match has been found, and we can * + * proceed round the loop. * + *************************************************************************/ + + if (!find_all) + return 0; /* Finish unless -g was given */ + + /* Loop for second and subsequent matches */ + + for (;;) { + int options = 0; /* Normally no options */ + int start_offset = ovector[1]; /* Start at end of previous match */ + + /* + * If the previous match was for an empty string, we are finished if we + * are at the end of the subject. Otherwise, arrange to run another + * match at the same point to see if a non-empty match can be found. + */ + + if (ovector[0] == ovector[1]) { + if (ovector[0] == subject_length) + break; + options = PCRE_NOTEMPTY | PCRE_ANCHORED; + } + /* Run the next matching operation */ + + rc = pcre_exec( + re, /* the compiled pattern */ + NULL, /* no extra data - we didn't study the + * pattern */ + subject, /* the subject string */ + subject_length, /* the length of the subject */ + start_offset, /* starting offset in the subject */ + options, /* options */ + ovector, /* output vector for substring information */ + OVECCOUNT);/* number of elements in the output vector */ + + /* + * This time, a result of NOMATCH isn't an error. If the value in + * "options" is zero, it just means we have found all possible matches, + * so the loop ends. Otherwise, it means we have failed to find a + * non-empty-string match at a point where there was a previous + * empty-string match. In this case, we do what Perl does: advance the + * matching position by one, and continue. We do this by setting the + * "end of previous match" offset, because that is picked up at the top + * of the loop as the point at which to start again. + */ + + if (rc == PCRE_ERROR_NOMATCH) { + if (options == 0) + break; + ovector[1] = start_offset + 1; + continue; /* Go round the loop again */ + } + /* Other matching errors are not recoverable. */ + + if (rc < 0) { + printf("Matching error %d\n", rc); + return 1; + } + /* Match succeded */ + + printf("\nMatch succeeded again at offset %d\n", ovector[0]); + + /* The match succeeded, but the output vector wasn't big enough. */ + + if (rc == 0) { + rc = OVECCOUNT / 3; + printf("ovector only has room for %d captured substrings\n", rc - 1); + } + /* + * As before, show substrings stored in the output vector by number, + * and then also any named substrings. + */ + + for (i = 0; i < rc; i++) { + char *substring_start = subject + ovector[2 * i]; + int substring_length = ovector[2 * i + 1] - ovector[2 * i]; + printf("%2d: %.*s\n", i, substring_length, substring_start); + } + + if (namecount <= 0) + printf("No named substrings\n"); + else { + unsigned char *tabptr = name_table; + printf("Named substrings\n"); + for (i = 0; i < namecount; i++) { + int n = (tabptr[0] << 8) | tabptr[1]; + printf("(%d) %*s: %.*s\n", n, name_entry_size - 3, tabptr + 2, + ovector[2 * n + 1] - ovector[2 * n], subject + ovector[2 * n]); + tabptr += name_entry_size; + } + } + } /* End of loop to find second and subsequent + * matches */ + + printf("\n"); + return 0; +} + +/* End of pcredemo.c */ diff --git a/lc-continuity/mk4/continuity/pcre/pcregrep.c b/lc-continuity/mk4/continuity/pcre/pcregrep.c new file mode 100644 index 0000000000000000000000000000000000000000..f4a59f4f41c2325430ce2829fce8fc0466f58c80 --- /dev/null +++ b/lc-continuity/mk4/continuity/pcre/pcregrep.c @@ -0,0 +1,642 @@ +/************************************************* +* pcregrep program * +*************************************************/ + +/* This is a grep program that uses the PCRE regular expression library to do +its pattern matching. On a Unix or Win32 system it can recurse into +directories. */ + +#include +#include +#include +#include +#include +#include "config.h" +#include "pcre.h" + +#define FALSE 0 +#define TRUE 1 + +typedef int BOOL; + +#define VERSION "3.0 14-Jan-2003" +#define MAX_PATTERN_COUNT 100 + + +/************************************************* +* Global variables * +*************************************************/ + +static char *pattern_filename = NULL; +static int pattern_count = 0; +static pcre **pattern_list; +static pcre_extra **hints_list; + +static BOOL count_only = FALSE; +static BOOL filenames = TRUE; +static BOOL filenames_only = FALSE; +static BOOL invert = FALSE; +static BOOL number = FALSE; +static BOOL recurse = FALSE; +static BOOL silent = FALSE; +static BOOL whole_lines = FALSE; + +/* Structure for options and list of them */ + +typedef struct option_item { + int one_char; + const char *long_name; + const char *help_text; +} option_item; + +static option_item optionlist[] = { + { -1, "help", "display this help and exit" }, + { 'c', "count", "print only a count of matching lines per FILE" }, + { 'h', "no-filename", "suppress the prefixing filename on output" }, + { 'i', "ignore-case", "ignore case distinctions" }, + { 'l', "files-with-matches", "print only FILE names containing matches" }, + { 'n', "line-number", "print line number with output lines" }, + { 'r', "recursive", "recursively scan sub-directories" }, + { 's', "no-messages", "suppress error messages" }, + { 'u', "utf-8", "use UTF-8 mode" }, + { 'V', "version", "print version information and exit" }, + { 'v', "invert-match", "select non-matching lines" }, + { 'x', "line-regex", "force PATTERN to match only whole lines" }, + { 'x', "line-regexp", "force PATTERN to match only whole lines" }, + { 0, NULL, NULL } +}; + + +/************************************************* +* Functions for directory scanning * +*************************************************/ + +/* These functions are defined so that they can be made system specific, +although at present the only ones are for Unix, Win32, and for "no directory +recursion support". */ + + +/************* Directory scanning in Unix ***********/ + +#if IS_UNIX +#include +#include +#include + +typedef DIR directory_type; + +static int +isdirectory(char *filename) +{ +struct stat statbuf; +if (stat(filename, &statbuf) < 0) + return 0; /* In the expectation that opening as a file will fail */ +return ((statbuf.st_mode & S_IFMT) == S_IFDIR)? '/' : 0; +} + +static directory_type * +opendirectory(char *filename) +{ +return opendir(filename); +} + +static char * +readdirectory(directory_type *dir) +{ +for (;;) + { + struct dirent *dent = readdir(dir); + if (dent == NULL) return NULL; + if (strcmp(dent->d_name, ".") != 0 && strcmp(dent->d_name, "..") != 0) + return dent->d_name; + } +return NULL; /* Keep compiler happy; never executed */ +} + +static void +closedirectory(directory_type *dir) +{ +closedir(dir); +} + + +/************* Directory scanning in Win32 ***********/ + +/* I (Philip Hazel) have no means of testing this code. It was contributed by +Lionel Fourquaux. */ + + +#elif HAVE_WIN32API + +#ifndef STRICT +# define STRICT +#endif +#ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +#endif +#include + +typedef struct directory_type +{ +HANDLE handle; +BOOL first; +WIN32_FIND_DATA data; +} directory_type; + +int +isdirectory(char *filename) +{ +DWORD attr = GetFileAttributes(filename); +if (attr == INVALID_FILE_ATTRIBUTES) + return 0; +return ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) ? '/' : 0; +} + +directory_type * +opendirectory(char *filename) +{ +size_t len; +char *pattern; +directory_type *dir; +DWORD err; +len = strlen(filename); +pattern = (char *) malloc(len + 3); +dir = (directory_type *) malloc(sizeof(*dir)); +if ((pattern == NULL) || (dir == NULL)) + { + fprintf(stderr, "pcregrep: malloc failed\n"); + exit(2); + } +memcpy(pattern, filename, len); +memcpy(&(pattern[len]), "\\*", 3); +dir->handle = FindFirstFile(pattern, &(dir->data)); +if (dir->handle != INVALID_HANDLE_VALUE) + { + free(pattern); + dir->first = TRUE; + return dir; + } +err = GetLastError(); +free(pattern); +free(dir); +errno = (err == ERROR_ACCESS_DENIED) ? EACCES : ENOENT; +return NULL; +} + +char * +readdirectory(directory_type *dir) +{ +for (;;) + { + if (!dir->first) + { + if (!FindNextFile(dir->handle, &(dir->data))) + return NULL; + } + else + { + dir->first = FALSE; + } + if (strcmp(dir->data.cFileName, ".") != 0 && strcmp(dir->data.cFileName, "..") != 0) + return dir->data.cFileName; + } +#ifndef _MSC_VER +return NULL; /* Keep compiler happy; never executed */ +#endif +} + +void +closedirectory(directory_type *dir) +{ +FindClose(dir->handle); +free(dir); +} + + +/************* Directory scanning when we can't do it ***********/ + +/* The type is void, and apart from isdirectory(), the functions do nothing. */ + +#else + +typedef void directory_type; + +int isdirectory(char *filename) { return FALSE; } +directory_type * opendirectory(char *filename) {} +char *readdirectory(directory_type *dir) {} +void closedirectory(directory_type *dir) {} + +#endif + + + +#if ! HAVE_STRERROR +/************************************************* +* Provide strerror() for non-ANSI libraries * +*************************************************/ + +/* Some old-fashioned systems still around (e.g. SunOS4) don't have strerror() +in their libraries, but can provide the same facility by this simple +alternative function. */ + +extern int sys_nerr; +extern char *sys_errlist[]; + +char * +strerror(int n) +{ +if (n < 0 || n >= sys_nerr) return "unknown error number"; +return sys_errlist[n]; +} +#endif /* HAVE_STRERROR */ + + + +/************************************************* +* Grep an individual file * +*************************************************/ + +static int +pcregrep(FILE *in, char *name) +{ +int rc = 1; +int linenumber = 0; +int count = 0; +int offsets[99]; +char buffer[BUFSIZ]; + +while (fgets(buffer, sizeof(buffer), in) != NULL) + { + BOOL match = FALSE; + int i; + int length = (int)strlen(buffer); + if (length > 0 && buffer[length-1] == '\n') buffer[--length] = 0; + linenumber++; + + for (i = 0; !match && i < pattern_count; i++) + { + match = pcre_exec(pattern_list[i], hints_list[i], buffer, length, 0, 0, + offsets, 99) >= 0; + if (match && whole_lines && offsets[1] != length) match = FALSE; + } + + if (match != invert) + { + if (count_only) count++; + + else if (filenames_only) + { + fprintf(stdout, "%s\n", (name == NULL)? "" : name); + return 0; + } + + else if (silent) return 0; + + else + { + if (name != NULL) fprintf(stdout, "%s:", name); + if (number) fprintf(stdout, "%d:", linenumber); + fprintf(stdout, "%s\n", buffer); + } + + rc = 0; + } + } + +if (count_only) + { + if (name != NULL) fprintf(stdout, "%s:", name); + fprintf(stdout, "%d\n", count); + } + +return rc; +} + + + + +/************************************************* +* Grep a file or recurse into a directory * +*************************************************/ + +static int +grep_or_recurse(char *filename, BOOL dir_recurse, BOOL show_filenames, + BOOL only_one_at_top) +{ +int rc = 1; +int sep; +FILE *in; + +/* If the file is a directory and we are recursing, scan each file within it. +The scanning code is localized so it can be made system-specific. */ + +if ((sep = isdirectory(filename)) != 0 && dir_recurse) + { + char buffer[1024]; + char *nextfile; + directory_type *dir = opendirectory(filename); + + if (dir == NULL) + { + fprintf(stderr, "pcregrep: Failed to open directory %s: %s\n", filename, + strerror(errno)); + return 2; + } + + while ((nextfile = readdirectory(dir)) != NULL) + { + int frc; + sprintf(buffer, "%.512s%c%.128s", filename, sep, nextfile); + frc = grep_or_recurse(buffer, dir_recurse, TRUE, FALSE); + if (frc == 0 && rc == 1) rc = 0; + } + + closedirectory(dir); + return rc; + } + +/* If the file is not a directory, or we are not recursing, scan it. If this is +the first and only argument at top level, we don't show the file name (unless +we are only showing the file name). Otherwise, control is via the +show_filenames variable. */ + +in = fopen(filename, "r"); +if (in == NULL) + { + fprintf(stderr, "pcregrep: Failed to open %s: %s\n", filename, strerror(errno)); + return 2; + } + +rc = pcregrep(in, (filenames_only || (show_filenames && !only_one_at_top))? + filename : NULL); +fclose(in); +return rc; +} + + + + +/************************************************* +* Usage function * +*************************************************/ + +static int +usage(int rc) +{ +fprintf(stderr, "Usage: pcregrep [-Vcfhilnrsvx] [long-options] [pattern] [file1 file2 ...]\n"); +fprintf(stderr, "Type `pcregrep --help' for more information.\n"); +return rc; +} + + + + +/************************************************* +* Help function * +*************************************************/ + +static void +help(void) +{ +option_item *op; + +printf("Usage: pcregrep [OPTION]... [PATTERN] [FILE1 FILE2 ...]\n"); +printf("Search for PATTERN in each FILE or standard input.\n"); +printf("PATTERN must be present if -f is not used.\n"); +printf("Example: pcregrep -i 'hello.*world' menu.h main.c\n\n"); + +printf("Options:\n"); + +for (op = optionlist; op->one_char != 0; op++) + { + int n; + char s[4]; + if (op->one_char > 0) sprintf(s, "-%c,", op->one_char); else strcpy(s, " "); + printf(" %s --%s%n", s, op->long_name, &n); + n = 30 - n; + if (n < 1) n = 1; + printf("%.*s%s\n", n, " ", op->help_text); + } + +printf("\n -f or --file=\n"); +printf(" Read patterns from instead of using a command line option.\n"); +printf(" Trailing white space is removed; blanks lines are ignored.\n"); +printf(" There is a maximum of %d patterns.\n", MAX_PATTERN_COUNT); + +printf("\nWith no FILE, read standard input. If fewer than two FILEs given, assume -h.\n"); +printf("Exit status is 0 if any matches, 1 if no matches, and 2 if trouble.\n"); +} + + + + +/************************************************* +* Handle an option * +*************************************************/ + +static int +handle_option(int letter, int options) +{ +switch(letter) + { + case -1: help(); exit(0); + case 'c': count_only = TRUE; break; + case 'h': filenames = FALSE; break; + case 'i': options |= PCRE_CASELESS; break; + case 'l': filenames_only = TRUE; + case 'n': number = TRUE; break; + case 'r': recurse = TRUE; break; + case 's': silent = TRUE; break; + case 'u': options |= PCRE_UTF8; break; + case 'v': invert = TRUE; break; + case 'x': whole_lines = TRUE; options |= PCRE_ANCHORED; break; + + case 'V': + fprintf(stderr, "pcregrep version %s using ", VERSION); + fprintf(stderr, "PCRE version %s\n", pcre_version()); + exit(0); + break; + + default: + fprintf(stderr, "pcregrep: Unknown option -%c\n", letter); + exit(usage(2)); + } + +return options; +} + + + + +/************************************************* +* Main program * +*************************************************/ + +int +main(int argc, char **argv) +{ +int i, j; +int rc = 1; +int options = 0; +int errptr; +const char *error; +BOOL only_one_at_top; + +/* Process the options */ + +for (i = 1; i < argc; i++) + { + if (argv[i][0] != '-') break; + + /* Missing options */ + + if (argv[i][1] == 0) exit(usage(2)); + + /* Long name options */ + + if (argv[i][1] == '-') + { + option_item *op; + + if (strncmp(argv[i]+2, "file=", 5) == 0) + { + pattern_filename = argv[i] + 7; + continue; + } + + for (op = optionlist; op->one_char != 0; op++) + { + if (strcmp(argv[i]+2, op->long_name) == 0) + { + options = handle_option(op->one_char, options); + break; + } + } + if (op->one_char == 0) + { + fprintf(stderr, "pcregrep: Unknown option %s\n", argv[i]); + exit(usage(2)); + } + } + + /* One-char options */ + + else + { + char *s = argv[i] + 1; + while (*s != 0) + { + if (*s == 'f') + { + pattern_filename = s + 1; + if (pattern_filename[0] == 0) + { + if (i >= argc - 1) + { + fprintf(stderr, "pcregrep: File name missing after -f\n"); + exit(usage(2)); + } + pattern_filename = argv[++i]; + } + break; + } + else options = handle_option(*s++, options); + } + } + } + +pattern_list = malloc(MAX_PATTERN_COUNT * sizeof(pcre *)); +hints_list = malloc(MAX_PATTERN_COUNT * sizeof(pcre_extra *)); + +if (pattern_list == NULL || hints_list == NULL) + { + fprintf(stderr, "pcregrep: malloc failed\n"); + return 2; + } + +/* Compile the regular expression(s). */ + +if (pattern_filename != NULL) + { + FILE *f = fopen(pattern_filename, "r"); + char buffer[BUFSIZ]; + if (f == NULL) + { + fprintf(stderr, "pcregrep: Failed to open %s: %s\n", pattern_filename, + strerror(errno)); + return 2; + } + while (fgets(buffer, sizeof(buffer), f) != NULL) + { + char *s = buffer + (int)strlen(buffer); + if (pattern_count >= MAX_PATTERN_COUNT) + { + fprintf(stderr, "pcregrep: Too many patterns in file (max %d)\n", + MAX_PATTERN_COUNT); + return 2; + } + while (s > buffer && isspace((unsigned char)(s[-1]))) s--; + if (s == buffer) continue; + *s = 0; + pattern_list[pattern_count] = pcre_compile(buffer, options, &error, + &errptr, NULL); + if (pattern_list[pattern_count++] == NULL) + { + fprintf(stderr, "pcregrep: Error in regex number %d at offset %d: %s\n", + pattern_count, errptr, error); + return 2; + } + } + fclose(f); + } + +/* If no file name, a single regex must be given inline */ + +else + { + if (i >= argc) return usage(2); + pattern_list[0] = pcre_compile(argv[i++], options, &error, &errptr, NULL); + if (pattern_list[0] == NULL) + { + fprintf(stderr, "pcregrep: Error in regex at offset %d: %s\n", errptr, + error); + return 2; + } + pattern_count++; + } + +/* Study the regular expressions, as we will be running them may times */ + +for (j = 0; j < pattern_count; j++) + { + hints_list[j] = pcre_study(pattern_list[j], 0, &error); + if (error != NULL) + { + char s[16]; + if (pattern_count == 1) s[0] = 0; else sprintf(s, " number %d", j); + fprintf(stderr, "pcregrep: Error while studying regex%s: %s\n", s, error); + return 2; + } + } + +/* If there are no further arguments, do the business on stdin and exit */ + +if (i >= argc) return pcregrep(stdin, NULL); + +/* Otherwise, work through the remaining arguments as files or directories. +Pass in the fact that there is only one argument at top level - this suppresses +the file name if the argument is not a directory. */ + +only_one_at_top = (i == argc - 1); +if (filenames_only) filenames = TRUE; + +for (; i < argc; i++) + { + int frc = grep_or_recurse(argv[i], recurse, filenames, only_one_at_top); + if (frc == 0 && rc == 1) rc = 0; + } + +return rc; +} + +/* End */ diff --git a/lc-continuity/mk4/continuity/pcre/pcreposix.c b/lc-continuity/mk4/continuity/pcre/pcreposix.c new file mode 100644 index 0000000000000000000000000000000000000000..49094f280d9f671a1ed0fe4264ba1013e12aed93 --- /dev/null +++ b/lc-continuity/mk4/continuity/pcre/pcreposix.c @@ -0,0 +1,301 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* +This is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. See +the file Tech.Notes for some information on the internals. + +This module is a wrapper that provides a POSIX API to the underlying PCRE +functions. + +Written by: Philip Hazel + + Copyright (c) 1997-2003 University of Cambridge + +----------------------------------------------------------------------------- +Permission is granted to anyone to use this software for any purpose on any +computer system, and to redistribute it freely, subject to the following +restrictions: + +1. This software 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. + +2. The origin of this software must not be misrepresented, either by + explicit claim or by omission. + +3. Altered versions must be plainly marked as such, and must not be + misrepresented as being the original software. + +4. If PCRE is embedded in any software that is released under the GNU + General Purpose Licence (GPL), then the terms of that licence shall + supersede any condition above with which it is incompatible. +----------------------------------------------------------------------------- +*/ + +#include "internal.h" +#include "pcreposix.h" +#include "stdlib.h" + + + +/* Corresponding tables of PCRE error messages and POSIX error codes. */ + +static const char *estring[] = { + ERR1, ERR2, ERR3, ERR4, ERR5, ERR6, ERR7, ERR8, ERR9, ERR10, + ERR11, ERR12, ERR13, ERR14, ERR15, ERR16, ERR17, ERR18, ERR19, ERR20, + ERR21, ERR22, ERR23, ERR24, ERR25, ERR26, ERR27, ERR29, ERR29, ERR30, + ERR31, ERR32, ERR33, ERR34, ERR35, ERR36, ERR37, ERR38, ERR39, ERR40, + ERR41, ERR42, ERR43 }; + +static int eint[] = { + REG_EESCAPE, /* "\\ at end of pattern" */ + REG_EESCAPE, /* "\\c at end of pattern" */ + REG_EESCAPE, /* "unrecognized character follows \\" */ + REG_BADBR, /* "numbers out of order in {} quantifier" */ + REG_BADBR, /* "number too big in {} quantifier" */ + REG_EBRACK, /* "missing terminating ] for character class" */ + REG_ECTYPE, /* "invalid escape sequence in character class" */ + REG_ERANGE, /* "range out of order in character class" */ + REG_BADRPT, /* "nothing to repeat" */ + REG_BADRPT, /* "operand of unlimited repeat could match the empty string" */ + REG_ASSERT, /* "internal error: unexpected repeat" */ + REG_BADPAT, /* "unrecognized character after (?" */ + REG_BADPAT, /* "POSIX named classes are supported only within a class" */ + REG_EPAREN, /* "missing )" */ + REG_ESUBREG, /* "reference to non-existent subpattern" */ + REG_INVARG, /* "erroffset passed as NULL" */ + REG_INVARG, /* "unknown option bit(s) set" */ + REG_EPAREN, /* "missing ) after comment" */ + REG_ESIZE, /* "parentheses nested too deeply" */ + REG_ESIZE, /* "regular expression too large" */ + REG_ESPACE, /* "failed to get memory" */ + REG_EPAREN, /* "unmatched brackets" */ + REG_ASSERT, /* "internal error: code overflow" */ + REG_BADPAT, /* "unrecognized character after (?<" */ + REG_BADPAT, /* "lookbehind assertion is not fixed length" */ + REG_BADPAT, /* "malformed number after (?(" */ + REG_BADPAT, /* "conditional group containe more than two branches" */ + REG_BADPAT, /* "assertion expected after (?(" */ + REG_BADPAT, /* "(?R or (?digits must be followed by )" */ + REG_ECTYPE, /* "unknown POSIX class name" */ + REG_BADPAT, /* "POSIX collating elements are not supported" */ + REG_INVARG, /* "this version of PCRE is not compiled with PCRE_UTF8 support" */ + REG_BADPAT, /* "spare error" */ + REG_BADPAT, /* "character value in \x{...} sequence is too large" */ + REG_BADPAT, /* "invalid condition (?(0)" */ + REG_BADPAT, /* "\\C not allowed in lookbehind assertion" */ + REG_EESCAPE, /* "PCRE does not support \\L, \\l, \\N, \\P, \\p, \\U, \\u, or \\X" */ + REG_BADPAT, /* "number after (?C is > 255" */ + REG_BADPAT, /* "closing ) for (?C expected" */ + REG_BADPAT, /* "recursive call could loop indefinitely" */ + REG_BADPAT, /* "unrecognized character after (?P" */ + REG_BADPAT, /* "syntax error after (?P" */ + REG_BADPAT /* "two named groups have the same name" */ +}; + +/* Table of texts corresponding to POSIX error codes */ + +static const char *pstring[] = { + "", /* Dummy for value 0 */ + "internal error", /* REG_ASSERT */ + "invalid repeat counts in {}", /* BADBR */ + "pattern error", /* BADPAT */ + "? * + invalid", /* BADRPT */ + "unbalanced {}", /* EBRACE */ + "unbalanced []", /* EBRACK */ + "collation error - not relevant", /* ECOLLATE */ + "bad class", /* ECTYPE */ + "bad escape sequence", /* EESCAPE */ + "empty expression", /* EMPTY */ + "unbalanced ()", /* EPAREN */ + "bad range inside []", /* ERANGE */ + "expression too big", /* ESIZE */ + "failed to get memory", /* ESPACE */ + "bad back reference", /* ESUBREG */ + "bad argument", /* INVARG */ + "match failed" /* NOMATCH */ +}; + + + + +/************************************************* +* Translate PCRE text code to int * +*************************************************/ + +/* PCRE compile-time errors are given as strings defined as macros. We can just +look them up in a table to turn them into POSIX-style error codes. */ + +static int +pcre_posix_error_code(const char *s) +{ +size_t i; +for (i = 0; i < sizeof(estring)/sizeof(char *); i++) + if (strcmp(s, estring[i]) == 0) return eint[i]; +return REG_ASSERT; +} + + + +/************************************************* +* Translate error code to string * +*************************************************/ + +size_t +regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size) +{ +const char *message, *addmessage; +size_t length, addlength; + +message = (errcode >= (int)(sizeof(pstring)/sizeof(char *)))? + "unknown error code" : pstring[errcode]; +length = strlen(message) + 1; + +addmessage = " at offset "; +addlength = (preg != NULL && (int)preg->re_erroffset != -1)? + strlen(addmessage) + 6 : 0; + +if (errbuf_size > 0) + { + if (addlength > 0 && errbuf_size >= length + addlength) + sprintf(errbuf, "%s%s%-6d", message, addmessage, (int)preg->re_erroffset); + else + { + strncpy(errbuf, message, errbuf_size - 1); + errbuf[errbuf_size-1] = 0; + } + } + +return length + addlength; +} + + + + +/************************************************* +* Free store held by a regex * +*************************************************/ + +void +regfree(regex_t *preg) +{ +(pcre_free)(preg->re_pcre); +} + + + + +/************************************************* +* Compile a regular expression * +*************************************************/ + +/* +Arguments: + preg points to a structure for recording the compiled expression + pattern the pattern to compile + cflags compilation flags + +Returns: 0 on success + various non-zero codes on failure +*/ + +int +regcomp(regex_t *preg, const char *pattern, int cflags) +{ +const char *errorptr; +int erroffset; +int options = 0; + +if ((cflags & REG_ICASE) != 0) options |= PCRE_CASELESS; +if ((cflags & REG_NEWLINE) != 0) options |= PCRE_MULTILINE; + +preg->re_pcre = pcre_compile(pattern, options, &errorptr, &erroffset, NULL); +preg->re_erroffset = erroffset; + +if (preg->re_pcre == NULL) return pcre_posix_error_code(errorptr); + +preg->re_nsub = pcre_info(preg->re_pcre, NULL, NULL); +return 0; +} + + + + +/************************************************* +* Match a regular expression * +*************************************************/ + +/* Unfortunately, PCRE requires 3 ints of working space for each captured +substring, so we have to get and release working store instead of just using +the POSIX structures as was done in earlier releases when PCRE needed only 2 +ints. However, if the number of possible capturing brackets is small, use a +block of store on the stack, to reduce the use of malloc/free. The threshold is +in a macro that can be changed at configure time. */ + +int +regexec(const regex_t *preg, const char *string, size_t nmatch, + regmatch_t pmatch[], int eflags) +{ +int rc; +int options = 0; +int *ovector = NULL; +int small_ovector[POSIX_MALLOC_THRESHOLD * 3]; +BOOL allocated_ovector = FALSE; + +if ((eflags & REG_NOTBOL) != 0) options |= PCRE_NOTBOL; +if ((eflags & REG_NOTEOL) != 0) options |= PCRE_NOTEOL; + +((regex_t *)preg)->re_erroffset = (size_t)(-1); /* Only has meaning after compile */ + +if (nmatch > 0) + { + if (nmatch <= POSIX_MALLOC_THRESHOLD) + { + ovector = &(small_ovector[0]); + } + else + { + ovector = (int *)malloc(sizeof(int) * nmatch * 3); + if (ovector == NULL) return REG_ESPACE; + allocated_ovector = TRUE; + } + } + +rc = pcre_exec(preg->re_pcre, NULL, string, (int)strlen(string), 0, options, + ovector, nmatch * 3); + +if (rc == 0) rc = nmatch; /* All captured slots were filled in */ + +if (rc >= 0) + { + size_t i; + for (i = 0; i < (size_t)rc; i++) + { + pmatch[i].rm_so = ovector[i*2]; + pmatch[i].rm_eo = ovector[i*2+1]; + } + if (allocated_ovector) free(ovector); + for (; i < nmatch; i++) pmatch[i].rm_so = pmatch[i].rm_eo = -1; + return 0; + } + +else + { + if (allocated_ovector) free(ovector); + switch(rc) + { + case PCRE_ERROR_NOMATCH: return REG_NOMATCH; + case PCRE_ERROR_NULL: return REG_INVARG; + case PCRE_ERROR_BADOPTION: return REG_INVARG; + case PCRE_ERROR_BADMAGIC: return REG_INVARG; + case PCRE_ERROR_UNKNOWN_NODE: return REG_ASSERT; + case PCRE_ERROR_NOMEMORY: return REG_ESPACE; + default: return REG_ASSERT; + } + } +} + +/* End of pcreposix.c */ diff --git a/lc-continuity/mk4/continuity/pcre/pcreposix.h b/lc-continuity/mk4/continuity/pcre/pcreposix.h new file mode 100644 index 0000000000000000000000000000000000000000..2b97bf44f50496b24c5fc6784106eef29d0020cd --- /dev/null +++ b/lc-continuity/mk4/continuity/pcre/pcreposix.h @@ -0,0 +1,88 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* Copyright (c) 1997-2003 University of Cambridge */ + +#ifndef _PCREPOSIX_H +#define _PCREPOSIX_H + +/* This is the header for the POSIX wrapper interface to the PCRE Perl- +Compatible Regular Expression library. It defines the things POSIX says should +be there. I hope. */ + +/* Have to include stdlib.h in order to ensure that size_t is defined. */ + +#include + +/* Allow for C++ users */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Options defined by POSIX. */ + +#define REG_ICASE 0x01 +#define REG_NEWLINE 0x02 +#define REG_NOTBOL 0x04 +#define REG_NOTEOL 0x08 + +/* These are not used by PCRE, but by defining them we make it easier +to slot PCRE into existing programs that make POSIX calls. */ + +#define REG_EXTENDED 0 +#define REG_NOSUB 0 + +/* Error values. Not all these are relevant or used by the wrapper. */ + +enum { + REG_ASSERT = 1, /* internal error ? */ + REG_BADBR, /* invalid repeat counts in {} */ + REG_BADPAT, /* pattern error */ + REG_BADRPT, /* ? * + invalid */ + REG_EBRACE, /* unbalanced {} */ + REG_EBRACK, /* unbalanced [] */ + REG_ECOLLATE, /* collation error - not relevant */ + REG_ECTYPE, /* bad class */ + REG_EESCAPE, /* bad escape sequence */ + REG_EMPTY, /* empty expression */ + REG_EPAREN, /* unbalanced () */ + REG_ERANGE, /* bad range inside [] */ + REG_ESIZE, /* expression too big */ + REG_ESPACE, /* failed to get memory */ + REG_ESUBREG, /* bad back reference */ + REG_INVARG, /* bad argument */ + REG_NOMATCH /* match failed */ +}; + + +/* The structure representing a compiled regular expression. */ + +typedef struct { + void *re_pcre; + size_t re_nsub; + size_t re_erroffset; +} regex_t; + +/* The structure in which a captured offset is returned. */ + +typedef int regoff_t; + +typedef struct { + regoff_t rm_so; + regoff_t rm_eo; +} regmatch_t; + +/* The functions */ + +extern int regcomp(regex_t *, const char *, int); +extern int regexec(const regex_t *, const char *, size_t, regmatch_t *, int); +extern size_t regerror(int, const regex_t *, char *, size_t); +extern void regfree(regex_t *); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* End of pcreposix.h */ diff --git a/lc-continuity/mk4/continuity/pcre/pcretest.c b/lc-continuity/mk4/continuity/pcre/pcretest.c new file mode 100644 index 0000000000000000000000000000000000000000..ad729b7cfc948f6e4b7ac8041c807b769bb083f3 --- /dev/null +++ b/lc-continuity/mk4/continuity/pcre/pcretest.c @@ -0,0 +1,1421 @@ +/************************************************* +* PCRE testing program * +*************************************************/ + +/* This program was hacked up as a tester for PCRE. I really should have +written it more tidily in the first place. Will I ever learn? It has grown and +been extended and consequently is now rather untidy in places. */ + +#include +#include +#include +#include +#include +#include + +/* We need the internal info for displaying the results of pcre_study(). Also +for getting the opcodes for showing compiled code. */ + +#define PCRE_SPY /* For Win32 build, import data, not export */ +#include "internal.h" + +/* It is possible to compile this test program without including support for +testing the POSIX interface, though this is not available via the standard +Makefile. */ + +#if !defined NOPOSIX +#include "pcreposix.h" +#endif + +#ifndef CLOCKS_PER_SEC +#ifdef CLK_TCK +#define CLOCKS_PER_SEC CLK_TCK +#else +#define CLOCKS_PER_SEC 100 +#endif +#endif + +#define LOOPREPEAT 50000 + +#define BUFFER_SIZE 30000 +#define DBUFFER_SIZE 1024 + + +static FILE *outfile; +static int log_store = 0; +static int callout_count; +static int callout_extra; +static int callout_fail_count; +static int callout_fail_id; +static int first_callout; +static int use_utf8; +static size_t gotten_store; + + + +static const int utf8_table1[] = { + 0x0000007f, 0x000007ff, 0x0000ffff, 0x001fffff, 0x03ffffff, 0x7fffffff}; + +static const int utf8_table2[] = { + 0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc}; + +static const int utf8_table3[] = { + 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01}; + + + +/************************************************* +* Print compiled regex * +*************************************************/ + +/* The code for doing this is held in a separate file that is also included in +pcre.c when it is compiled with the debug switch. It defines a function called +print_internals(), which uses a table of opcode lengths defined by the macro +OP_LENGTHS, whose name must be OP_lengths. */ + +static uschar OP_lengths[] = { OP_LENGTHS }; + +#include "printint.c" + + + +/************************************************* +* Read number from string * +*************************************************/ + +/* We don't use strtoul() because SunOS4 doesn't have it. Rather than mess +around with conditional compilation, just do the job by hand. It is only used +for unpicking the -o argument, so just keep it simple. + +Arguments: + str string to be converted + endptr where to put the end pointer + +Returns: the unsigned long +*/ + +static int +get_value(unsigned char *str, unsigned char **endptr) +{ +int result = 0; +while(*str != 0 && isspace(*str)) str++; +while (isdigit(*str)) result = result * 10 + (int)(*str++ - '0'); +*endptr = str; +return(result); +} + + + +/************************************************* +* Convert character value to UTF-8 * +*************************************************/ + +/* This function takes an integer value in the range 0 - 0x7fffffff +and encodes it as a UTF-8 character in 0 to 6 bytes. + +Arguments: + cvalue the character value + buffer pointer to buffer for result - at least 6 bytes long + +Returns: number of characters placed in the buffer + -1 if input character is negative + 0 if input character is positive but too big (only when + int is longer than 32 bits) +*/ + +static int +ord2utf8(int cvalue, unsigned char *buffer) +{ +register int i, j; +for (i = 0; i < sizeof(utf8_table1)/sizeof(int); i++) + if (cvalue <= utf8_table1[i]) break; +if (i >= sizeof(utf8_table1)/sizeof(int)) return 0; +if (cvalue < 0) return -1; + +buffer += i; +for (j = i; j > 0; j--) + { + *buffer-- = 0x80 | (cvalue & 0x3f); + cvalue >>= 6; + } +*buffer = utf8_table2[i] | cvalue; +return i + 1; +} + + +/************************************************* +* Convert UTF-8 string to value * +*************************************************/ + +/* This function takes one or more bytes that represents a UTF-8 character, +and returns the value of the character. + +Argument: + buffer a pointer to the byte vector + vptr a pointer to an int to receive the value + +Returns: > 0 => the number of bytes consumed + -6 to 0 => malformed UTF-8 character at offset = (-return) +*/ + +static int +utf82ord(unsigned char *buffer, int *vptr) +{ +int c = *buffer++; +int d = c; +int i, j, s; + +for (i = -1; i < 6; i++) /* i is number of additional bytes */ + { + if ((d & 0x80) == 0) break; + d <<= 1; + } + +if (i == -1) { *vptr = c; return 1; } /* ascii character */ +if (i == 0 || i == 6) return 0; /* invalid UTF-8 */ + +/* i now has a value in the range 1-5 */ + +s = 6*i; +d = (c & utf8_table3[i]) << s; + +for (j = 0; j < i; j++) + { + c = *buffer++; + if ((c & 0xc0) != 0x80) return -(j+1); + s -= 6; + d |= (c & 0x3f) << s; + } + +/* Check that encoding was the correct unique one */ + +for (j = 0; j < sizeof(utf8_table1)/sizeof(int); j++) + if (d <= utf8_table1[j]) break; +if (j != i) return -(i+1); + +/* Valid value */ + +*vptr = d; +return i+1; +} + + + +/************************************************* +* Print character string * +*************************************************/ + +/* Character string printing function. Must handle UTF-8 strings in utf8 +mode. Yields number of characters printed. If handed a NULL file, just counts +chars without printing. */ + +static int pchars(unsigned char *p, int length, FILE *f) +{ +int c; +int yield = 0; + +while (length-- > 0) + { + if (use_utf8) + { + int rc = utf82ord(p, &c); + + if (rc > 0 && rc <= length + 1) /* Mustn't run over the end */ + { + length -= rc - 1; + p += rc; + if (c < 256 && isprint(c)) + { + if (f != NULL) fprintf(f, "%c", c); + yield++; + } + else + { + int n; + if (f != NULL) fprintf(f, "\\x{%02x}%n", c, &n); + yield += n; + } + continue; + } + } + + /* Not UTF-8, or malformed UTF-8 */ + + if (isprint(c = *(p++))) + { + if (f != NULL) fprintf(f, "%c", c); + yield++; + } + else + { + if (f != NULL) fprintf(f, "\\x%02x", c); + yield += 4; + } + } + +return yield; +} + + + +/************************************************* +* Callout function * +*************************************************/ + +/* Called from PCRE as a result of the (?C) item. We print out where we are in +the match. Yield zero unless more callouts than the fail count, or the callout +data is not zero. */ + +static int callout(pcre_callout_block *cb) +{ +FILE *f = (first_callout | callout_extra)? outfile : NULL; +int i, pre_start, post_start; + +if (callout_extra) + { + fprintf(f, "Callout %d: last capture = %d\n", + cb->callout_number, cb->capture_last); + + for (i = 0; i < cb->capture_top * 2; i += 2) + { + if (cb->offset_vector[i] < 0) + fprintf(f, "%2d: \n", i/2); + else + { + fprintf(f, "%2d: ", i/2); + (void)pchars((unsigned char *)cb->subject + cb->offset_vector[i], + cb->offset_vector[i+1] - cb->offset_vector[i], f); + fprintf(f, "\n"); + } + } + } + +/* Re-print the subject in canonical form, the first time or if giving full +datails. On subsequent calls in the same match, we use pchars just to find the +printed lengths of the substrings. */ + +if (f != NULL) fprintf(f, "--->"); + +pre_start = pchars((unsigned char *)cb->subject, cb->start_match, f); +post_start = pchars((unsigned char *)(cb->subject + cb->start_match), + cb->current_position - cb->start_match, f); + +(void)pchars((unsigned char *)(cb->subject + cb->current_position), + cb->subject_length - cb->current_position, f); + +if (f != NULL) fprintf(f, "\n"); + +/* Always print appropriate indicators, with callout number if not already +shown */ + +if (callout_extra) fprintf(outfile, " "); + else fprintf(outfile, "%3d ", cb->callout_number); + +for (i = 0; i < pre_start; i++) fprintf(outfile, " "); +fprintf(outfile, "^"); + +if (post_start > 0) + { + for (i = 0; i < post_start - 1; i++) fprintf(outfile, " "); + fprintf(outfile, "^"); + } + +fprintf(outfile, "\n"); + +first_callout = 0; + +if ((int)(cb->callout_data) != 0) + { + fprintf(outfile, "Callout data = %d\n", (int)(cb->callout_data)); + return (int)(cb->callout_data); + } + +return (cb->callout_number != callout_fail_id)? 0 : + (++callout_count >= callout_fail_count)? 1 : 0; +} + + +/************************************************* +* Local malloc function * +*************************************************/ + +/* Alternative malloc function, to test functionality and show the size of the +compiled re. */ + +static void *new_malloc(size_t size) +{ +gotten_store = size; +return malloc(size); +} + + + +/************************************************* +* Call pcre_fullinfo() * +*************************************************/ + +/* Get one piece of information from the pcre_fullinfo() function */ + +static void new_info(pcre *re, pcre_extra *study, int option, void *ptr) +{ +int rc; +if ((rc = pcre_fullinfo(re, study, option, ptr)) < 0) + fprintf(outfile, "Error %d from pcre_fullinfo(%d)\n", rc, option); +} + + + +/************************************************* +* Main Program * +*************************************************/ + +/* Read lines from named file or stdin and write to named file or stdout; lines +consist of a regular expression, in delimiters and optionally followed by +options, followed by a set of test data, terminated by an empty line. */ + +int main(int argc, char **argv) +{ +FILE *infile = stdin; +int options = 0; +int study_options = 0; +int op = 1; +int timeit = 0; +int showinfo = 0; +int showstore = 0; +int size_offsets = 45; +int size_offsets_max; +int *offsets; +#if !defined NOPOSIX +int posix = 0; +#endif +int debug = 0; +int done = 0; + +unsigned char *buffer; +unsigned char *dbuffer; + +/* Get buffers from malloc() so that Electric Fence will check their misuse +when I am debugging. */ + +buffer = malloc(BUFFER_SIZE); +dbuffer = malloc(DBUFFER_SIZE); + +/* Static so that new_malloc can use it. */ + +outfile = stdout; + +/* Scan options */ + +while (argc > 1 && argv[op][0] == '-') + { + unsigned char *endptr; + + if (strcmp(argv[op], "-s") == 0 || strcmp(argv[op], "-m") == 0) + showstore = 1; + else if (strcmp(argv[op], "-t") == 0) timeit = 1; + else if (strcmp(argv[op], "-i") == 0) showinfo = 1; + else if (strcmp(argv[op], "-d") == 0) showinfo = debug = 1; + else if (strcmp(argv[op], "-o") == 0 && argc > 2 && + ((size_offsets = get_value((unsigned char *)argv[op+1], &endptr)), + *endptr == 0)) + { + op++; + argc--; + } +#if !defined NOPOSIX + else if (strcmp(argv[op], "-p") == 0) posix = 1; +#endif + else if (strcmp(argv[op], "-C") == 0) + { + int rc; + printf("PCRE version %s\n", pcre_version()); + printf("Compiled with\n"); + (void)pcre_config(PCRE_CONFIG_UTF8, &rc); + printf(" %sUTF-8 support\n", rc? "" : "No "); + (void)pcre_config(PCRE_CONFIG_NEWLINE, &rc); + printf(" Newline character is %s\n", (rc == '\r')? "CR" : "LF"); + (void)pcre_config(PCRE_CONFIG_LINK_SIZE, &rc); + printf(" Internal link size = %d\n", rc); + (void)pcre_config(PCRE_CONFIG_POSIX_MALLOC_THRESHOLD, &rc); + printf(" POSIX malloc threshold = %d\n", rc); + (void)pcre_config(PCRE_CONFIG_MATCH_LIMIT, &rc); + printf(" Default match limit = %d\n", rc); + exit(0); + } + else + { + printf("** Unknown or malformed option %s\n", argv[op]); + printf("Usage: pcretest [-d] [-i] [-o ] [-p] [-s] [-t] [ []]\n"); + printf(" -C show PCRE compile-time options and exit\n"); + printf(" -d debug: show compiled code; implies -i\n" + " -i show information about compiled pattern\n" + " -o set size of offsets vector to \n"); +#if !defined NOPOSIX + printf(" -p use POSIX interface\n"); +#endif + printf(" -s output store information\n" + " -t time compilation and execution\n"); + return 1; + } + op++; + argc--; + } + +/* Get the store for the offsets vector, and remember what it was */ + +size_offsets_max = size_offsets; +offsets = malloc(size_offsets_max * sizeof(int)); +if (offsets == NULL) + { + printf("** Failed to get %d bytes of memory for offsets vector\n", + size_offsets_max * sizeof(int)); + return 1; + } + +/* Sort out the input and output files */ + +if (argc > 1) + { + infile = fopen(argv[op], "r"); + if (infile == NULL) + { + printf("** Failed to open %s\n", argv[op]); + return 1; + } + } + +if (argc > 2) + { + outfile = fopen(argv[op+1], "w"); + if (outfile == NULL) + { + printf("** Failed to open %s\n", argv[op+1]); + return 1; + } + } + +/* Set alternative malloc function */ + +pcre_malloc = new_malloc; + +/* Heading line, then prompt for first regex if stdin */ + +fprintf(outfile, "PCRE version %s\n\n", pcre_version()); + +/* Main loop */ + +while (!done) + { + pcre *re = NULL; + pcre_extra *extra = NULL; + +#if !defined NOPOSIX /* There are still compilers that require no indent */ + regex_t preg; + int do_posix = 0; +#endif + + const char *error; + unsigned char *p, *pp, *ppp; + const unsigned char *tables = NULL; + int do_study = 0; + int do_debug = debug; + int do_G = 0; + int do_g = 0; + int do_showinfo = showinfo; + int do_showrest = 0; + int erroroffset, len, delimiter; + + use_utf8 = 0; + + if (infile == stdin) printf(" re> "); + if (fgets((char *)buffer, BUFFER_SIZE, infile) == NULL) break; + if (infile != stdin) fprintf(outfile, "%s", (char *)buffer); + fflush(outfile); + + p = buffer; + while (isspace(*p)) p++; + if (*p == 0) continue; + + /* Get the delimiter and seek the end of the pattern; if is isn't + complete, read more. */ + + delimiter = *p++; + + if (isalnum(delimiter) || delimiter == '\\') + { + fprintf(outfile, "** Delimiter must not be alphameric or \\\n"); + goto SKIP_DATA; + } + + pp = p; + + for(;;) + { + while (*pp != 0) + { + if (*pp == '\\' && pp[1] != 0) pp++; + else if (*pp == delimiter) break; + pp++; + } + if (*pp != 0) break; + + len = BUFFER_SIZE - (pp - buffer); + if (len < 256) + { + fprintf(outfile, "** Expression too long - missing delimiter?\n"); + goto SKIP_DATA; + } + + if (infile == stdin) printf(" > "); + if (fgets((char *)pp, len, infile) == NULL) + { + fprintf(outfile, "** Unexpected EOF\n"); + done = 1; + goto CONTINUE; + } + if (infile != stdin) fprintf(outfile, "%s", (char *)pp); + } + + /* If the first character after the delimiter is backslash, make + the pattern end with backslash. This is purely to provide a way + of testing for the error message when a pattern ends with backslash. */ + + if (pp[1] == '\\') *pp++ = '\\'; + + /* Terminate the pattern at the delimiter */ + + *pp++ = 0; + + /* Look for options after final delimiter */ + + options = 0; + study_options = 0; + log_store = showstore; /* default from command line */ + + while (*pp != 0) + { + switch (*pp++) + { + case 'g': do_g = 1; break; + case 'i': options |= PCRE_CASELESS; break; + case 'm': options |= PCRE_MULTILINE; break; + case 's': options |= PCRE_DOTALL; break; + case 'x': options |= PCRE_EXTENDED; break; + + case '+': do_showrest = 1; break; + case 'A': options |= PCRE_ANCHORED; break; + case 'D': do_debug = do_showinfo = 1; break; + case 'E': options |= PCRE_DOLLAR_ENDONLY; break; + case 'G': do_G = 1; break; + case 'I': do_showinfo = 1; break; + case 'M': log_store = 1; break; + case 'N': options |= PCRE_NO_AUTO_CAPTURE; break; + +#if !defined NOPOSIX + case 'P': do_posix = 1; break; +#endif + + case 'S': do_study = 1; break; + case 'U': options |= PCRE_UNGREEDY; break; + case 'X': options |= PCRE_EXTRA; break; + case '8': options |= PCRE_UTF8; use_utf8 = 1; break; + + case 'L': + ppp = pp; + while (*ppp != '\n' && *ppp != ' ') ppp++; + *ppp = 0; + if (setlocale(LC_CTYPE, (const char *)pp) == NULL) + { + fprintf(outfile, "** Failed to set locale \"%s\"\n", pp); + goto SKIP_DATA; + } + tables = pcre_maketables(); + pp = ppp; + break; + + case '\n': case ' ': break; + default: + fprintf(outfile, "** Unknown option '%c'\n", pp[-1]); + goto SKIP_DATA; + } + } + + /* Handle compiling via the POSIX interface, which doesn't support the + timing, showing, or debugging options, nor the ability to pass over + local character tables. */ + +#if !defined NOPOSIX + if (posix || do_posix) + { + int rc; + int cflags = 0; + if ((options & PCRE_CASELESS) != 0) cflags |= REG_ICASE; + if ((options & PCRE_MULTILINE) != 0) cflags |= REG_NEWLINE; + rc = regcomp(&preg, (char *)p, cflags); + + /* Compilation failed; go back for another re, skipping to blank line + if non-interactive. */ + + if (rc != 0) + { + (void)regerror(rc, &preg, (char *)buffer, BUFFER_SIZE); + fprintf(outfile, "Failed: POSIX code %d: %s\n", rc, buffer); + goto SKIP_DATA; + } + } + + /* Handle compiling via the native interface */ + + else +#endif /* !defined NOPOSIX */ + + { + if (timeit) + { + register int i; + clock_t time_taken; + clock_t start_time = clock(); + for (i = 0; i < LOOPREPEAT; i++) + { + re = pcre_compile((char *)p, options, &error, &erroroffset, tables); + if (re != NULL) free(re); + } + time_taken = clock() - start_time; + fprintf(outfile, "Compile time %.3f milliseconds\n", + (((double)time_taken * 1000.0) / (double)LOOPREPEAT) / + (double)CLOCKS_PER_SEC); + } + + re = pcre_compile((char *)p, options, &error, &erroroffset, tables); + + /* Compilation failed; go back for another re, skipping to blank line + if non-interactive. */ + + if (re == NULL) + { + fprintf(outfile, "Failed: %s at offset %d\n", error, erroroffset); + SKIP_DATA: + if (infile != stdin) + { + for (;;) + { + if (fgets((char *)buffer, BUFFER_SIZE, infile) == NULL) + { + done = 1; + goto CONTINUE; + } + len = (int)strlen((char *)buffer); + while (len > 0 && isspace(buffer[len-1])) len--; + if (len == 0) break; + } + fprintf(outfile, "\n"); + } + goto CONTINUE; + } + + /* Compilation succeeded; print data if required. There are now two + info-returning functions. The old one has a limited interface and + returns only limited data. Check that it agrees with the newer one. */ + + if (log_store) + fprintf(outfile, "Memory allocation (code space): %d\n", + (int)(gotten_store - + sizeof(real_pcre) - + ((real_pcre *)re)->name_count * ((real_pcre *)re)->name_entry_size)); + + if (do_showinfo) + { + unsigned long int get_options; + int old_first_char, old_options, old_count; + int count, backrefmax, first_char, need_char; + int nameentrysize, namecount; + const uschar *nametable; + size_t size; + + if (do_debug) + { + fprintf(outfile, "------------------------------------------------------------------\n"); + print_internals(re, outfile); + } + + new_info(re, NULL, PCRE_INFO_OPTIONS, &get_options); + new_info(re, NULL, PCRE_INFO_SIZE, &size); + new_info(re, NULL, PCRE_INFO_CAPTURECOUNT, &count); + new_info(re, NULL, PCRE_INFO_BACKREFMAX, &backrefmax); + new_info(re, NULL, PCRE_INFO_FIRSTBYTE, &first_char); + new_info(re, NULL, PCRE_INFO_LASTLITERAL, &need_char); + new_info(re, NULL, PCRE_INFO_NAMEENTRYSIZE, &nameentrysize); + new_info(re, NULL, PCRE_INFO_NAMECOUNT, &namecount); + new_info(re, NULL, PCRE_INFO_NAMETABLE, (void *)&nametable); + + old_count = pcre_info(re, &old_options, &old_first_char); + if (count < 0) fprintf(outfile, + "Error %d from pcre_info()\n", count); + else + { + if (old_count != count) fprintf(outfile, + "Count disagreement: pcre_fullinfo=%d pcre_info=%d\n", count, + old_count); + + if (old_first_char != first_char) fprintf(outfile, + "First char disagreement: pcre_fullinfo=%d pcre_info=%d\n", + first_char, old_first_char); + + if (old_options != (int)get_options) fprintf(outfile, + "Options disagreement: pcre_fullinfo=%ld pcre_info=%d\n", + get_options, old_options); + } + + if (size != gotten_store) fprintf(outfile, + "Size disagreement: pcre_fullinfo=%d call to malloc for %d\n", + size, gotten_store); + + fprintf(outfile, "Capturing subpattern count = %d\n", count); + if (backrefmax > 0) + fprintf(outfile, "Max back reference = %d\n", backrefmax); + + if (namecount > 0) + { + fprintf(outfile, "Named capturing subpatterns:\n"); + while (namecount-- > 0) + { + fprintf(outfile, " %s %*s%3d\n", nametable + 2, + nameentrysize - 3 - (int)strlen((char *)nametable + 2), "", + GET2(nametable, 0)); + nametable += nameentrysize; + } + } + + if (get_options == 0) fprintf(outfile, "No options\n"); + else fprintf(outfile, "Options:%s%s%s%s%s%s%s%s%s\n", + ((get_options & PCRE_ANCHORED) != 0)? " anchored" : "", + ((get_options & PCRE_CASELESS) != 0)? " caseless" : "", + ((get_options & PCRE_EXTENDED) != 0)? " extended" : "", + ((get_options & PCRE_MULTILINE) != 0)? " multiline" : "", + ((get_options & PCRE_DOTALL) != 0)? " dotall" : "", + ((get_options & PCRE_DOLLAR_ENDONLY) != 0)? " dollar_endonly" : "", + ((get_options & PCRE_EXTRA) != 0)? " extra" : "", + ((get_options & PCRE_UNGREEDY) != 0)? " ungreedy" : "", + ((get_options & PCRE_UTF8) != 0)? " utf8" : ""); + + if (((((real_pcre *)re)->options) & PCRE_ICHANGED) != 0) + fprintf(outfile, "Case state changes\n"); + + if (first_char == -1) + { + fprintf(outfile, "First char at start or follows \\n\n"); + } + else if (first_char < 0) + { + fprintf(outfile, "No first char\n"); + } + else + { + int ch = first_char & 255; + const char *caseless = ((first_char & REQ_CASELESS) == 0)? + "" : " (caseless)"; + if (isprint(ch)) + fprintf(outfile, "First char = \'%c\'%s\n", ch, caseless); + else + fprintf(outfile, "First char = %d%s\n", ch, caseless); + } + + if (need_char < 0) + { + fprintf(outfile, "No need char\n"); + } + else + { + int ch = need_char & 255; + const char *caseless = ((need_char & REQ_CASELESS) == 0)? + "" : " (caseless)"; + if (isprint(ch)) + fprintf(outfile, "Need char = \'%c\'%s\n", ch, caseless); + else + fprintf(outfile, "Need char = %d%s\n", ch, caseless); + } + } + + /* If /S was present, study the regexp to generate additional info to + help with the matching. */ + + if (do_study) + { + if (timeit) + { + register int i; + clock_t time_taken; + clock_t start_time = clock(); + for (i = 0; i < LOOPREPEAT; i++) + extra = pcre_study(re, study_options, &error); + time_taken = clock() - start_time; + if (extra != NULL) free(extra); + fprintf(outfile, " Study time %.3f milliseconds\n", + (((double)time_taken * 1000.0) / (double)LOOPREPEAT) / + (double)CLOCKS_PER_SEC); + } + + extra = pcre_study(re, study_options, &error); + if (error != NULL) + fprintf(outfile, "Failed to study: %s\n", error); + else if (extra == NULL) + fprintf(outfile, "Study returned NULL\n"); + + else if (do_showinfo) + { + size_t size; + uschar *start_bits = NULL; + new_info(re, extra, PCRE_INFO_STUDYSIZE, &size); + new_info(re, extra, PCRE_INFO_FIRSTTABLE, &start_bits); + fprintf(outfile, "Study size = %d\n", size); + if (start_bits == NULL) + fprintf(outfile, "No starting character set\n"); + else + { + int i; + int c = 24; + fprintf(outfile, "Starting character set: "); + for (i = 0; i < 256; i++) + { + if ((start_bits[i/8] & (1<<(i%8))) != 0) + { + if (c > 75) + { + fprintf(outfile, "\n "); + c = 2; + } + if (isprint(i) && i != ' ') + { + fprintf(outfile, "%c ", i); + c += 2; + } + else + { + fprintf(outfile, "\\x%02x ", i); + c += 5; + } + } + } + fprintf(outfile, "\n"); + } + } + } + } + + /* Read data lines and test them */ + + for (;;) + { + unsigned char *q; + unsigned char *bptr = dbuffer; + int *use_offsets = offsets; + int use_size_offsets = size_offsets; + int callout_data = 0; + int callout_data_set = 0; + int count, c; + int copystrings = 0; + int find_match_limit = 0; + int getstrings = 0; + int getlist = 0; + int gmatched = 0; + int start_offset = 0; + int g_notempty = 0; + + options = 0; + + pcre_callout = callout; + first_callout = 1; + callout_extra = 0; + callout_count = 0; + callout_fail_count = 999999; + callout_fail_id = -1; + + if (infile == stdin) printf("data> "); + if (fgets((char *)buffer, BUFFER_SIZE, infile) == NULL) + { + done = 1; + goto CONTINUE; + } + if (infile != stdin) fprintf(outfile, "%s", (char *)buffer); + + len = (int)strlen((char *)buffer); + while (len > 0 && isspace(buffer[len-1])) len--; + buffer[len] = 0; + if (len == 0) break; + + p = buffer; + while (isspace(*p)) p++; + + q = dbuffer; + while ((c = *p++) != 0) + { + int i = 0; + int n = 0; + + if (c == '\\') switch ((c = *p++)) + { + case 'a': c = 7; break; + case 'b': c = '\b'; break; + case 'e': c = 27; break; + case 'f': c = '\f'; break; + case 'n': c = '\n'; break; + case 'r': c = '\r'; break; + case 't': c = '\t'; break; + case 'v': c = '\v'; break; + + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + c -= '0'; + while (i++ < 2 && isdigit(*p) && *p != '8' && *p != '9') + c = c * 8 + *p++ - '0'; + break; + + case 'x': + + /* Handle \x{..} specially - new Perl thing for utf8 */ + + if (*p == '{') + { + unsigned char *pt = p; + c = 0; + while (isxdigit(*(++pt))) + c = c * 16 + tolower(*pt) - ((isdigit(*pt))? '0' : 'W'); + if (*pt == '}') + { + unsigned char buff8[8]; + int ii, utn; + utn = ord2utf8(c, buff8); + for (ii = 0; ii < utn - 1; ii++) *q++ = buff8[ii]; + c = buff8[ii]; /* Last byte */ + p = pt + 1; + break; + } + /* Not correct form; fall through */ + } + + /* Ordinary \x */ + + c = 0; + while (i++ < 2 && isxdigit(*p)) + { + c = c * 16 + tolower(*p) - ((isdigit(*p))? '0' : 'W'); + p++; + } + break; + + case 0: /* Allows for an empty line */ + p--; + continue; + + case 'A': /* Option setting */ + options |= PCRE_ANCHORED; + continue; + + case 'B': + options |= PCRE_NOTBOL; + continue; + + case 'C': + if (isdigit(*p)) /* Set copy string */ + { + while(isdigit(*p)) n = n * 10 + *p++ - '0'; + copystrings |= 1 << n; + } + else if (isalnum(*p)) + { + uschar name[256]; + uschar *npp = name; + while (isalnum(*p)) *npp++ = *p++; + *npp = 0; + n = pcre_get_stringnumber(re, (char *)name); + if (n < 0) + fprintf(outfile, "no parentheses with name \"%s\"\n", name); + else copystrings |= 1 << n; + } + else if (*p == '+') + { + callout_extra = 1; + p++; + } + else if (*p == '-') + { + pcre_callout = NULL; + p++; + } + else if (*p == '!') + { + callout_fail_id = 0; + p++; + while(isdigit(*p)) + callout_fail_id = callout_fail_id * 10 + *p++ - '0'; + callout_fail_count = 0; + if (*p == '!') + { + p++; + while(isdigit(*p)) + callout_fail_count = callout_fail_count * 10 + *p++ - '0'; + } + } + else if (*p == '*') + { + int sign = 1; + callout_data = 0; + if (*(++p) == '-') { sign = -1; p++; } + while(isdigit(*p)) + callout_data = callout_data * 10 + *p++ - '0'; + callout_data *= sign; + callout_data_set = 1; + } + continue; + + case 'G': + if (isdigit(*p)) + { + while(isdigit(*p)) n = n * 10 + *p++ - '0'; + getstrings |= 1 << n; + } + else if (isalnum(*p)) + { + uschar name[256]; + uschar *npp = name; + while (isalnum(*p)) *npp++ = *p++; + *npp = 0; + n = pcre_get_stringnumber(re, (char *)name); + if (n < 0) + fprintf(outfile, "no parentheses with name \"%s\"\n", name); + else getstrings |= 1 << n; + } + continue; + + case 'L': + getlist = 1; + continue; + + case 'M': + find_match_limit = 1; + continue; + + case 'N': + options |= PCRE_NOTEMPTY; + continue; + + case 'O': + while(isdigit(*p)) n = n * 10 + *p++ - '0'; + if (n > size_offsets_max) + { + size_offsets_max = n; + free(offsets); + use_offsets = offsets = malloc(size_offsets_max * sizeof(int)); + if (offsets == NULL) + { + printf("** Failed to get %d bytes of memory for offsets vector\n", + size_offsets_max * sizeof(int)); + return 1; + } + } + use_size_offsets = n; + if (n == 0) use_offsets = NULL; /* Ensures it can't write to it */ + continue; + + case 'Z': + options |= PCRE_NOTEOL; + continue; + } + *q++ = c; + } + *q = 0; + len = q - dbuffer; + + /* Handle matching via the POSIX interface, which does not + support timing or playing with the match limit or callout data. */ + +#if !defined NOPOSIX + if (posix || do_posix) + { + int rc; + int eflags = 0; + regmatch_t *pmatch = NULL; + if (use_size_offsets > 0) + pmatch = malloc(sizeof(regmatch_t) * use_size_offsets); + if ((options & PCRE_NOTBOL) != 0) eflags |= REG_NOTBOL; + if ((options & PCRE_NOTEOL) != 0) eflags |= REG_NOTEOL; + + rc = regexec(&preg, (const char *)bptr, use_size_offsets, pmatch, eflags); + + if (rc != 0) + { + (void)regerror(rc, &preg, (char *)buffer, BUFFER_SIZE); + fprintf(outfile, "No match: POSIX code %d: %s\n", rc, buffer); + } + else + { + size_t i; + for (i = 0; i < (size_t)use_size_offsets; i++) + { + if (pmatch[i].rm_so >= 0) + { + fprintf(outfile, "%2d: ", (int)i); + (void)pchars(dbuffer + pmatch[i].rm_so, + pmatch[i].rm_eo - pmatch[i].rm_so, outfile); + fprintf(outfile, "\n"); + if (i == 0 && do_showrest) + { + fprintf(outfile, " 0+ "); + (void)pchars(dbuffer + pmatch[i].rm_eo, len - pmatch[i].rm_eo, + outfile); + fprintf(outfile, "\n"); + } + } + } + } + free(pmatch); + } + + /* Handle matching via the native interface - repeats for /g and /G */ + + else +#endif /* !defined NOPOSIX */ + + for (;; gmatched++) /* Loop for /g or /G */ + { + if (timeit) + { + register int i; + clock_t time_taken; + clock_t start_time = clock(); + for (i = 0; i < LOOPREPEAT; i++) + count = pcre_exec(re, extra, (char *)bptr, len, + start_offset, options | g_notempty, use_offsets, use_size_offsets); + time_taken = clock() - start_time; + fprintf(outfile, "Execute time %.3f milliseconds\n", + (((double)time_taken * 1000.0) / (double)LOOPREPEAT) / + (double)CLOCKS_PER_SEC); + } + + /* If find_match_limit is set, we want to do repeated matches with + varying limits in order to find the minimum value. */ + + if (find_match_limit) + { + int min = 0; + int mid = 64; + int max = -1; + + if (extra == NULL) + { + extra = malloc(sizeof(pcre_extra)); + extra->flags = 0; + } + extra->flags |= PCRE_EXTRA_MATCH_LIMIT; + + for (;;) + { + extra->match_limit = mid; + count = pcre_exec(re, extra, (char *)bptr, len, start_offset, + options | g_notempty, use_offsets, use_size_offsets); + if (count == PCRE_ERROR_MATCHLIMIT) + { + /* fprintf(outfile, "Testing match limit = %d\n", mid); */ + min = mid; + mid = (mid == max - 1)? max : (max > 0)? (min + max)/2 : mid*2; + } + else if (count >= 0 || count == PCRE_ERROR_NOMATCH) + { + if (mid == min + 1) + { + fprintf(outfile, "Minimum match limit = %d\n", mid); + break; + } + /* fprintf(outfile, "Testing match limit = %d\n", mid); */ + max = mid; + mid = (min + mid)/2; + } + else break; /* Some other error */ + } + + extra->flags &= ~PCRE_EXTRA_MATCH_LIMIT; + } + + /* If callout_data is set, use the interface with additional data */ + + else if (callout_data_set) + { + if (extra == NULL) + { + extra = malloc(sizeof(pcre_extra)); + extra->flags = 0; + } + extra->flags |= PCRE_EXTRA_CALLOUT_DATA; + extra->callout_data = (void *)callout_data; + count = pcre_exec(re, extra, (char *)bptr, len, start_offset, + options | g_notempty, use_offsets, use_size_offsets); + extra->flags &= ~PCRE_EXTRA_CALLOUT_DATA; + } + + /* The normal case is just to do the match once, with the default + value of match_limit. */ + + else count = pcre_exec(re, extra, (char *)bptr, len, + start_offset, options | g_notempty, use_offsets, use_size_offsets); + + if (count == 0) + { + fprintf(outfile, "Matched, but too many substrings\n"); + count = use_size_offsets/3; + } + + /* Matched */ + + if (count >= 0) + { + int i; + for (i = 0; i < count * 2; i += 2) + { + if (use_offsets[i] < 0) + fprintf(outfile, "%2d: \n", i/2); + else + { + fprintf(outfile, "%2d: ", i/2); + (void)pchars(bptr + use_offsets[i], + use_offsets[i+1] - use_offsets[i], outfile); + fprintf(outfile, "\n"); + if (i == 0) + { + if (do_showrest) + { + fprintf(outfile, " 0+ "); + (void)pchars(bptr + use_offsets[i+1], len - use_offsets[i+1], + outfile); + fprintf(outfile, "\n"); + } + } + } + } + + for (i = 0; i < 32; i++) + { + if ((copystrings & (1 << i)) != 0) + { + char copybuffer[16]; + int rc = pcre_copy_substring((char *)bptr, use_offsets, count, + i, copybuffer, sizeof(copybuffer)); + if (rc < 0) + fprintf(outfile, "copy substring %d failed %d\n", i, rc); + else + fprintf(outfile, "%2dC %s (%d)\n", i, copybuffer, rc); + } + } + + for (i = 0; i < 32; i++) + { + if ((getstrings & (1 << i)) != 0) + { + const char *substring; + int rc = pcre_get_substring((char *)bptr, use_offsets, count, + i, &substring); + if (rc < 0) + fprintf(outfile, "get substring %d failed %d\n", i, rc); + else + { + fprintf(outfile, "%2dG %s (%d)\n", i, substring, rc); + /* free((void *)substring); */ + pcre_free_substring(substring); + } + } + } + + if (getlist) + { + const char **stringlist; + int rc = pcre_get_substring_list((char *)bptr, use_offsets, count, + &stringlist); + if (rc < 0) + fprintf(outfile, "get substring list failed %d\n", rc); + else + { + for (i = 0; i < count; i++) + fprintf(outfile, "%2dL %s\n", i, stringlist[i]); + if (stringlist[i] != NULL) + fprintf(outfile, "string list not terminated by NULL\n"); + /* free((void *)stringlist); */ + pcre_free_substring_list(stringlist); + } + } + } + + /* Failed to match. If this is a /g or /G loop and we previously set + g_notempty after a null match, this is not necessarily the end. + We want to advance the start offset, and continue. Fudge the offset + values to achieve this. We won't be at the end of the string - that + was checked before setting g_notempty. */ + + else + { + if (g_notempty != 0) + { + use_offsets[0] = start_offset; + use_offsets[1] = start_offset + 1; + } + else + { + if (gmatched == 0) /* Error if no previous matches */ + { + if (count == -1) fprintf(outfile, "No match\n"); + else fprintf(outfile, "Error %d\n", count); + } + break; /* Out of the /g loop */ + } + } + + /* If not /g or /G we are done */ + + if (!do_g && !do_G) break; + + /* If we have matched an empty string, first check to see if we are at + the end of the subject. If so, the /g loop is over. Otherwise, mimic + what Perl's /g options does. This turns out to be rather cunning. First + we set PCRE_NOTEMPTY and PCRE_ANCHORED and try the match again at the + same point. If this fails (picked up above) we advance to the next + character. */ + + g_notempty = 0; + if (use_offsets[0] == use_offsets[1]) + { + if (use_offsets[0] == len) break; + g_notempty = PCRE_NOTEMPTY | PCRE_ANCHORED; + } + + /* For /g, update the start offset, leaving the rest alone */ + + if (do_g) start_offset = use_offsets[1]; + + /* For /G, update the pointer and length */ + + else + { + bptr += use_offsets[1]; + len -= use_offsets[1]; + } + } /* End of loop for /g and /G */ + } /* End of loop for data lines */ + + CONTINUE: + +#if !defined NOPOSIX + if (posix || do_posix) regfree(&preg); +#endif + + if (re != NULL) free(re); + if (extra != NULL) free(extra); + if (tables != NULL) + { + free((void *)tables); + setlocale(LC_CTYPE, "C"); + } + } + +fprintf(outfile, "\n"); +return 0; +} + +/* End */ diff --git a/lc-continuity/mk4/continuity/pcre/perltest b/lc-continuity/mk4/continuity/pcre/perltest new file mode 100644 index 0000000000000000000000000000000000000000..bb34cc8398f32a761ec91aadb86a123bd56f731f --- /dev/null +++ b/lc-continuity/mk4/continuity/pcre/perltest @@ -0,0 +1,211 @@ +#! /usr/bin/perl + +# Program for testing regular expressions with perl to check that PCRE handles +# them the same. This is the version that supports /8 for UTF-8 testing. As it +# stands, it requires at least Perl 5.8 for UTF-8 support. For Perl 5.6, it +# can be used as is for non-UTF-8 testing, but you have to uncomment the +# "use utf8" lines in order to to UTF-8 stuff (and you mustn't uncomment them +# for non-UTF-8 use). + + +# Function for turning a string into a string of printing chars. There are +# currently problems with UTF-8 strings; this fudges round them. + +sub pchars { +my($t) = ""; + +if ($utf8) + { +# use utf8; <=============== For UTF-8 in Perl 5.6 + @p = unpack('U*', $_[0]); + foreach $c (@p) + { + if ($c >= 32 && $c < 127) { $t .= chr $c; } + else { $t .= sprintf("\\x{%02x}", $c); } + } + } + +else + { + foreach $c (split(//, $_[0])) + { + if (ord $c >= 32 && ord $c < 127) { $t .= $c; } + else { $t .= sprintf("\\x%02x", ord $c); } + } + } + +$t; +} + + + +# Read lines from named file or stdin and write to named file or stdout; lines +# consist of a regular expression, in delimiters and optionally followed by +# options, followed by a set of test data, terminated by an empty line. + +# Sort out the input and output files + +if (@ARGV > 0) + { + open(INFILE, "<$ARGV[0]") || die "Failed to open $ARGV[0]\n"; + $infile = "INFILE"; + } +else { $infile = "STDIN"; } + +if (@ARGV > 1) + { + open(OUTFILE, ">$ARGV[1]") || die "Failed to open $ARGV[1]\n"; + $outfile = "OUTFILE"; + } +else { $outfile = "STDOUT"; } + +printf($outfile "Perl $] Regular Expressions\n\n"); + +# Main loop + +NEXT_RE: +for (;;) + { + printf " re> " if $infile eq "STDIN"; + last if ! ($_ = <$infile>); + printf $outfile "$_" if $infile ne "STDIN"; + next if ($_ eq ""); + + $pattern = $_; + + while ($pattern !~ /^\s*(.).*\1/s) + { + printf " > " if $infile eq "STDIN"; + last if ! ($_ = <$infile>); + printf $outfile "$_" if $infile ne "STDIN"; + $pattern .= $_; + } + + chomp($pattern); + $pattern =~ s/\s+$//; + + # The private /+ modifier means "print $' afterwards". + + $showrest = ($pattern =~ s/\+(?=[a-z]*$)//); + + # The private /8 modifier means "operate in UTF-8". Currently, Perl + # has bugs that we try to work around using this flag. + + $utf8 = ($pattern =~ s/8(?=[a-z]*$)//); + + # Check that the pattern is valid + + if ($utf8) + { +# use utf8; <=============== For UTF-8 in Perl 5.6 + eval "\$_ =~ ${pattern}"; + } + else + { + eval "\$_ =~ ${pattern}"; + } + + if ($@) + { + printf $outfile "Error: $@"; + next NEXT_RE; + } + + # If the /g modifier is present, we want to put a loop round the matching; + # otherwise just a single "if". + + $cmd = ($pattern =~ /g[a-z]*$/)? "while" : "if"; + + # If the pattern is actually the null string, Perl uses the most recently + # executed (and successfully compiled) regex is used instead. This is a + # nasty trap for the unwary! The PCRE test suite does contain null strings + # in places - if they are allowed through here all sorts of weird and + # unexpected effects happen. To avoid this, we replace such patterns with + # a non-null pattern that has the same effect. + + $pattern = "/(?#)/$2" if ($pattern =~ /^(.)\1(.*)$/); + + # Read data lines and test them + + for (;;) + { + printf "data> " if $infile eq "STDIN"; + last NEXT_RE if ! ($_ = <$infile>); + chomp; + printf $outfile "$_\n" if $infile ne "STDIN"; + + s/\s+$//; + s/^\s+//; + + last if ($_ eq ""); + + $x = eval "\"$_\""; # To get escapes processed + + # Empty array for holding results, then do the matching. + + @subs = (); + + $pushes = "push \@subs,\$&;" . + "push \@subs,\$1;" . + "push \@subs,\$2;" . + "push \@subs,\$3;" . + "push \@subs,\$4;" . + "push \@subs,\$5;" . + "push \@subs,\$6;" . + "push \@subs,\$7;" . + "push \@subs,\$8;" . + "push \@subs,\$9;" . + "push \@subs,\$10;" . + "push \@subs,\$11;" . + "push \@subs,\$12;" . + "push \@subs,\$13;" . + "push \@subs,\$14;" . + "push \@subs,\$15;" . + "push \@subs,\$16;" . + "push \@subs,\$'; }"; + + if ($utf8) + { +# use utf8; <=============== For UTF-8 in Perl 5.6 + eval "${cmd} (\$x =~ ${pattern}) {" . $pushes; + } + else + { + eval "${cmd} (\$x =~ ${pattern}) {" . $pushes; + } + + if ($@) + { + printf $outfile "Error: $@\n"; + next NEXT_RE; + } + elsif (scalar(@subs) == 0) + { + printf $outfile "No match\n"; + } + else + { + while (scalar(@subs) != 0) + { + printf $outfile (" 0: %s\n", &pchars($subs[0])); + printf $outfile (" 0+ %s\n", &pchars($subs[17])) if $showrest; + $last_printed = 0; + for ($i = 1; $i <= 16; $i++) + { + if (defined $subs[$i]) + { + while ($last_printed++ < $i-1) + { printf $outfile ("%2d: \n", $last_printed); } + printf $outfile ("%2d: %s\n", $i, &pchars($subs[$i])); + $last_printed = $i; + } + } + splice(@subs, 0, 18); + } + } + } + } + +printf $outfile "\n"; + +# End diff --git a/lc-continuity/mk4/continuity/pcre/printint.c b/lc-continuity/mk4/continuity/pcre/printint.c new file mode 100644 index 0000000000000000000000000000000000000000..cd01f0577d7976a371f54896d92dd6b3bfcc8aaf --- /dev/null +++ b/lc-continuity/mk4/continuity/pcre/printint.c @@ -0,0 +1,360 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* +This is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. See +the file Tech.Notes for some information on the internals. + +Written by: Philip Hazel + + Copyright (c) 1997-2003 University of Cambridge + +----------------------------------------------------------------------------- +Permission is granted to anyone to use this software for any purpose on any +computer system, and to redistribute it freely, subject to the following +restrictions: + +1. This software 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. + +2. The origin of this software must not be misrepresented, either by + explicit claim or by omission. + +3. Altered versions must be plainly marked as such, and must not be + misrepresented as being the original software. + +4. If PCRE is embedded in any software that is released under the GNU + General Purpose Licence (GPL), then the terms of that licence shall + supersede any condition above with which it is incompatible. +----------------------------------------------------------------------------- +*/ + + +/* This module contains a debugging function for printing out the internal form +of a compiled regular expression. It is kept in a separate file so that it can +be #included both in the pcretest program, and in the library itself when +compiled with the debugging switch. */ + + +static const char *OP_names[] = { OP_NAME_LIST }; + + +/************************************************* +* Print single- or multi-byte character * +*************************************************/ + +/* These tables are actually copies of ones in pcre.c. If we compile the +library with debugging, they are included twice, but that isn't really a +problem - compiling with debugging is pretty rare and these are very small. */ + +static int utf8_t3[] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01}; + +static uschar utf8_t4[] = { + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 }; + +static int +print_char(FILE *f, uschar *ptr, BOOL utf8) +{ +int c = *ptr; + +if (!utf8 || (c & 0xc0) != 0xc0) + { + if (isprint(c)) fprintf(f, "%c", c); else fprintf(f, "\\x%02x", c); + return 0; + } +else + { + int i; + int a = utf8_t4[c & 0x3f]; /* Number of additional bytes */ + int s = 6*a; + c = (c & utf8_t3[a]) << s; + for (i = 1; i <= a; i++) + { + s -= 6; + c |= (ptr[i] & 0x3f) << s; + } + if (c < 128) fprintf(f, "\\x%02x", c); else fprintf(f, "\\x{%x}", c); + return a; + } +} + + + + +/************************************************* +* Print compiled regex * +*************************************************/ + +static void +print_internals(pcre *external_re, FILE *f) +{ +real_pcre *re = (real_pcre *)external_re; +uschar *codestart = + (uschar *)re + sizeof(real_pcre) + re->name_count * re->name_entry_size; +uschar *code = codestart; +BOOL utf8 = (re->options & PCRE_UTF8) != 0; + +for(;;) + { + uschar *ccode; + int c; + int extra = 0; + + fprintf(f, "%3d ", code - codestart); + + if (*code >= OP_BRA) + { + if (*code - OP_BRA > EXTRACT_BASIC_MAX) + fprintf(f, "%3d Bra extra\n", GET(code, 1)); + else + fprintf(f, "%3d Bra %d\n", GET(code, 1), *code - OP_BRA); + code += OP_lengths[OP_BRA]; + continue; + } + + switch(*code) + { + case OP_END: + fprintf(f, " %s\n", OP_names[*code]); + fprintf(f, "------------------------------------------------------------------\n"); + return; + + case OP_OPT: + fprintf(f, " %.2x %s", code[1], OP_names[*code]); + break; + + case OP_CHARS: + { + int charlength = code[1]; + ccode = code + 2; + extra = charlength; + fprintf(f, "%3d ", charlength); + while (charlength > 0) + { + int extrabytes = print_char(f, ccode, utf8); + ccode += 1 + extrabytes; + charlength -= 1 + extrabytes; + } + } + break; + + case OP_KETRMAX: + case OP_KETRMIN: + case OP_ALT: + case OP_KET: + case OP_ASSERT: + case OP_ASSERT_NOT: + case OP_ASSERTBACK: + case OP_ASSERTBACK_NOT: + case OP_ONCE: + case OP_COND: + case OP_REVERSE: + fprintf(f, "%3d %s", GET(code, 1), OP_names[*code]); + break; + + case OP_BRANUMBER: + printf("%3d %s", GET2(code, 1), OP_names[*code]); + break; + + case OP_CREF: + if (GET2(code, 1) == CREF_RECURSE) + fprintf(f, " Cond recurse"); + else + fprintf(f, "%3d %s", GET2(code,1), OP_names[*code]); + break; + + case OP_STAR: + case OP_MINSTAR: + case OP_PLUS: + case OP_MINPLUS: + case OP_QUERY: + case OP_MINQUERY: + case OP_TYPESTAR: + case OP_TYPEMINSTAR: + case OP_TYPEPLUS: + case OP_TYPEMINPLUS: + case OP_TYPEQUERY: + case OP_TYPEMINQUERY: + fprintf(f, " "); + if (*code >= OP_TYPESTAR) fprintf(f, "%s", OP_names[code[1]]); + else extra = print_char(f, code+1, utf8); + fprintf(f, "%s", OP_names[*code]); + break; + + case OP_EXACT: + case OP_UPTO: + case OP_MINUPTO: + fprintf(f, " "); + extra = print_char(f, code+3, utf8); + fprintf(f, "{"); + if (*code != OP_EXACT) fprintf(f, ","); + fprintf(f, "%d}", GET2(code,1)); + if (*code == OP_MINUPTO) fprintf(f, "?"); + break; + + case OP_TYPEEXACT: + case OP_TYPEUPTO: + case OP_TYPEMINUPTO: + fprintf(f, " %s{", OP_names[code[3]]); + if (*code != OP_TYPEEXACT) fprintf(f, "0,"); + fprintf(f, "%d}", GET2(code,1)); + if (*code == OP_TYPEMINUPTO) fprintf(f, "?"); + break; + + case OP_NOT: + if (isprint(c = code[1])) fprintf(f, " [^%c]", c); + else fprintf(f, " [^\\x%02x]", c); + break; + + case OP_NOTSTAR: + case OP_NOTMINSTAR: + case OP_NOTPLUS: + case OP_NOTMINPLUS: + case OP_NOTQUERY: + case OP_NOTMINQUERY: + if (isprint(c = code[1])) fprintf(f, " [^%c]", c); + else fprintf(f, " [^\\x%02x]", c); + fprintf(f, "%s", OP_names[*code]); + break; + + case OP_NOTEXACT: + case OP_NOTUPTO: + case OP_NOTMINUPTO: + if (isprint(c = code[3])) fprintf(f, " [^%c]{", c); + else fprintf(f, " [^\\x%02x]{", c); + if (*code != OP_NOTEXACT) fprintf(f, ","); + fprintf(f, "%d}", GET2(code,1)); + if (*code == OP_NOTMINUPTO) fprintf(f, "?"); + break; + + case OP_RECURSE: + fprintf(f, "%3d %s", GET(code, 1), OP_names[*code]); + break; + + case OP_REF: + fprintf(f, " \\%d", GET2(code,1)); + ccode = code + OP_lengths[*code]; + goto CLASS_REF_REPEAT; + + case OP_CALLOUT: + fprintf(f, " %s %d", OP_names[*code], code[1]); + break; + + /* OP_XCLASS can only occur in UTF-8 mode. However, there's no harm in + having this code always here, and it makes it less messy without all those + #ifdefs. */ + + case OP_CLASS: + case OP_NCLASS: + case OP_XCLASS: + { + int i, min, max; + BOOL printmap; + + fprintf(f, " ["); + + if (*code == OP_XCLASS) + { + extra = GET(code, 1); + ccode = code + LINK_SIZE + 1; + printmap = (*ccode & XCL_MAP) != 0; + if ((*ccode++ & XCL_NOT) != 0) fprintf(f, "^"); + } + else + { + printmap = TRUE; + ccode = code + 1; + } + + /* Print a bit map */ + + if (printmap) + { + for (i = 0; i < 256; i++) + { + if ((ccode[i/8] & (1 << (i&7))) != 0) + { + int j; + for (j = i+1; j < 256; j++) + if ((ccode[j/8] & (1 << (j&7))) == 0) break; + if (i == '-' || i == ']') fprintf(f, "\\"); + if (isprint(i)) fprintf(f, "%c", i); else fprintf(f, "\\x%02x", i); + if (--j > i) + { + fprintf(f, "-"); + if (j == '-' || j == ']') fprintf(f, "\\"); + if (isprint(j)) fprintf(f, "%c", j); else fprintf(f, "\\x%02x", j); + } + i = j; + } + } + ccode += 32; + } + + /* For an XCLASS there is always some additional data */ + + if (*code == OP_XCLASS) + { + int ch; + while ((ch = *ccode++) != XCL_END) + { + ccode += 1 + print_char(f, ccode, TRUE); + if (ch == XCL_RANGE) + { + fprintf(f, "-"); + ccode += 1 + print_char(f, ccode, TRUE); + } + } + } + + /* Indicate a non-UTF8 class which was created by negation */ + + fprintf(f, "]%s", (*code == OP_NCLASS)? " (neg)" : ""); + + /* Handle repeats after a class or a back reference */ + + CLASS_REF_REPEAT: + switch(*ccode) + { + case OP_CRSTAR: + case OP_CRMINSTAR: + case OP_CRPLUS: + case OP_CRMINPLUS: + case OP_CRQUERY: + case OP_CRMINQUERY: + fprintf(f, "%s", OP_names[*ccode]); + extra = OP_lengths[*ccode]; + break; + + case OP_CRRANGE: + case OP_CRMINRANGE: + min = GET2(ccode,1); + max = GET2(ccode,3); + if (max == 0) fprintf(f, "{%d,}", min); + else fprintf(f, "{%d,%d}", min, max); + if (*ccode == OP_CRMINRANGE) fprintf(f, "?"); + extra = OP_lengths[*ccode]; + break; + } + } + break; + + /* Anything else is just an item with no data*/ + + default: + fprintf(f, " %s", OP_names[*code]); + break; + } + + code += OP_lengths[*code] + extra; + fprintf(f, "\n"); + } +} + +/* End of printint.c */ diff --git a/lc-continuity/mk4/continuity/pcre/study.c b/lc-continuity/mk4/continuity/pcre/study.c new file mode 100644 index 0000000000000000000000000000000000000000..4320bd23d072fe9161aff36e16cdafa06380f3f2 --- /dev/null +++ b/lc-continuity/mk4/continuity/pcre/study.c @@ -0,0 +1,438 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* +This is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. See +the file Tech.Notes for some information on the internals. + +Written by: Philip Hazel + + Copyright (c) 1997-2002 University of Cambridge + +----------------------------------------------------------------------------- +Permission is granted to anyone to use this software for any purpose on any +computer system, and to redistribute it freely, subject to the following +restrictions: + +1. This software 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. + +2. The origin of this software must not be misrepresented, either by + explicit claim or by omission. + +3. Altered versions must be plainly marked as such, and must not be + misrepresented as being the original software. + +4. If PCRE is embedded in any software that is released under the GNU + General Purpose Licence (GPL), then the terms of that licence shall + supersede any condition above with which it is incompatible. +----------------------------------------------------------------------------- +*/ + + +/* Include the internals header, which itself includes Standard C headers plus +the external pcre header. */ + +#include "internal.h" + + + +/************************************************* +* Set a bit and maybe its alternate case * +*************************************************/ + +/* Given a character, set its bit in the table, and also the bit for the other +version of a letter if we are caseless. + +Arguments: + start_bits points to the bit map + c is the character + caseless the caseless flag + cd the block with char table pointers + +Returns: nothing +*/ + +static void +set_bit(uschar *start_bits, int c, BOOL caseless, compile_data *cd) +{ +start_bits[c/8] |= (1 << (c&7)); +if (caseless && (cd->ctypes[c] & ctype_letter) != 0) + start_bits[cd->fcc[c]/8] |= (1 << (cd->fcc[c]&7)); +} + + + +/************************************************* +* Create bitmap of starting chars * +*************************************************/ + +/* This function scans a compiled unanchored expression and attempts to build a +bitmap of the set of initial characters. If it can't, it returns FALSE. As time +goes by, we may be able to get more clever at doing this. + +Arguments: + code points to an expression + start_bits points to a 32-byte table, initialized to 0 + caseless the current state of the caseless flag + utf8 TRUE if in UTF-8 mode + cd the block with char table pointers + +Returns: TRUE if table built, FALSE otherwise +*/ + +static BOOL +set_start_bits(const uschar *code, uschar *start_bits, BOOL caseless, + BOOL utf8, compile_data *cd) +{ +register int c; + +/* This next statement and the later reference to dummy are here in order to +trick the optimizer of the IBM C compiler for OS/2 into generating correct +code. Apparently IBM isn't going to fix the problem, and we would rather not +disable optimization (in this module it actually makes a big difference, and +the pcre module can use all the optimization it can get). */ + +volatile int dummy; + +do + { + const uschar *tcode = code + 1 + LINK_SIZE; + BOOL try_next = TRUE; + + while (try_next) + { + /* If a branch starts with a bracket or a positive lookahead assertion, + recurse to set bits from within them. That's all for this branch. */ + + if ((int)*tcode >= OP_BRA || *tcode == OP_ASSERT) + { + if (!set_start_bits(tcode, start_bits, caseless, utf8, cd)) + return FALSE; + try_next = FALSE; + } + + else switch(*tcode) + { + default: + return FALSE; + + /* Skip over callout */ + + case OP_CALLOUT: + tcode += 2; + break; + + /* Skip over extended extraction bracket number */ + + case OP_BRANUMBER: + tcode += 3; + break; + + /* Skip over lookbehind and negative lookahead assertions */ + + case OP_ASSERT_NOT: + case OP_ASSERTBACK: + case OP_ASSERTBACK_NOT: + do tcode += GET(tcode, 1); while (*tcode == OP_ALT); + tcode += 1+LINK_SIZE; + break; + + /* Skip over an option setting, changing the caseless flag */ + + case OP_OPT: + caseless = (tcode[1] & PCRE_CASELESS) != 0; + tcode += 2; + break; + + /* BRAZERO does the bracket, but carries on. */ + + case OP_BRAZERO: + case OP_BRAMINZERO: + if (!set_start_bits(++tcode, start_bits, caseless, utf8, cd)) + return FALSE; + dummy = 1; + do tcode += GET(tcode,1); while (*tcode == OP_ALT); + tcode += 1+LINK_SIZE; + break; + + /* Single-char * or ? sets the bit and tries the next item */ + + case OP_STAR: + case OP_MINSTAR: + case OP_QUERY: + case OP_MINQUERY: + set_bit(start_bits, tcode[1], caseless, cd); + tcode += 2; +#ifdef SUPPORT_UTF8 + if (utf8) while ((*tcode & 0xc0) == 0x80) tcode++; +#endif + break; + + /* Single-char upto sets the bit and tries the next */ + + case OP_UPTO: + case OP_MINUPTO: + set_bit(start_bits, tcode[3], caseless, cd); + tcode += 4; +#ifdef SUPPORT_UTF8 + if (utf8) while ((*tcode & 0xc0) == 0x80) tcode++; +#endif + break; + + /* At least one single char sets the bit and stops */ + + case OP_EXACT: /* Fall through */ + tcode++; + + case OP_CHARS: /* Fall through */ + tcode++; + + case OP_PLUS: + case OP_MINPLUS: + set_bit(start_bits, tcode[1], caseless, cd); + try_next = FALSE; + break; + + /* Single character type sets the bits and stops */ + + case OP_NOT_DIGIT: + for (c = 0; c < 32; c++) + start_bits[c] |= ~cd->cbits[c+cbit_digit]; + try_next = FALSE; + break; + + case OP_DIGIT: + for (c = 0; c < 32; c++) + start_bits[c] |= cd->cbits[c+cbit_digit]; + try_next = FALSE; + break; + + case OP_NOT_WHITESPACE: + for (c = 0; c < 32; c++) + start_bits[c] |= ~cd->cbits[c+cbit_space]; + try_next = FALSE; + break; + + case OP_WHITESPACE: + for (c = 0; c < 32; c++) + start_bits[c] |= cd->cbits[c+cbit_space]; + try_next = FALSE; + break; + + case OP_NOT_WORDCHAR: + for (c = 0; c < 32; c++) + start_bits[c] |= ~cd->cbits[c+cbit_word]; + try_next = FALSE; + break; + + case OP_WORDCHAR: + for (c = 0; c < 32; c++) + start_bits[c] |= cd->cbits[c+cbit_word]; + try_next = FALSE; + break; + + /* One or more character type fudges the pointer and restarts, knowing + it will hit a single character type and stop there. */ + + case OP_TYPEPLUS: + case OP_TYPEMINPLUS: + tcode++; + break; + + case OP_TYPEEXACT: + tcode += 3; + break; + + /* Zero or more repeats of character types set the bits and then + try again. */ + + case OP_TYPEUPTO: + case OP_TYPEMINUPTO: + tcode += 2; /* Fall through */ + + case OP_TYPESTAR: + case OP_TYPEMINSTAR: + case OP_TYPEQUERY: + case OP_TYPEMINQUERY: + switch(tcode[1]) + { + case OP_NOT_DIGIT: + for (c = 0; c < 32; c++) + start_bits[c] |= ~cd->cbits[c+cbit_digit]; + break; + + case OP_DIGIT: + for (c = 0; c < 32; c++) + start_bits[c] |= cd->cbits[c+cbit_digit]; + break; + + case OP_NOT_WHITESPACE: + for (c = 0; c < 32; c++) + start_bits[c] |= ~cd->cbits[c+cbit_space]; + break; + + case OP_WHITESPACE: + for (c = 0; c < 32; c++) + start_bits[c] |= cd->cbits[c+cbit_space]; + break; + + case OP_NOT_WORDCHAR: + for (c = 0; c < 32; c++) + start_bits[c] |= ~cd->cbits[c+cbit_word]; + break; + + case OP_WORDCHAR: + for (c = 0; c < 32; c++) + start_bits[c] |= cd->cbits[c+cbit_word]; + break; + } + + tcode += 2; + break; + + /* Character class where all the information is in a bit map: set the + bits and either carry on or not, according to the repeat count. If it was + a negative class, and we are operating with UTF-8 characters, any byte + with the top-bit set is a potentially valid starter because it may start + a character with a value > 255. (This is sub-optimal in that the + character may be in the range 128-255, and those characters might be + unwanted, but that's as far as we go for the moment.) */ + + case OP_NCLASS: + if (utf8) memset(start_bits+16, 0xff, 16); + /* Fall through */ + + case OP_CLASS: + { + tcode++; + for (c = 0; c < 32; c++) start_bits[c] |= tcode[c]; + tcode += 32; + switch (*tcode) + { + case OP_CRSTAR: + case OP_CRMINSTAR: + case OP_CRQUERY: + case OP_CRMINQUERY: + tcode++; + break; + + case OP_CRRANGE: + case OP_CRMINRANGE: + if (((tcode[1] << 8) + tcode[2]) == 0) tcode += 5; + else try_next = FALSE; + break; + + default: + try_next = FALSE; + break; + } + } + break; /* End of bitmap class handling */ + + } /* End of switch */ + } /* End of try_next loop */ + + code += GET(code, 1); /* Advance to next branch */ + } +while (*code == OP_ALT); +return TRUE; +} + + + +/************************************************* +* Study a compiled expression * +*************************************************/ + +/* This function is handed a compiled expression that it must study to produce +information that will speed up the matching. It returns a pcre_extra block +which then gets handed back to pcre_exec(). + +Arguments: + re points to the compiled expression + options contains option bits + errorptr points to where to place error messages; + set NULL unless error + +Returns: pointer to a pcre_extra block, with study_data filled in and the + appropriate flag set; + NULL on error or if no optimization possible +*/ + +pcre_extra * +pcre_study(const pcre *external_re, int options, const char **errorptr) +{ +uschar start_bits[32]; +pcre_extra *extra; +pcre_study_data *study; +const real_pcre *re = (const real_pcre *)external_re; +uschar *code = (uschar *)re + sizeof(real_pcre) + + (re->name_count * re->name_entry_size); +compile_data compile_block; + +*errorptr = NULL; + +if (re == NULL || re->magic_number != MAGIC_NUMBER) + { + *errorptr = "argument is not a compiled regular expression"; + return NULL; + } + +if ((options & ~PUBLIC_STUDY_OPTIONS) != 0) + { + *errorptr = "unknown or incorrect option bit(s) set"; + return NULL; + } + +/* For an anchored pattern, or an unanchored pattern that has a first char, or +a multiline pattern that matches only at "line starts", no further processing +at present. */ + +if ((re->options & (PCRE_ANCHORED|PCRE_FIRSTSET|PCRE_STARTLINE)) != 0) + return NULL; + +/* Set the character tables in the block which is passed around */ + +compile_block.lcc = re->tables + lcc_offset; +compile_block.fcc = re->tables + fcc_offset; +compile_block.cbits = re->tables + cbits_offset; +compile_block.ctypes = re->tables + ctypes_offset; + +/* See if we can find a fixed set of initial characters for the pattern. */ + +memset(start_bits, 0, 32 * sizeof(uschar)); +if (!set_start_bits(code, start_bits, (re->options & PCRE_CASELESS) != 0, + (re->options & PCRE_UTF8) != 0, &compile_block)) return NULL; + +/* Get a pcre_extra block and a pcre_study_data block. The study data is put in +the latter, which is pointed to by the former, which may also get additional +data set later by the calling program. At the moment, the size of +pcre_study_data is fixed. We nevertheless save it in a field for returning via +the pcre_fullinfo() function so that if it becomes variable in the future, we +don't have to change that code. */ + +extra = (pcre_extra *)(pcre_malloc) + (sizeof(pcre_extra) + sizeof(pcre_study_data)); + +if (extra == NULL) + { + *errorptr = "failed to get memory"; + return NULL; + } + +study = (pcre_study_data *)((char *)extra + sizeof(pcre_extra)); +extra->flags = PCRE_EXTRA_STUDY_DATA; +extra->study_data = study; + +study->size = sizeof(pcre_study_data); +study->options = PCRE_STUDY_MAPPED; +memcpy(study->start_bits, start_bits, sizeof(start_bits)); + +return extra; +} + +/* End of study.c */ diff --git a/lc-continuity/mk4/continuity/todoc b/lc-continuity/mk4/continuity/todoc new file mode 100644 index 0000000000000000000000000000000000000000..a85010f155b75727cae3d37f5c8e66b23a81e176 --- /dev/null +++ b/lc-continuity/mk4/continuity/todoc @@ -0,0 +1,48 @@ +void httpFset_state (httpTtrans *t, int state); + +int httpFset_nph (httpTtrans *t); + +phpF* + +int siteFsite_data_set(const char *siteid, const char *name, void *data); +void *siteFsite_data_get(const char *siteid, const char *name); + +int hshFvoid_size(hshTvoid_list * list); + +void hshFvoid_int_replace(hshTvoid_list * list, const int key, void *data); +void hshFvoid_replace(hshTvoid_list * list, const char *name, void *data); + +/* remove but not destroy/deallocate */ +void *hshFvoid_remove(hshTvoid_list * list, const char *name); +void *hshFvoid_int_remove(hshTvoid_list * list, int key); +void *hshFvoid_raw_remove(hshTvoid_list * list, const char *name, size_t name_len); + +void logFoutputfh_set(FILE *fh, int close); +FILE *logFoutputfh_get(void); +void fleFrotate(int count, const char *fn) + +conFget_config -> conFget_config_basetag + +hshFvoid_destroy -> hshFvoid_free + +hsh replace functions -> update + +void hshFvalue_destructor_set(hshTvoid_list *list, void (*destructor)(void *)) + +void dicFuserdata_destructor_set(dicTdictionary *d, void (*destructor)(void *)) +void *dicFuserdata_find(dicTdictionary *d, int idx) +void dicFuserdata_update(dicTdictionary *d, int idx, void *data) + +unsigned int utlFatoui(const char *s) +int utlFatoi(const char *s) + +int sysFfs_info(lstTset * set); +int sysFnet_usage(uint32_t *obytes, uint32_t *ibytes, + uint32_t *opkts, uint32_t *ipkts) + + +const char *xmlFfirst_child_value_str (const xmlTtag *tag, const char *name); + +const xmlTtag *siteFget_config_by_siteid (const char *siteid); +static void utlFhexdump(void *data, size_t size) + diff --git a/lc-continuity/mk4/doc/CVS/Entries b/lc-continuity/mk4/doc/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..9a22b00e51393b06a5ab6f511245dbbcef12da98 --- /dev/null +++ b/lc-continuity/mk4/doc/CVS/Entries @@ -0,0 +1,2 @@ +/standards.txt/1.3/Wed Mar 31 19:59:51 2004//Tmk4_mod6_rc2 +D diff --git a/lc-continuity/mk4/doc/CVS/Repository b/lc-continuity/mk4/doc/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..ee97d929427a4dc2cbae22fc175ca1501fafc573 --- /dev/null +++ b/lc-continuity/mk4/doc/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/doc diff --git a/lc-continuity/mk4/doc/CVS/Root b/lc-continuity/mk4/doc/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/doc/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/doc/CVS/Tag b/lc-continuity/mk4/doc/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/doc/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/doc/standards.txt b/lc-continuity/mk4/doc/standards.txt new file mode 100644 index 0000000000000000000000000000000000000000..937f0ba93c173dce89a6d4bde83f345f5e50737c --- /dev/null +++ b/lc-continuity/mk4/doc/standards.txt @@ -0,0 +1,77 @@ +$Header: /san01/cvs/ashpool/csrc/doc/Attic/standards.txt,v 1.3 2004/03/31 19:59:51 aleigh Exp $ + +-= API & Code Terms =- + +This is an attempt to create a small glossary of "approved" terms, +mostly for use when naming function calls and objects. There has been +some drift over the months and even within my own code I use confusing +or inconsistent nomenclature. + +The following are "approved" terms which should be use exclusively; +for example "create" should not be used in lieu of "init". + +init: Create / Allocate a thing + +free: Destroy / De-Allocate a thing + +add: Exclusivly add a thing to storage thing. +Only add if the thing was not already in the storage +thing unless the storage thing does not enforce +uniqueness. + +replace: Replace one thing with another. Do not +add the thing if it was not already there. + +update: Add/Replace the value of a thing in +a container. + +delete: Delete a thing and destroy it. + +remove: Remove a thing but return it instead of +destroying it. + +find: Lookup a thing, search for a thing, get a specific thing. + +-= Source Code =- + +4 space tabs. Do not use the tab character. + +One-True Brace Style. + +No implicit blocks: + + if (a==1) { + return 1; + } + +instead of + + if(a==1) + return 1; + +No implicit conditionals: + + if(a==0) + +instead of + + if(!a); + +-= Return Status =- + +Functions may have one of several return profiles depending on +their individual function. + +Standard Boolean: +-1 Error + 0 success + +Standard State: +-1 Error + 0 did nothing + 1 did something + +Standard I/O: +-1 Error + n bytes read/written + diff --git a/lc-continuity/mk4/httpclient/CVS/Entries b/lc-continuity/mk4/httpclient/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..9af8591e431f42d2cdc9b51772de6941884c11dd --- /dev/null +++ b/lc-continuity/mk4/httpclient/CVS/Entries @@ -0,0 +1,3 @@ +/Makefile/1.1/Thu May 27 13:50:58 2004//Tmk4_mod6_rc2 +/httpclient.c/1.4/Tue Jun 1 12:55:59 2004//Tmk4_mod6_rc2 +D diff --git a/lc-continuity/mk4/httpclient/CVS/Repository b/lc-continuity/mk4/httpclient/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..d5405ae0279e7ae6365d5fee8d680c673408f3c2 --- /dev/null +++ b/lc-continuity/mk4/httpclient/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/httpclient diff --git a/lc-continuity/mk4/httpclient/CVS/Root b/lc-continuity/mk4/httpclient/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/httpclient/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/httpclient/CVS/Tag b/lc-continuity/mk4/httpclient/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/httpclient/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/httpclient/Makefile b/lc-continuity/mk4/httpclient/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..5af45971a0821ad4acc080e02c58a994bda88b47 --- /dev/null +++ b/lc-continuity/mk4/httpclient/Makefile @@ -0,0 +1,11 @@ +include ../continuity/lib/env.mk + +SRCS=httpclient.c +OBJS=httpclient.o + +CFLAGS+=-I../continuity/include + +httpclient: $(OBJS) + $(CC) httpclient.o ../continuity/lib/mechanism.a -o httpclient $(LIBS) +clean: + $(RM) $(OBJS) httpclient diff --git a/lc-continuity/mk4/httpclient/httpclient.c b/lc-continuity/mk4/httpclient/httpclient.c new file mode 100644 index 0000000000000000000000000000000000000000..da5fd46221b13772e66ac1436b5f16eda618b0c8 --- /dev/null +++ b/lc-continuity/mk4/httpclient/httpclient.c @@ -0,0 +1,115 @@ +#include + +int request(const char *uri, const char *hostname, const char *port, const char *host_tuple) { + int sd; + netTconn *conn; + netTreader *reader; + char buf[1024]; + + logFmsg(3,"Connecting to %s:%s for %s", hostname, port, uri); + + + sd=netFtcp_connect(hostname,atoi(port)); + + if(sd<0) { + logFmsg(2,"Connect failed: e: %d", errno); + return -1; + } + + conn=netFconn_make(sd); + + assert(conn!=NULL); + + if(host_tuple!=NULL) { + netFconn_writef(conn,"GET %s HTTP/1.0\r\nHost: %s\r\nUser-agent: Continuity httpclient\r\n\r\n", + uri, host_tuple); + } else { + netFconn_writef(conn,"GET %s HTTP/1.0\r\nUser-agent: Continuity httpclient\r\n\r\n", + uri); + } + reader=netFreader_init(); + + assert(reader!=NULL); + + while(netFconn_read(conn,reader,buf,sizeof(buf))>0) { + printf("%s", buf); + } + fflush(stdout); + + netFreader_free(reader); + netFconn_close(conn); + netFconn_free(conn); +} + +int main(int argc, char **argv) { + + mecha_init(); + + logFmsg(0,"httpclient v1.00"); + logFmsg(0,"Copyright (c) 2004, Alex Leigh"); + + extern char *optarg; + int ret; + int u=0, p=0, s=0, h=0; + char *u_arg=NULL, *p_arg=NULL, *s_arg=NULL, *h_arg=NULL; + int err=0; + + while((ret=getopt(argc, argv, "u:p:s:h:"))!=EOF) { + switch(ret) { + case 'u': + if(u==1) { + err++; + } else { + u++; + } + u_arg=optarg; + break; + case 'p': + if(p==1) { + err++; + } else { + p++; + } + p_arg=optarg; + break; + case 's': + if(s==1) { + err++; + } else { + s++; + } + s_arg=optarg; + break; + case 'h': + if(h==1) { + err++; + } else { + h++; + } + h_arg=optarg; + break; + default: + err++; + } + } + + if(s==0 || p==0 || u==0) { + err++; + } + + if(s_arg==NULL || p_arg==NULL || u_arg==NULL) { + err++; + } + + if(err>0) { + printf("Usage: httpclient -s server -p port -u uri [-h http_host]\n"); + exit(0); + } + + request(u_arg, s_arg, p_arg, h_arg); + + exit(0); +} + + + diff --git a/lc-continuity/mk4/install-sh b/lc-continuity/mk4/install-sh new file mode 100644 index 0000000000000000000000000000000000000000..e9de23842dcd44d2953129c866b1ad25f7e1f1d9 --- /dev/null +++ b/lc-continuity/mk4/install-sh @@ -0,0 +1,251 @@ +#!/bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5 (mit/util/scripts/install.sh). +# +# Copyright 1991 by the Massachusetts Institute of Technology +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation, and that the name of M.I.T. not be used in advertising or +# publicity pertaining to distribution of the software without specific, +# written prior permission. M.I.T. makes no representations about the +# suitability of this software for any purpose. It is provided "as is" +# without express or implied warranty. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +transformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +else + true +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d $dst ]; then + instcmd=: + chmodcmd="" + else + instcmd=mkdir + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f $src -o -d $src ] + then + true + else + echo "install: $src does not exist" + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "install: no destination specified" + exit 1 + else + true + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d $dst ] + then + dst="$dst"/`basename $src` + else + true + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' +' +IFS="${IFS-${defaultIFS}}" + +oIFS="${IFS}" +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS="${oIFS}" + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp="${pathcomp}${1}" + shift + + if [ ! -d "${pathcomp}" ] ; + then + $mkdirprog "${pathcomp}" + else + true + fi + + pathcomp="${pathcomp}/" +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd $dst && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename $dst` + else + dstfile=`basename $dst $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename $dst` + else + true + fi + +# Make a temp file name in the proper directory. + + dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + + $doit $instcmd $src $dsttmp && + + trap "rm -f ${dsttmp}" 0 && + +# and set any options; do chmod last to preserve setuid bits + +# If any of these fail, we abort the whole thing. If we want to +# ignore errors from any of these, just make sure not to ignore +# errors from the above "$doit $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && + +# Now rename the file to the real destination. + + $doit $rmcmd -f $dstdir/$dstfile && + $doit $mvcmd $dsttmp $dstdir/$dstfile + +fi && + + +exit 0 diff --git a/lc-continuity/mk4/lib/CVS/Entries b/lc-continuity/mk4/lib/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..05d73291ff0e6c7b8fb4ff45e02138684ed48583 --- /dev/null +++ b/lc-continuity/mk4/lib/CVS/Entries @@ -0,0 +1,3 @@ +D/aura//// +D/causality//// +D/causality-client//// diff --git a/lc-continuity/mk4/lib/CVS/Repository b/lc-continuity/mk4/lib/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..65dbf85a62c8859185e660e14d75c723c21fd269 --- /dev/null +++ b/lc-continuity/mk4/lib/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/lib diff --git a/lc-continuity/mk4/lib/CVS/Root b/lc-continuity/mk4/lib/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/lib/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/lib/CVS/Tag b/lc-continuity/mk4/lib/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..3677f37e4f0eee70c8ee8cab24c43155060ef7d0 --- /dev/null +++ b/lc-continuity/mk4/lib/CVS/Tag @@ -0,0 +1 @@ +Tmk4_mod6_rc2 diff --git a/lc-continuity/mk4/lib/aura/CVS/Entries b/lc-continuity/mk4/lib/aura/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..ecabe183b4fe290791023bb0c97ab938f40294cc --- /dev/null +++ b/lc-continuity/mk4/lib/aura/CVS/Entries @@ -0,0 +1,4 @@ +/Makefile/1.4/Thu May 13 07:48:44 2004//Tmk4_mod6_rc2 +D/include//// +D/scripts//// +D/src//// diff --git a/lc-continuity/mk4/lib/aura/CVS/Repository b/lc-continuity/mk4/lib/aura/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..34f8ab2a058b0c453a55834cb77ab5f311049359 --- /dev/null +++ b/lc-continuity/mk4/lib/aura/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/lib/aura diff --git a/lc-continuity/mk4/lib/aura/CVS/Root b/lc-continuity/mk4/lib/aura/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/lib/aura/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/lib/aura/CVS/Tag b/lc-continuity/mk4/lib/aura/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/lib/aura/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/lib/aura/Makefile b/lc-continuity/mk4/lib/aura/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..4533a2598e320d6488d7b4fad6019f50ecf2583a --- /dev/null +++ b/lc-continuity/mk4/lib/aura/Makefile @@ -0,0 +1,12 @@ +CONTINUITY = ../../continuity + +TARGET = aura +TARGETTYPE = shared static + +SOURCES = src/serialization.c src/typelocator.c src/basictypes.c \ + src/serializationinfo.c src/iterator.c src/memutil.c \ + src/stringdictionary.c src/list_iterator.c + +INCLUDES += -Iinclude + +include $(CONTINUITY)/lib/build.mk diff --git a/lc-continuity/mk4/lib/aura/include/CVS/Entries b/lc-continuity/mk4/lib/aura/include/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..a3adbf8d0bad70b7f667aed60ce43e7a7e76fe7a --- /dev/null +++ b/lc-continuity/mk4/lib/aura/include/CVS/Entries @@ -0,0 +1,10 @@ +/basictypes.h/1.1/Wed Apr 28 06:12:24 2004//Tmk4_mod6_rc2 +/iterator.h/1.5/Thu May 13 00:04:41 2004//Tmk4_mod6_rc2 +/list_iterator.h/1.1/Wed Apr 28 07:07:20 2004//Tmk4_mod6_rc2 +/memutil.h/1.1/Wed Apr 28 06:12:24 2004//Tmk4_mod6_rc2 +/serialization.h/1.2/Fri Apr 30 19:14:07 2004//Tmk4_mod6_rc2 +/serializationinfo.h/1.1/Wed Apr 28 06:12:24 2004//Tmk4_mod6_rc2 +/stringdictionary.h/1.3/Fri May 14 06:20:32 2004//Tmk4_mod6_rc2 +/type.h/1.3/Fri May 14 06:20:32 2004//Tmk4_mod6_rc2 +/typelocator.h/1.1/Wed Apr 28 06:12:24 2004//Tmk4_mod6_rc2 +D diff --git a/lc-continuity/mk4/lib/aura/include/CVS/Repository b/lc-continuity/mk4/lib/aura/include/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..0bb85ebafc6ee16adee48cc63504816f00346223 --- /dev/null +++ b/lc-continuity/mk4/lib/aura/include/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/lib/aura/include diff --git a/lc-continuity/mk4/lib/aura/include/CVS/Root b/lc-continuity/mk4/lib/aura/include/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/lib/aura/include/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/lib/aura/include/CVS/Tag b/lc-continuity/mk4/lib/aura/include/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/lib/aura/include/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/lib/aura/include/basictypes.h b/lc-continuity/mk4/lib/aura/include/basictypes.h new file mode 100644 index 0000000000000000000000000000000000000000..a2b4df4f5a059846934d7847b07ecb7ccb93fa5a --- /dev/null +++ b/lc-continuity/mk4/lib/aura/include/basictypes.h @@ -0,0 +1,10 @@ +#ifndef __BASICTYPES_H_ +#define __BASICTYPES_H_ + +bool basictypes_serializeInt (void *field, SerializationInfo *info); +bool basictypes_deserializeInt (void *field, SerializationInfo *info); + +bool basictypes_serializeString (void *field, SerializationInfo *info); +bool basictypes_deserializeString (void *field, SerializationInfo *serializerData); + +#endif diff --git a/lc-continuity/mk4/lib/aura/include/iterator.h b/lc-continuity/mk4/lib/aura/include/iterator.h new file mode 100644 index 0000000000000000000000000000000000000000..9253804b6df4607ed3de59c97db9948c4b6b0728 --- /dev/null +++ b/lc-continuity/mk4/lib/aura/include/iterator.h @@ -0,0 +1,35 @@ +#ifndef __ITERATOR_H_ +#define __ITERATOR_H_ + +enum e_IteratorStatus +{ + IteratorSuccess, + IteratorEnd, + IteratorOutOfSync +}; + +typedef struct s_IIterator IIterator; + +typedef struct s_Iterator Iterator; +typedef enum e_IteratorStatus IteratorStatus; + +struct s_IIterator +{ + IteratorStatus (*next) (IIterator *); + void * (*get_value) (IIterator *); + void (*destroy) (IIterator *); +}; + +typedef IteratorStatus (*IteratorNextDelegate)(void *data); +typedef void *(*IteratorValueDelegate)(void *data); +typedef void (*IteratorDestroyDelegate)(void *data); + +Iterator * iterator_new (void *data, IteratorNextDelegate next, + IteratorValueDelegate value, IteratorDestroyDelegate destroy); + +IteratorStatus iterator_next (Iterator *iter); +void * iterator_value (Iterator *iter); +void iterator_destroy (void *ptr); + + +#endif diff --git a/lc-continuity/mk4/lib/aura/include/list_iterator.h b/lc-continuity/mk4/lib/aura/include/list_iterator.h new file mode 100644 index 0000000000000000000000000000000000000000..6d6360a8cdcbcc190a26b9a932523ece69acfd48 --- /dev/null +++ b/lc-continuity/mk4/lib/aura/include/list_iterator.h @@ -0,0 +1,10 @@ + +#ifndef __LIST_ITERATOR_H__ +#define __LIST_ITERATOR_H__ + +typedef struct s_ListIterator ListIterator; + +ListIterator * list_iterator_new (lstTlist *list); +void list_iterator_destroy (IIterator *ptr); + +#endif diff --git a/lc-continuity/mk4/lib/aura/include/memutil.h b/lc-continuity/mk4/lib/aura/include/memutil.h new file mode 100644 index 0000000000000000000000000000000000000000..fad605d410fd7788239139b76716f07ae338c2c6 --- /dev/null +++ b/lc-continuity/mk4/lib/aura/include/memutil.h @@ -0,0 +1,8 @@ +#ifndef __MEMUTIL_H_ +#define __MEMUTIL_H_ + +void memutil_printMemAllocated (void); + +int memutil_getMemAllocated (void); + +#endif diff --git a/lc-continuity/mk4/lib/aura/include/serialization.h b/lc-continuity/mk4/lib/aura/include/serialization.h new file mode 100644 index 0000000000000000000000000000000000000000..54e83daa3b0b1bf3da34b48b6c4d7c05c725b0fb --- /dev/null +++ b/lc-continuity/mk4/lib/aura/include/serialization.h @@ -0,0 +1,30 @@ +#ifndef __SERIALIZATION_H_ +#define __SERIALIZATION_H_ + +#include + +#include "type.h" +#include "serializationinfo.h" +#include "iterator.h" + + +dynTstring * serialization_serializeType (const char *typeName, void *field); +bool serialization_deserializeType (const char *typeName, void *field, dynTstring *serializationData); + +dynTstring * serialization_serialize (SerializationInfo *info); +SerializationInfo * serialization_deserialize (dynTstring *string); + +dynTstring * serialization_serializeList (lstTlist *list); +lstTlist * serialization_deserializeList (dynTstring *string); + + +// -aleigh +//typedef __typeof__ (void (*) (void *context, void *element)) DeserializationCallback; + +typedef void *(*DeserializationCallback)(void *context, void *element); + +dynTstring * serialization_serializeTypeList (const char *typeName, Iterator *iterator); +bool serialization_deserializeTypeList (const char *typeName, dynTstring *serializationData, + DeserializationCallback callback, void *context); + +#endif diff --git a/lc-continuity/mk4/lib/aura/include/serializationinfo.h b/lc-continuity/mk4/lib/aura/include/serializationinfo.h new file mode 100644 index 0000000000000000000000000000000000000000..febc0ba8fa3063ef3d7e2255a8fa78bed15fe44f --- /dev/null +++ b/lc-continuity/mk4/lib/aura/include/serializationinfo.h @@ -0,0 +1,18 @@ +#ifndef __SERIALIZATIONINFO_H_ +#define __SERIALIZATIONINFO_H_ + +#include + +typedef struct s_SerializationInfo SerializationInfo; + +SerializationInfo *serializationinfo_new (void); +void serializationinfo_addValue (SerializationInfo *info, const char *key, dynTstring *value); +dynTstring * serializationinfo_getValue (SerializationInfo *info, const char *key); +void serializationinfo_destroy (void *ptr); + +void serializationinfo_addValueData (SerializationInfo *info, const char *key, int keyLen, dynTstring *value); + +hshTiterator * serializationinfo_getIterator (SerializationInfo *info); +void serializationinfo_destroyIterator (hshTiterator *iter); + +#endif diff --git a/lc-continuity/mk4/lib/aura/include/stringdictionary.h b/lc-continuity/mk4/lib/aura/include/stringdictionary.h new file mode 100644 index 0000000000000000000000000000000000000000..8fbe89836e6e2b81c22915fd9e33ce80e63697e5 --- /dev/null +++ b/lc-continuity/mk4/lib/aura/include/stringdictionary.h @@ -0,0 +1,18 @@ +#ifndef __STRINGDICTIONARY_H_ +#define __STRINGDICTIONARY_H_ + +#include "mecha.h" + +typedef struct s_StringDictionary StringDictionary; + +StringDictionary * stringdictionary_new (void); +void stringdictionary_destroy (void *ptr); + +void stringdictionary_setValue (StringDictionary *info, const char *key, dynTstring *value); +bool stringdictionary_addValue (StringDictionary *info, const char *key, dynTstring *value); + +dynTstring * stringdictionary_getValue (StringDictionary *info, const char *key); + +hshTiterator * stringdictionary_getIterator (StringDictionary *dict); + +#endif diff --git a/lc-continuity/mk4/lib/aura/include/type.h b/lc-continuity/mk4/lib/aura/include/type.h new file mode 100644 index 0000000000000000000000000000000000000000..1d4e269c6cc93aed3f6abe906f6a9a1d6a104471 --- /dev/null +++ b/lc-continuity/mk4/lib/aura/include/type.h @@ -0,0 +1,26 @@ +#ifndef __TYPE_H__ +#define __TYPE_H__ + +#include "mecha.h" + +#include "serializationinfo.h" + +#define DEREFERENCE_TYPE(__type,__y) ((__type *) *((__type **) __y)) + +// -aleigh +// typedef __typeof__ (bool (*) (void *, SerializationInfo *)) SerializeDelegate; +// typedef __typeof__ (bool (*) (void *, SerializationInfo *)) DeserializeDelegate; + +typedef bool (*SerializeDelegate)(void *, SerializationInfo *); +typedef bool (*DeserializeDelegate)(void *, SerializationInfo *); + +typedef struct s_Type Type; + +struct s_Type +{ + const char *name; + SerializeDelegate serialize; + DeserializeDelegate deserialize; +}; + +#endif diff --git a/lc-continuity/mk4/lib/aura/include/typelocator.h b/lc-continuity/mk4/lib/aura/include/typelocator.h new file mode 100644 index 0000000000000000000000000000000000000000..073a27d085a382a3b516f1dba049527eaf8c8faf --- /dev/null +++ b/lc-continuity/mk4/lib/aura/include/typelocator.h @@ -0,0 +1,10 @@ +#ifndef __TYPELOCATOR_H__ +#define __TYPELOCATOR_H__ + +typedef struct s_TypeLocator TypeLocator; + +TypeLocator *typelocator_new (void); +TypeLocator *typelocator_getLocator (void); +Type * typelocator_getType (TypeLocator *locator, const char *typeName); + +#endif diff --git a/lc-continuity/mk4/lib/aura/scripts/CVS/Entries b/lc-continuity/mk4/lib/aura/scripts/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..892b284c01eecd07d80f457a368e67e0eb802a87 --- /dev/null +++ b/lc-continuity/mk4/lib/aura/scripts/CVS/Entries @@ -0,0 +1,2 @@ +/create_aura_class.pl/1.1/Wed Apr 28 06:12:24 2004//Tmk4_mod6_rc2 +D diff --git a/lc-continuity/mk4/lib/aura/scripts/CVS/Repository b/lc-continuity/mk4/lib/aura/scripts/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..c11067b381616f3eca321f035f4e0fec6fe30000 --- /dev/null +++ b/lc-continuity/mk4/lib/aura/scripts/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/lib/aura/scripts diff --git a/lc-continuity/mk4/lib/aura/scripts/CVS/Root b/lc-continuity/mk4/lib/aura/scripts/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/lib/aura/scripts/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/lib/aura/scripts/CVS/Tag b/lc-continuity/mk4/lib/aura/scripts/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/lib/aura/scripts/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/lib/aura/scripts/create_aura_class.pl b/lc-continuity/mk4/lib/aura/scripts/create_aura_class.pl new file mode 100644 index 0000000000000000000000000000000000000000..cca88750b4c86df3a60c26c5c97c4ad2f5dcb7c5 --- /dev/null +++ b/lc-continuity/mk4/lib/aura/scripts/create_aura_class.pl @@ -0,0 +1,138 @@ +#!/usr/bin/env perl + +use strict; +use warnings; +use File::Basename; + +my $source_data = q| +#include + +#include "%CLASS_AS_PREFIX%.h" + +struct s_%CLASS% +{ + /* insert fields here */ +}; + +%CLASS% * +%CLASS_AS_PREFIX%_new (void) +{ + %CLASS% *instance = (%CLASS% *) malloc (sizeof (%CLASS%)); + + /* initialize other fields */ + + return (instance); +} + +void +%CLASS_AS_PREFIX%_destroy (void *ptr) +{ + %CLASS% *instance = (%CLASS% *) ptr; + + /* free other fields */ + + free (instance); +} +|; + +my $include_data = q| +#ifndef __%CLASS_AS_PREFIX_UPPER%_H__ +#define __%CLASS_AS_PREFIX_UPPER%_H__ + +typedef struct s_%CLASS% %CLASS%; + +%CLASS% * %CLASS_AS_PREFIX%_new (void); +void %CLASS_AS_PREFIX%_destroy (void *ptr); + +#endif +|; + +exit (main(@ARGV)); + +sub main +{ + my @argv = @_; + + if (!defined ($argv[0])) + { + print "usage: " . basename ($0) . " \n"; + + return (1); + } + + my $class = $argv[0]; + + my $class_prefix = get_class_prefix ($class); + + if (!-d "include" || !-d "src") + { + print "Error: This must be ran from a directory containing \"include\" and \"src\".\n"; + + return (2); + } + + my $include_file = "include/" . $class_prefix . ".h"; + my $src_file = "src/" . $class_prefix . ".c"; + + if (-f $include_file || -f $src_file) + { + print "Error: Cannot overwrite existing files.\n"; + + return (3); + } + + open (FILE, "> $include_file") || die "$include_file: $^E"; + + print FILE get_include ($class); + + close (FILE); + + open (FILE, "> $src_file") || die "$src_file: $^E"; + + print FILE get_source ($class); + + close (FILE); + + return (0); +} + +sub get_source($) +{ + my ($class) = @_; + + return (update_string_for_class ($class, $source_data)); +} + +sub get_include($) +{ + my ($class) = @_; + + return (update_string_for_class ($class, $include_data)); +} + +sub update_string_for_class ($$) +{ + my ($class, $data) = @_; + + my $class_as_prefix = &get_class_prefix ($class); + + my $class_as_prefix_upper = uc ($class_as_prefix); + + $data =~ s/%CLASS%/$class/g; + $data =~ s/%CLASS_AS_PREFIX%/$class_as_prefix/g; + $data =~ s/%CLASS_AS_PREFIX_UPPER%/$class_as_prefix_upper/g; + + return ($data); +} + +sub get_class_prefix ($) +{ + my ($class) = @_; + + #(my $class_as_prefix = $class) =~ s/([A-Z]*)([A-Z])([^A-Z])/lc ($1) . "_" . lc ($2) . $3/eg; + (my $class_as_prefix = $class) =~ s/([A-Z]*)([A-Z])([^A-Z])/\L$1_$2\E$3/g; + + $class_as_prefix =~ s/^_+//g; + + return ($class_as_prefix); +} diff --git a/lc-continuity/mk4/lib/aura/src/.cvsignore b/lc-continuity/mk4/lib/aura/src/.cvsignore new file mode 100644 index 0000000000000000000000000000000000000000..39a06683b730815e864ffb8e1993c54683d30c54 --- /dev/null +++ b/lc-continuity/mk4/lib/aura/src/.cvsignore @@ -0,0 +1 @@ +.deps diff --git a/lc-continuity/mk4/lib/aura/src/CVS/Entries b/lc-continuity/mk4/lib/aura/src/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..fe3aa0198659841c180304e5aa734ffa87b21c23 --- /dev/null +++ b/lc-continuity/mk4/lib/aura/src/CVS/Entries @@ -0,0 +1,10 @@ +/.cvsignore/1.1/Wed Apr 28 06:12:24 2004//Tmk4_mod6_rc2 +/basictypes.c/1.1/Wed Apr 28 06:12:24 2004//Tmk4_mod6_rc2 +/iterator.c/1.2/Wed Apr 28 07:07:20 2004//Tmk4_mod6_rc2 +/list_iterator.c/1.1/Wed Apr 28 07:07:20 2004//Tmk4_mod6_rc2 +/memutil.c/1.3/Thu Jun 3 14:32:48 2004//Tmk4_mod6_rc2 +/serialization.c/1.2/Fri May 14 19:12:09 2004//Tmk4_mod6_rc2 +/serializationinfo.c/1.1/Wed Apr 28 06:12:24 2004//Tmk4_mod6_rc2 +/stringdictionary.c/1.3/Fri May 14 06:20:32 2004//Tmk4_mod6_rc2 +/typelocator.c/1.2/Fri May 14 19:12:09 2004//Tmk4_mod6_rc2 +D diff --git a/lc-continuity/mk4/lib/aura/src/CVS/Repository b/lc-continuity/mk4/lib/aura/src/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..fa31cbb61ef1e3e04238b22db8985091662f489d --- /dev/null +++ b/lc-continuity/mk4/lib/aura/src/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/lib/aura/src diff --git a/lc-continuity/mk4/lib/aura/src/CVS/Root b/lc-continuity/mk4/lib/aura/src/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/lib/aura/src/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/lib/aura/src/CVS/Tag b/lc-continuity/mk4/lib/aura/src/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/lib/aura/src/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/lib/aura/src/basictypes.c b/lc-continuity/mk4/lib/aura/src/basictypes.c new file mode 100644 index 0000000000000000000000000000000000000000..19b3f51f845cbd22f2207deb4185e67700d0eb3e --- /dev/null +++ b/lc-continuity/mk4/lib/aura/src/basictypes.c @@ -0,0 +1,72 @@ + +#include +#include + +#include "type.h" +#include "basictypes.h" + +Type type_declaration_Int = { "Int", basictypes_serializeInt, basictypes_deserializeInt }; +Type type_declaration_String = { "String", basictypes_serializeString, basictypes_deserializeString }; + +bool +basictypes_serializeInt (void *field, SerializationInfo *info) +{ + dynTstring *string = dynFinit(); + int *data = (int *) field; + + dynFappend_print (string, "%d", *data); + + serializationinfo_addValue (info, "value", string); + + return (true); +} + +bool +basictypes_deserializeInt (void *field, SerializationInfo *info) +{ + int result; + dynTstring *string; + int *int_field = (int *) field; + char *endptr; + + string = serializationinfo_getValue (info, "value"); + + result = strtol (dynFgetstr (string), &endptr, 10); + + if (endptr == NULL) + { + return (false); + } + else + { + *int_field = result; + + return (true); + } +} + +bool +basictypes_serializeString (void *field, SerializationInfo *info) +{ + dynTstring *string = dynFinit(); + char **char_field = (char **) field; + + dynFsappend (string, *char_field); + + serializationinfo_addValue (info, "value", string); + + return (true); +} + +bool +basictypes_deserializeString (void *field, SerializationInfo *info) +{ + char **char_field = (char **) field; + dynTstring *string; + + string = serializationinfo_getValue (info, "value"); + + *char_field = strdup (dynFgetstr (string)); + + return (true); +} diff --git a/lc-continuity/mk4/lib/aura/src/iterator.c b/lc-continuity/mk4/lib/aura/src/iterator.c new file mode 100644 index 0000000000000000000000000000000000000000..7f19191f32489af491b0eab3c90fab04d9c0b871 --- /dev/null +++ b/lc-continuity/mk4/lib/aura/src/iterator.c @@ -0,0 +1,52 @@ + +#include + +#include "iterator.h" + +struct s_Iterator +{ + void *data; + + IteratorNextDelegate next; + IteratorValueDelegate value; + IteratorDestroyDelegate destroy; +}; + +Iterator * +iterator_new (void *data, IteratorNextDelegate next, + IteratorValueDelegate value, IteratorDestroyDelegate destroy) +{ + Iterator *iter = malloc (sizeof (Iterator)); + + iter->data = data; + iter->next = next; + iter->value = value; + iter->destroy = destroy; + + return (iter); +} + +IteratorStatus +iterator_next (Iterator *iter) +{ + return (iter->next (iter->data)); +} + +void * +iterator_value (Iterator *iter) +{ + return (iter->value (iter->data)); +} + +void +iterator_destroy (void *ptr) +{ + Iterator *iter = (Iterator *) ptr; + + if (iter->destroy != NULL && iter->data != NULL) + { + iter->destroy (iter->data); + } + + free (iter); +} diff --git a/lc-continuity/mk4/lib/aura/src/list_iterator.c b/lc-continuity/mk4/lib/aura/src/list_iterator.c new file mode 100644 index 0000000000000000000000000000000000000000..fdecfeabadac4f680e266a4bd3d1b34802721d60 --- /dev/null +++ b/lc-continuity/mk4/lib/aura/src/list_iterator.c @@ -0,0 +1,86 @@ + +#include + +#include "mecha.h" + +#include "iterator.h" + +#include "list_iterator.h" + +struct s_ListIterator +{ + IIterator interface; + + lstTlist *list; + lstTlist_elem *cur_elem; + + int list_size; +}; + + +static IteratorStatus list_iterator_next (IIterator *inst); +static void * list_iterator_value (IIterator *inst); + +ListIterator * +list_iterator_new (lstTlist *list) +{ + ListIterator *instance = (ListIterator *) malloc (sizeof (ListIterator)); + + instance->interface.next = list_iterator_next; + instance->interface.get_value = list_iterator_value; + instance->interface.destroy = list_iterator_destroy; + + instance->list = list; + instance->cur_elem = NULL; + + instance->list_size = lstFlist_size (list); + + return (instance); +} + +void +list_iterator_destroy (IIterator *inst) +{ + ListIterator *instance = (ListIterator *) inst; + + free (instance); +} + +static IteratorStatus +list_iterator_next (IIterator *inst) +{ + ListIterator *instance = (ListIterator *) inst; + + if (lstFlist_size (instance->list) != instance->list_size) + { + return (IteratorOutOfSync); + } + + if (instance->cur_elem == NULL) + { + instance->cur_elem = lstFlist_head (instance->list); + } + else + { + instance->cur_elem = lstFlist_next (instance->cur_elem); + } + + if (instance->cur_elem != NULL) + { + return (IteratorSuccess); + } + else + { + return (IteratorEnd); + } +} + +static void * +list_iterator_value (IIterator *inst) +{ + ListIterator *instance = (ListIterator *) inst; + + assert (instance->cur_elem != NULL); + + return (lstFlist_data (instance->cur_elem)); +} diff --git a/lc-continuity/mk4/lib/aura/src/memutil.c b/lc-continuity/mk4/lib/aura/src/memutil.c new file mode 100644 index 0000000000000000000000000000000000000000..6c6e81f32082cc92c252f8800a60134ee87be404 --- /dev/null +++ b/lc-continuity/mk4/lib/aura/src/memutil.c @@ -0,0 +1,37 @@ + +#include + +#ifndef DARWIN +#include +#endif + +#include "memutil.h" + +void +memutil_printMemAllocated() +{ +#ifdef LINUX + struct mallinfo info; + + info = mallinfo(); + + printf ("= allocated: %d\n", info.uordblks); +#else + printf("memutil_printMemAllocated() not supported on Darwin."); +#endif + +} + +int +memutil_getMemAllocated() +{ +#ifdef LINUX + struct mallinfo info; + + info = mallinfo(); + + return (info.uordblks); +#else + return 0; +#endif +} diff --git a/lc-continuity/mk4/lib/aura/src/serialization.c b/lc-continuity/mk4/lib/aura/src/serialization.c new file mode 100644 index 0000000000000000000000000000000000000000..3ca9615cc313e23bb254117b925133666c014abf --- /dev/null +++ b/lc-continuity/mk4/lib/aura/src/serialization.c @@ -0,0 +1,355 @@ + +#include + +#include "serialization.h" +#include "type.h" +#include "typelocator.h" +#include "serializationinfo.h" +#include "iterator.h" + +#include + +dynTstring * +serialization_serializeType (const char *typeName, void *field) +{ + SerializationInfo *info; + dynTstring *string = NULL; + bool serialize_result; + Type *type; + + type = typelocator_getType (typelocator_getLocator(), typeName); + + if (type == NULL) + { + logFmsg (CONT_LOG_ERROR, "unknown type: %s", typeName); + + return (NULL); + } + + info = serializationinfo_new(); + + serialize_result = type->serialize (field, info); + + if (serialize_result == true) + { + string = serialization_serialize (info); + } + + serializationinfo_destroy (info); + + /* returning the string if successful, and otherwise, NULL */ + return (string); +} + +bool +serialization_deserializeType (const char *typeName, void *field, dynTstring *serializationData) +{ + SerializationInfo *info; + bool deserialize_result; + Type *type = typelocator_getType (typelocator_getLocator(), typeName); + + if (type == NULL) + { + logFmsg (CONT_LOG_ERROR, "unknown type: %s", typeName); + + return (false); + } + + /* this should likely be updated to take a dynstring */ + info = serialization_deserialize (serializationData); + + if (info == NULL) + { + logFmsg (CONT_LOG_ERROR, "couldn't deserialize %s", typeName); + + serializationinfo_destroy (info); + + return (false); + } + + deserialize_result = type->deserialize (field, info); + + serializationinfo_destroy (info); + + return (deserialize_result); +} + +static const char * +serialization_getStringData (const char *data, char **outData, int *outLen) +{ + char *endptr; + int len = strtol (data, &endptr, 10); + + if (*endptr != '[') + { + logFmsg (CONT_LOG_ERROR, "unknown string: %s", data); + + return (NULL); + } + + *outData = endptr + 1; + *outLen = len; + + /* + * data looks like: + * nn[ssssssss] + * + * where + * n = "number" + * s = "string" + * + * endptr will be at "[" and the number in "nn" will be the length of + * "sss", so all we need to do is add 1 to get to "sss", ad len, and add 1 + * to get to the end of the string + */ + endptr += 1 + len + 1; + + return (endptr); +} + +static const char * +serialization_getString (const char *data, dynTstring *string) +{ + const char *endptr; + char *outData; + int outLen; + + endptr = serialization_getStringData (data, &outData, &outLen); + + if (endptr == NULL) + { + return (NULL); + } + + dynFappend (string, outData, outLen); + + return (endptr); +} + + +dynTstring * +serialization_serializeTypeList (const char *typeName, Iterator *iterator) +{ + dynTstring *string = dynFinit(); + + dynFsappend (string, ""); + + while (iterator_next (iterator) == IteratorSuccess) + { + dynTstring *entry_string; + void *entry; + + entry = iterator_value (iterator); + + entry_string = serialization_serializeType (typeName, &entry); + + dynFappend_print (string, "%d", dynFgetlen (entry_string)); + dynFappend (string, "[", 1); + dynFappend (string, dynFgetstr (entry_string), dynFgetlen (entry_string)); + dynFappend (string, "]", 1); + + dynFfree (entry_string); + } + + iterator_destroy (iterator); + + return (string); +} + +bool +serialization_deserializeTypeList (const char *typeName, dynTstring *serializationData, DeserializationCallback callback, void *context) +{ + int len = dynFgetlen (serializationData); + const char *str_loc = dynFgetstr (serializationData); + + if (strncmp ("", str_loc, 3) != 0) + { + logFmsg (CONT_LOG_ERROR, "not a list: %s", str_loc); + + return (false); + } + else + { + str_loc += 3; + } + + while (str_loc != NULL && ((str_loc - dynFgetstr (serializationData)) < len)) + { + dynTstring *value = dynFinit(); + void *value_object; + + str_loc = serialization_getString (str_loc, value); + + if (serialization_deserializeType (typeName, &value_object, value) == false) + { + logFmsg (CONT_LOG_ERROR, "Couldn't deserialize type %s", typeName); + + dynFfree (value); + + return (false); + } + + dynFfree (value); + + callback (context, value_object); + } + + if (str_loc == NULL) + { + logFmsg (CONT_LOG_ERROR, "error in data: %s", dynFgetstr (serializationData)); + + return (false); + } + + return (true); +} + +dynTstring * +serialization_serialize (SerializationInfo *info) +{ + hshTiterator *iter = serializationinfo_getIterator (info); + dynTstring *string = dynFinit(); + + dynFappend (string, "", 4); + + while (hshFiterator_next (iter) == 1) + { + char *key = (char *) hshFiterator_current_key (iter); + dynTstring *value = (dynTstring *) hshFiterator_current_value (iter); + int key_len = strlen (key); + + dynFappend_print (string, "%d", key_len); + dynFappend (string, "[", 1); + dynFappend (string, key, key_len); + dynFappend (string, "]", 1); + + dynFappend_print (string, "%d", dynFgetlen (value)); + dynFappend (string, "[", 1); + dynFappend (string, dynFgetstr (value), dynFgetlen (value)); + dynFappend (string, "]", 1); + } + + hshFiterator_free (iter); + + return (string); +} + +SerializationInfo * +serialization_deserialize (dynTstring *string) +{ + SerializationInfo *info; + const char *str_loc = dynFgetstr (string); + + if (strncmp ("", str_loc, 4) != 0) + { + logFmsg (CONT_LOG_ERROR, "Not a SerializationInfo object: %s", dynFgetstr (string)); + + return (NULL); + } + else + { + str_loc += 4; + } + + info = serializationinfo_new(); + + while (str_loc != NULL && ((unsigned int) (str_loc - dynFgetstr (string)) < dynFgetlen (string))) + { + char *key; + int keyLen; + dynTstring *value; + + str_loc = serialization_getStringData (str_loc, &key, &keyLen); + + if (str_loc == NULL) + { + logFmsg (CONT_LOG_ERROR, "Wrong number of params in: %s", dynFgetstr (string)); + + serializationinfo_destroy (info); + + return (NULL); + } + + value = dynFinit(); + + str_loc = serialization_getString (str_loc, value); + + /* + * we're passing the value dynTstring to the SerializationInfo object, + * so we don't need to free it ourselves in this call. + */ + serializationinfo_addValueData (info, key, keyLen, value); + } + + if (str_loc == NULL) + { + logFmsg (CONT_LOG_ERROR, "Error in data: %s", dynFgetstr (string)); + serializationinfo_destroy (info); + + return (NULL); + } + + return (info); +} + +dynTstring * +serialization_serializeList (lstTlist *list) +{ + dynTstring *string = dynFinit(); + lstTlist_elem *elem; + + dynFappend (string, "", 3); + + for (elem = lstFlist_head (list); elem != NULL; elem = lstFlist_next (elem)) + { + dynTstring *value = lstFlist_data (elem); + + dynFappend_print (string, "%d", dynFgetlen (value)); + dynFappend (string, "[", 1); + dynFappend (string, dynFgetstr (value), dynFgetlen (value)); + dynFappend (string, "]", 1); + } + + return (string); +} + +lstTlist * +serialization_deserializeList (dynTstring *string) +{ + lstTlist *ser_data; + int len = dynFgetlen (string); + const char *str_loc = dynFgetstr (string); + + if (strncmp ("", str_loc, 3) != 0) + { + logFmsg (CONT_LOG_ERROR, "Not a list: %s", dynFgetstr (string)); + + return (NULL); + } + else + { + str_loc += 3; + } + + ser_data = lstFlist_create ((void (*) (void *)) dynFfree); + + while (str_loc != NULL && ((str_loc - dynFgetstr (string)) < len)) + { + dynTstring *value = dynFinit(); + + str_loc = serialization_getString (str_loc, value); + + lstFlist_add_next (ser_data, lstFlist_tail (ser_data), value); + } + + if (str_loc == NULL) + { + logFmsg (CONT_LOG_ERROR, "Error in data: %s", dynFgetstr (string)); + + lstFlist_free (ser_data); + + return (NULL); + } + + return (ser_data); +} diff --git a/lc-continuity/mk4/lib/aura/src/serializationinfo.c b/lc-continuity/mk4/lib/aura/src/serializationinfo.c new file mode 100644 index 0000000000000000000000000000000000000000..c233bb6bc66c449a6d0705eb7b777335add70e57 --- /dev/null +++ b/lc-continuity/mk4/lib/aura/src/serializationinfo.c @@ -0,0 +1,66 @@ + +#include +#include + +#include "serializationinfo.h" + +struct s_SerializationInfo +{ + hshTvoid_list *table; +}; + +SerializationInfo * +serializationinfo_new() +{ + SerializationInfo *info = (SerializationInfo *) malloc (sizeof (SerializationInfo)); + info->table = hshFvoid_init ((void (*) (void *)) dynFfree); + + return (info); +} + +void +serializationinfo_destroy (void *ptr) +{ + SerializationInfo *info = (SerializationInfo *) ptr; + + hshFvoid_destroy (info->table); + + free (info); +} + +void +serializationinfo_addValueData (SerializationInfo *info, const char *key, int keyLen, dynTstring *value) +{ + char *alloc_key = malloc (keyLen + 1); + + memcpy (alloc_key, key, keyLen); + + *(alloc_key + keyLen) = 0; + + /* if we use raw_add, we have to allocate the key ourselves */ + hshFvoid_raw_add (info->table, alloc_key, keyLen, value, 0); +} + +void +serializationinfo_addValue (SerializationInfo *info, const char *key, dynTstring *value) +{ + hshFvoid_add (info->table, key, value); +} + +dynTstring * +serializationinfo_getValue (SerializationInfo *info, const char *key) +{ + return ((dynTstring *) hshFvoid_find (info->table, key)); +} + +hshTiterator * +serializationinfo_getIterator (SerializationInfo *info) +{ + return (hshFiterator_init (info->table)); +} + +void +serializationinfo_destroyIterator (hshTiterator *iter) +{ + hshFiterator_free (iter); +} diff --git a/lc-continuity/mk4/lib/aura/src/stringdictionary.c b/lc-continuity/mk4/lib/aura/src/stringdictionary.c new file mode 100644 index 0000000000000000000000000000000000000000..d622990bb3999481ca9d8d2c6cde53cdd354ef83 --- /dev/null +++ b/lc-continuity/mk4/lib/aura/src/stringdictionary.c @@ -0,0 +1,233 @@ + +#include +#include + +#include "mecha.h" + +#include "stringdictionary.h" +#include "serializationinfo.h" +#include "type.h" + +struct s_StringDictionary +{ + hshTvoid_list *table; +}; + +static bool stringdictionary_serialize (void *field, SerializationInfo *info); +static bool stringdictionary_deserialize (void *field, SerializationInfo *info); +static dynTstring * stringdictionary_serializeTable (StringDictionary *dict); +static StringDictionary * strictdictionary_deserializeFromString (dynTstring *string); + +Type type_declaration_StringDictionary = { "StringDictionary", stringdictionary_serialize, stringdictionary_deserialize }; + +StringDictionary * +stringdictionary_new() +{ + StringDictionary *info = (StringDictionary *) malloc (sizeof (StringDictionary)); + info->table = hshFvoid_init ((void (*) (void *)) dynFfree); + + return (info); +} + +void +stringdictionary_destroy (void *ptr) +{ + StringDictionary *info = (StringDictionary *) ptr; + + hshFvoid_destroy (info->table); + + free (info); +} + +bool +stringdictionary_addValue (StringDictionary *info, const char *key, dynTstring *value) +{ + if (hshFvoid_add (info->table, key, value)) + { + return (true); + } + else + { + return (false); + } +} + +void +stringdictionary_setValue (StringDictionary *info, const char *key, dynTstring *value) +{ + hshFvoid_replace (info->table, key, (void *) value); +} + +dynTstring * +stringdictionary_getValue (StringDictionary *info, const char *key) +{ + return ((dynTstring *) hshFvoid_find (info->table, key)); +} + +hshTiterator * +stringdictionary_getIterator (StringDictionary *dict) +{ + return (hshFiterator_init (dict->table)); +} + +static bool +stringdictionary_serialize (void *field, SerializationInfo *info) +{ + StringDictionary *dict = DEREFERENCE_TYPE (StringDictionary, field); + + serializationinfo_addValue (info, "table", + stringdictionary_serializeTable (dict)); + + return (true); +} + +static bool +stringdictionary_deserialize (void *field, SerializationInfo *info) +{ + StringDictionary *dict; + + dict = strictdictionary_deserializeFromString ( + serializationinfo_getValue (info, "table")); + + if (dict == NULL) + { + return (false); + } + else + { + StringDictionary **fieldPtr = (StringDictionary **) field; + + *fieldPtr = dict; + + /* DEREFERENCE_TYPE (StringDictionary, field) = dict; */ + + return (true); + } +} + +static const char * +stringdictionary_deserializeGetString (const char *data, dynTstring *string) +{ + char *endptr; + int len = strtol (data, &endptr, 10); + + if (*endptr != '[') + { + printf ("-- unknown string: %s\n", data); + + return (NULL); + } + + dynFappend (string, endptr + 1, len); + + /* + * data looks like: + * nn[ssssssss] + * + * where + * n = "number" + * s = "string" + * + * endptr will be at "[" and the number in "nn" will be the length of + * "sss", so all we need to do is add 1 to get to "sss", ad len, and add 1 + * to get to the end of the string + */ + endptr += 1 + len + 1; + + return (endptr); +} + +static dynTstring * +stringdictionary_serializeTable (StringDictionary *dict) +{ + hshTiterator *iter = hshFiterator_init (dict->table); + dynTstring *string = dynFinit(); + + dynFsappend (string, ""); + + while (hshFiterator_next (iter) == 1) + { + char *key = (char *) hshFiterator_current_key (iter); + dynTstring *value = (dynTstring *) hshFiterator_current_value (iter); + int key_len = strlen (key); + + dynFappend_print (string, "%d", key_len); + dynFappend (string, "[", 1); + dynFappend (string, key, key_len); + dynFappend (string, "]", 1); + + dynFappend_print (string, "%d", dynFgetlen (value)); + dynFappend (string, "[", 1); + dynFappend (string, dynFgetstr (value), dynFgetlen (value)); + dynFappend (string, "]", 1); + } + + hshFiterator_free (iter); + + return (string); +} + + +static StringDictionary * +strictdictionary_deserializeFromString (dynTstring *string) +{ + StringDictionary *dict; + int len = dynFgetlen (string); + const char *str_loc = dynFgetstr (string); + + if (strncmp ("", str_loc, 4) != 0) + { + printf ("-- not a SerializationInfo object: %s", dynFgetstr (string)); + + return (NULL); + } + else + { + str_loc += 4; + } + + dict = stringdictionary_new(); + + while (str_loc != NULL && ((str_loc - dynFgetstr (string)) < len)) + { + dynTstring *key = dynFinit(); + dynTstring *value; + + str_loc = stringdictionary_deserializeGetString (str_loc, key); + + if (str_loc == NULL) + { + printf ("-- wrong number of params in: %s\n", dynFgetstr (string)); + + stringdictionary_destroy (dict); + + dynFfree (key); + + return (NULL); + } + + value = dynFinit(); + + str_loc = stringdictionary_deserializeGetString (str_loc, value); + + /* + * we're passing the value dynTstring to the SerializationInfo object, + * so we don't need to free it ourselves in this call. + */ + stringdictionary_addValue (dict, dynFgetstr (key), value); + + dynFfree (key); + } + + if (str_loc == NULL) + { + printf ("-- error in data: %s\n", dynFgetstr (string)); + stringdictionary_destroy (dict); + + return (NULL); + } + + return (dict); +} + + diff --git a/lc-continuity/mk4/lib/aura/src/typelocator.c b/lc-continuity/mk4/lib/aura/src/typelocator.c new file mode 100644 index 0000000000000000000000000000000000000000..ae229f8e1e4d79a754037698022079788f61440c --- /dev/null +++ b/lc-continuity/mk4/lib/aura/src/typelocator.c @@ -0,0 +1,146 @@ + +#include +#include +#include +#include +#include + + +#include "type.h" +#include "typelocator.h" + +struct s_TypeLocator +{ + hshTvoid_list *types; + pthread_rwlock_t types_lock; +}; + +static TypeLocator *g_locator = NULL; + +TypeLocator * +typelocator_new() +{ + TypeLocator *locator = (TypeLocator *) malloc (sizeof (TypeLocator)); + + locator->types = hshFvoid_init (NULL); + + pthread_rwlock_init (&locator->types_lock, NULL); + + return (locator); +} + +TypeLocator * +typelocator_getLocator() +{ + if (g_locator == NULL) + { + g_locator = typelocator_new(); + } + + return (g_locator); +} + +#if 0 +static bool +typelocator_hasType (TypeLocator *locator, const char *typeName) +{ + bool ret; + + pthread_rwlock_rdlock (&locator->types_lock); + + ret = hshFvoid_contains (locator->types, typeName); + + pthread_rwlock_unlock (&locator->types_lock); + + return (ret); +} +#endif + +static Type * +typelocator_findType (TypeLocator *locator, const char *typeName) +{ + Type *type; + + pthread_rwlock_rdlock (&locator->types_lock); + + type = (Type *) hshFvoid_find (locator->types, typeName); + + pthread_rwlock_unlock (&locator->types_lock); + + return (type); + +} + +static bool +typelocator_addType (TypeLocator *locator, Type *type) +{ + bool ret; + + pthread_rwlock_wrlock (&locator->types_lock); + + /* this will only add an entry once */ + if (hshFvoid_add (locator->types, type->name, type)) + { + ret = true; + } + else + { + ret = false; + } + + pthread_rwlock_unlock (&locator->types_lock); + + return (ret); +} + +Type * +typelocator_getType (TypeLocator *locator, const char *typeName) +{ + Type *type; + + type = typelocator_findType (locator, typeName); + + if (type != NULL) + { + return (type); + } + else + { + dynTstring *string = dynFinit(); + const char *err; + + /* don't want to include the null */ + dynFappend (string, "type_declaration_", sizeof ("type_declaration_") - 1); + dynFsappend (string, typeName); + + type = dlsym (NULL, dynFgetstr (string)); + + dynFfree (string); + + if (type == NULL) + { + err = dlerror(); + + if (err != NULL) + { + logFmsg (CONT_LOG_ERROR, "dlsym: %s", err); + + return (NULL); + } + } + else + { + if (strcmp (typeName, type->name) != 0) + { + logFmsg (CONT_LOG_ERROR, "type missmatch: asked for \"%s\", found \"%s\"", + typeName, type->name); + + return (NULL); + } + } + + typelocator_addType (locator, type); + + return (type); + } +} diff --git a/lc-continuity/mk4/lib/causality-client/CVS/Entries b/lc-continuity/mk4/lib/causality-client/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..dc3e5ade63ca6c5a889e0dd580ee5d3e0efa40c2 --- /dev/null +++ b/lc-continuity/mk4/lib/causality-client/CVS/Entries @@ -0,0 +1,3 @@ +/Makefile/1.1/Thu May 13 21:08:28 2004//Tmk4_mod6_rc2 +D/include//// +D/src//// diff --git a/lc-continuity/mk4/lib/causality-client/CVS/Repository b/lc-continuity/mk4/lib/causality-client/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..878dfcc91c589c2ed1d370bbf7440e4e4bd737d0 --- /dev/null +++ b/lc-continuity/mk4/lib/causality-client/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/lib/causality-client diff --git a/lc-continuity/mk4/lib/causality-client/CVS/Root b/lc-continuity/mk4/lib/causality-client/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/lib/causality-client/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/lib/causality-client/CVS/Tag b/lc-continuity/mk4/lib/causality-client/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/lib/causality-client/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/lib/causality-client/Makefile b/lc-continuity/mk4/lib/causality-client/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..ee0bd3afbad8ceed482b89d7dead2df961fa6589 --- /dev/null +++ b/lc-continuity/mk4/lib/causality-client/Makefile @@ -0,0 +1,14 @@ +CONTINUITY = ../../continuity + +TARGET = causality-client +TARGETTYPE = shared static + +SOURCES = src/http_request.c src/http_request_handler.c \ + src/http_request_list.c src/http_request_queue.c \ + src/client.c src/http_response.c src/http_request_list_entry.c + +INCLUDES += -Iinclude -I../aura/include -I../causality/include +STATIC_LIBS += $(CONTINUITY)/lib/libaura.a $(CONTINUITY)/lib/libcausality.a +#LOCAL_CFLAGS += + +include $(CONTINUITY)/lib/build.mk diff --git a/lc-continuity/mk4/lib/causality-client/include/CVS/Entries b/lc-continuity/mk4/lib/causality-client/include/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..eec64851ea4f13a771ac01161c1867cc22bd45e8 --- /dev/null +++ b/lc-continuity/mk4/lib/causality-client/include/CVS/Entries @@ -0,0 +1,8 @@ +/client.h/1.1/Thu May 13 21:08:28 2004//Tmk4_mod6_rc2 +/http_request.h/1.1/Thu May 13 21:08:28 2004//Tmk4_mod6_rc2 +/http_request_handler.h/1.1/Thu May 13 21:08:28 2004//Tmk4_mod6_rc2 +/http_request_list.h/1.1/Thu May 13 21:08:28 2004//Tmk4_mod6_rc2 +/http_request_list_entry.h/1.1/Thu May 13 21:08:28 2004//Tmk4_mod6_rc2 +/http_request_queue.h/1.1/Thu May 13 21:08:28 2004//Tmk4_mod6_rc2 +/http_response.h/1.1/Thu May 13 21:08:28 2004//Tmk4_mod6_rc2 +D diff --git a/lc-continuity/mk4/lib/causality-client/include/CVS/Repository b/lc-continuity/mk4/lib/causality-client/include/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..c385c4ec6c8d4dc622d2c4d9349fe4830e6d11ae --- /dev/null +++ b/lc-continuity/mk4/lib/causality-client/include/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/lib/causality-client/include diff --git a/lc-continuity/mk4/lib/causality-client/include/CVS/Root b/lc-continuity/mk4/lib/causality-client/include/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/lib/causality-client/include/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/lib/causality-client/include/CVS/Tag b/lc-continuity/mk4/lib/causality-client/include/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/lib/causality-client/include/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/lib/causality-client/include/client.h b/lc-continuity/mk4/lib/causality-client/include/client.h new file mode 100644 index 0000000000000000000000000000000000000000..9d7bb5f1c595b3159e5f54d37f9dd768556849ad --- /dev/null +++ b/lc-continuity/mk4/lib/causality-client/include/client.h @@ -0,0 +1,34 @@ +#ifndef __CLIENT_H__ +#define __CLIENT_H__ + +#include "http_request.h" + +void client_init (const key_t ipcKey); +void client_destroy (void); + +void * client_get_request (void); + +bool client_write_data (HttpRequest *httpRequest, const char *data, int dataLen); + +bool client_write_string (HttpRequest *httpRequest, const char *data); + + +bool client_finish (const HttpRequest *request); + +const char * client_get_uri (const HttpRequest *request); +const char * client_get_query (const HttpRequest *request); +const char * client_get_method (const HttpRequest *request); +const char * client_get_request_header (const HttpRequest *httpRequest, const char *key); +const char * client_get_variable (const HttpRequest *httpRequest, char *key); +int client_get_entity (HttpRequest *httpRequest, char *buf, int bufLen); +void client_set_status (HttpRequest *httpRequest, const int status, const char *description); + +bool client_is_entire_entity_loaded (const HttpRequest *httpRequest); +bool client_headers_sent (const HttpRequest *request); + + +void client_set_response_header (const HttpRequest *httpRequest, const char *key, const char *value); + +const char * client_get_remote_ip (HttpRequest *instance); + +#endif diff --git a/lc-continuity/mk4/lib/causality-client/include/http_request.h b/lc-continuity/mk4/lib/causality-client/include/http_request.h new file mode 100644 index 0000000000000000000000000000000000000000..2db8a9ebdf786959f306040ea83cf5cbe4a8df86 --- /dev/null +++ b/lc-continuity/mk4/lib/causality-client/include/http_request.h @@ -0,0 +1,57 @@ +#ifndef __HTTP_REQUEST_H__ +#define __HTTP_REQUEST_H__ + +#include "message.h" +#include "processor.h" + +/* from continuity.h */ +#ifndef STATUS_OK + +#define STATUS_OK 1 +#define STATUS_ERROR 2 +#define STATUS_PROCEED 3 +#define STATUS_EXIT 4 +#define STATUS_RESTART 5 + +#endif + +typedef struct s_HttpRequest HttpRequest; + +HttpRequest * http_request_new (Message *requestMessage, Processor *processor); +void http_request_destroy (void *ptr); + +const char * http_request_getToken (const HttpRequest *request); +const char * http_request_getUri (const HttpRequest *request); +const char * http_request_getQuery (const HttpRequest *request); +const char * http_request_getMethod (const HttpRequest *request); +const char * http_request_getDocRoot (const HttpRequest *request); +const char * http_request_getRemoteIP (const HttpRequest *request); + +const dynTstring * http_request_getVariableString (const HttpRequest *request, const char *variable); +const char * http_request_getVariable (const HttpRequest *request, const char *variable); + +const char * http_request_getRequestHeader (const HttpRequest *request, const char *key); +const dynTstring * http_request_getRequestHeaderString (const HttpRequest *request, const char *key); + +bool http_request_writeData (HttpRequest *request, const char *data, int dataLen); +bool http_request_writeString (HttpRequest *request, const char *data); + +bool http_request_finish (const HttpRequest *request); + +int http_request_getEntity (HttpRequest *request, char *outBuf, int bufLen); +bool http_request_isEntireEntityLoaded (const HttpRequest *request); + +const dynTstring * http_request_getEntireEntity (HttpRequest *instance); + +void http_request_setResponseHeader (const HttpRequest *request, const char *key, const char *value); +void http_request_setResponseHeaderData (const HttpRequest *request, const char *key, const char *value, int valueLen); + +void http_request_setHttpStatus (HttpRequest *request, int status, const char *description); + +bool http_request_finishStatus (const HttpRequest *request, int status); + +bool http_request_headersSent (const HttpRequest *request); + +hshTiterator * http_request_getRequestHeaderIterator (const HttpRequest *request); + +#endif diff --git a/lc-continuity/mk4/lib/causality-client/include/http_request_handler.h b/lc-continuity/mk4/lib/causality-client/include/http_request_handler.h new file mode 100644 index 0000000000000000000000000000000000000000..ef53023c46084ab9f26efcc9912821d45c3273c8 --- /dev/null +++ b/lc-continuity/mk4/lib/causality-client/include/http_request_handler.h @@ -0,0 +1,12 @@ +#ifndef __HTTP_REQUEST_HANDLER_H__ +#define __HTTP_REQUEST_HANDLER_H__ + +#include "message.h" + +Message * http_request_handler_handleRequest (void *context, Message *requestMessage); +Message * http_request_handler_handlePing (void *context, Message *requestMessage); + +extern CommandHandler command_HttpRequestStart; +extern CommandHandler command_HttpRequestPing; + +#endif diff --git a/lc-continuity/mk4/lib/causality-client/include/http_request_list.h b/lc-continuity/mk4/lib/causality-client/include/http_request_list.h new file mode 100644 index 0000000000000000000000000000000000000000..40c326ace5ad8fea41c1224b5790fede8440f33a --- /dev/null +++ b/lc-continuity/mk4/lib/causality-client/include/http_request_list.h @@ -0,0 +1,30 @@ +#ifndef __HTTP_REQUEST_LIST_H__ +#define __HTTP_REQUEST_LIST_H__ + +#include "message.h" +#include "http_request.h" + +typedef struct s_HttpRequestList HttpRequestList; + +typedef void (*HttpRequestHandlerDelegate) (HttpRequest *request, void *context); + +HttpRequestList * http_request_list_new (void); +void http_request_list_destroy (void *ptr); + +void http_request_list_addRequest (HttpRequestList *requestList, HttpRequest *request); + +void http_request_list_setHandler (HttpRequestList *instance, + HttpRequestHandlerDelegate delegate, void *context); + +HttpRequestList * http_request_list_getRequestList (void); + +void http_request_list_handler (Message *requestMessage); + +HttpRequest * http_request_list_getNextRequest (HttpRequestList *requestList); + +void http_request_list_removeRequest (HttpRequestList *requestList, const char *token); + +bool http_request_list_containsRequest (HttpRequestList *requestList, const char *token); + + +#endif diff --git a/lc-continuity/mk4/lib/causality-client/include/http_request_list_entry.h b/lc-continuity/mk4/lib/causality-client/include/http_request_list_entry.h new file mode 100644 index 0000000000000000000000000000000000000000..c0207e4a32c4f2bb946bd6cb8c4c446dd0f3113c --- /dev/null +++ b/lc-continuity/mk4/lib/causality-client/include/http_request_list_entry.h @@ -0,0 +1,16 @@ + +#ifndef __HTTP_REQUEST_LIST_ENTRY_H__ +#define __HTTP_REQUEST_LIST_ENTRY_H__ + +#include "http_request_list.h" + +typedef struct s_HttpRequestListEntry HttpRequestListEntry; + +HttpRequestListEntry * +http_request_list_entry_new (HttpRequestHandlerDelegate delegate, + HttpRequest *request, void *context); +void http_request_list_entry_destroy (void *ptr); + +void http_request_list_entry_invokeEntry (void *ptr); + +#endif diff --git a/lc-continuity/mk4/lib/causality-client/include/http_request_queue.h b/lc-continuity/mk4/lib/causality-client/include/http_request_queue.h new file mode 100644 index 0000000000000000000000000000000000000000..0bc2c8e628b0bd7a4ee727e9dd5c11d6e45ae61d --- /dev/null +++ b/lc-continuity/mk4/lib/causality-client/include/http_request_queue.h @@ -0,0 +1,15 @@ +#ifndef __HTTP_REQUEST_QUEUE_H__ +#define __HTTP_REQUEST_QUEUE_H__ + +#include "http_request.h" + +typedef struct s_HttpRequestQueue HttpRequestQueue; + +HttpRequestQueue * http_request_queue_new (void); + +void http_request_queue_destroy (void *ptr); + +HttpRequest * http_request_queue_getRequest (HttpRequestQueue *resp); +void http_request_queue_addRequest (HttpRequestQueue *resp, HttpRequest *request); + +#endif diff --git a/lc-continuity/mk4/lib/causality-client/include/http_response.h b/lc-continuity/mk4/lib/causality-client/include/http_response.h new file mode 100644 index 0000000000000000000000000000000000000000..c26a99dd27a96f23b0adc6ceb50f09b40c1c9570 --- /dev/null +++ b/lc-continuity/mk4/lib/causality-client/include/http_response.h @@ -0,0 +1,12 @@ +#ifndef __HTTP_RESPONSE_H__ +#define __HTTP_RESPONSE_H__ + +bool http_response_sendWriteMessage (Processor *processor, const char *token, const char *data, int dataLen); + +bool http_response_sendFinishMessage (Processor *processor, const char *token, int returnStatus); + +bool http_response_sendReadEntityBody (Processor *processor, const char *token, dynTstring *entity); + +bool http_response_sendSimpleMessage (Processor *processor, Message *requestMessage); + +#endif diff --git a/lc-continuity/mk4/lib/causality-client/src/CVS/Entries b/lc-continuity/mk4/lib/causality-client/src/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..d191e5b964cd7bcfea5f20697b2c314b56db6c95 --- /dev/null +++ b/lc-continuity/mk4/lib/causality-client/src/CVS/Entries @@ -0,0 +1,8 @@ +/client.c/1.2/Fri May 14 16:51:25 2004//Tmk4_mod6_rc2 +/http_request.c/1.1/Thu May 13 21:08:28 2004//Tmk4_mod6_rc2 +/http_request_handler.c/1.2/Fri May 14 15:28:08 2004//Tmk4_mod6_rc2 +/http_request_list.c/1.1/Thu May 13 21:08:28 2004//Tmk4_mod6_rc2 +/http_request_list_entry.c/1.1/Thu May 13 21:08:28 2004//Tmk4_mod6_rc2 +/http_request_queue.c/1.1/Thu May 13 21:08:28 2004//Tmk4_mod6_rc2 +/http_response.c/1.2/Fri May 14 19:12:09 2004//Tmk4_mod6_rc2 +D diff --git a/lc-continuity/mk4/lib/causality-client/src/CVS/Repository b/lc-continuity/mk4/lib/causality-client/src/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..a76d10fa8196d249968465ab28336e0cf50646dc --- /dev/null +++ b/lc-continuity/mk4/lib/causality-client/src/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/lib/causality-client/src diff --git a/lc-continuity/mk4/lib/causality-client/src/CVS/Root b/lc-continuity/mk4/lib/causality-client/src/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/lib/causality-client/src/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/lib/causality-client/src/CVS/Tag b/lc-continuity/mk4/lib/causality-client/src/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/lib/causality-client/src/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/lib/causality-client/src/client.c b/lc-continuity/mk4/lib/causality-client/src/client.c new file mode 100644 index 0000000000000000000000000000000000000000..7fc3b7edcb3e0abb469f2eeaae253017d7255645 --- /dev/null +++ b/lc-continuity/mk4/lib/causality-client/src/client.c @@ -0,0 +1,141 @@ + +#include + +#include "client.h" + +#include "command_handlers.h" +#include "http_request_handler.h" + +#include "http_request_list.h" +#include "http_response.h" + +Processor *g_processor; + +void +client_init (const key_t ipcKey) +{ + logFinit(); + + logFmsg (CONT_LOG_DEBUG, "causality-client/%d: initting client.", getpid()); + + thrFmod_init(); + + g_processor = processor_new (ipcKey, true); + + processor_addRequestHandler (g_processor, &command_HttpRequestStart, g_processor); + processor_addRequestHandler (g_processor, &command_HttpRequestPing, NULL); + + processor_finishedInit (g_processor); + + logFmsg (CONT_LOG_DEBUG, "causality-client/%d: finished initting client.", getpid()); +} + +void +client_destroy() +{ + HttpRequestList *requestList = http_request_list_getRequestList(); + + http_request_list_destroy (requestList); + + processor_destroy (g_processor); +} + +void * +client_get_request() +{ + HttpRequestList *requestList = http_request_list_getRequestList(); + HttpRequest *request = http_request_list_getNextRequest (requestList); + + return (request); +} + +bool +client_write_data (HttpRequest *httpRequest, const char *data, int dataLen) +{ + return (http_request_writeData (httpRequest, data, dataLen)); +} + +bool +client_write_string (HttpRequest *httpRequest, const char *data) +{ + return (http_request_writeString (httpRequest, data)); +} + +const char * +client_get_remote_ip (HttpRequest *instance) +{ + return (http_request_getRemoteIP (instance)); +} + +const char * +client_get_uri (const HttpRequest *httpRequest) +{ + return (http_request_getUri (httpRequest)); +} + +const char * +client_get_query (const HttpRequest *httpRequest) +{ + return (http_request_getQuery (httpRequest)); +} + +const char * +client_get_variable (const HttpRequest *httpRequest, char *key) +{ + return (http_request_getVariable (httpRequest, key)); +} + +const char * +client_get_request_header (const HttpRequest *httpRequest, const char *key) +{ + return (http_request_getRequestHeader (httpRequest, key)); +} + +const char * +client_get_method (const HttpRequest *httpRequest) +{ + return (http_request_getMethod (httpRequest)); +} + +int +client_get_entity (HttpRequest *httpRequest, char *buf, int bufLen) +{ + return (http_request_getEntity (httpRequest, buf, bufLen)); +} + +bool +client_is_entire_entity_loaded (const HttpRequest *httpRequest) +{ + return (http_request_isEntireEntityLoaded (httpRequest)); +} + +void +client_set_response_header (const HttpRequest *httpRequest, const char *key, const char *value) +{ + http_request_setResponseHeader (httpRequest, key, value); +} + +void +client_set_status (HttpRequest *httpRequest, const int status, const char *description) +{ + http_request_setHttpStatus (httpRequest, status, description); +} + +bool +client_headers_sent (const HttpRequest *request) +{ + return (http_request_headersSent (request)); +} + +bool +client_finish (const HttpRequest *httpRequest) +{ + bool ret; + + ret = http_request_finish (httpRequest); + + http_request_list_removeRequest (http_request_list_getRequestList(), + http_request_getToken (httpRequest)); + + return (ret); +} diff --git a/lc-continuity/mk4/lib/causality-client/src/http_request.c b/lc-continuity/mk4/lib/causality-client/src/http_request.c new file mode 100644 index 0000000000000000000000000000000000000000..6eb752ba423f5f38c75d6924ac96307284428015 --- /dev/null +++ b/lc-continuity/mk4/lib/causality-client/src/http_request.c @@ -0,0 +1,463 @@ + +#include +#include + +#include + +#include + +#include "http_request.h" +#include "http_response.h" +#include "stringdictionary.h" +#include "serialization.h" + +struct s_HttpRequest +{ + dynTstring *token; + dynTstring *remoteIP; + + bool entityRequested; + unsigned int entityReadOffset; + dynTstring *entity; + + Processor *processor; + + StringDictionary *requestHeaders; + + StringDictionary *transactionVariables; + + int responseStatus; + dynTstring *responseReason; + + bool sentResponseHeaders; + StringDictionary *responseHeaders; +}; + +static bool http_request_setIfNotNull (dynTstring *dest, const dynTstring *src); +static const char *http_request_getInternalString (dynTstring *string); + +HttpRequest * +http_request_new (Message *requestMessage, Processor *processor) +{ + HttpRequest *request = malloc (sizeof (HttpRequest)); + + assert (requestMessage != NULL); + assert (processor != NULL); + + request->token = dynFinit(); + request->remoteIP = dynFinit(); + + request->entityRequested = false; + request->entityReadOffset = 0; + request->entity = dynFinit(); + + request->processor = processor; + + http_request_setIfNotNull (request->token, + message_getParameterString (requestMessage, "token")); + + http_request_setIfNotNull (request->remoteIP, + message_getParameterString (requestMessage, "remoteIP")); + + { + dynTstring *value = message_getParameterString (requestMessage, + "headers"); + + if (value != NULL) + { + serialization_deserializeType ("StringDictionary", + &request->requestHeaders, value); + } + else + { + request->requestHeaders = stringdictionary_new(); + } + } + + { + dynTstring *value = message_getParameterString (requestMessage, + "variables"); + + if (value != NULL) + { + serialization_deserializeType ("StringDictionary", + &request->transactionVariables, value); + } + else + { + request->transactionVariables = stringdictionary_new(); + } + } + + request->responseHeaders = stringdictionary_new(); + request->sentResponseHeaders = false; + + request->responseStatus = 200; + request->responseReason = dynFinit(); + + return (request); +} + +void +http_request_destroy (void *ptr) +{ + HttpRequest *request = (HttpRequest *) ptr; + + assert (request != NULL); + + dynFfree (request->token); + dynFfree (request->remoteIP); + dynFfree (request->entity); + + stringdictionary_destroy (request->requestHeaders); + stringdictionary_destroy (request->responseHeaders); + stringdictionary_destroy (request->transactionVariables); + + dynFfree (request->responseReason); + + free (request); +} + +void +http_request_setHttpStatus (HttpRequest *request, const int status, const char *description) +{ + assert (request != NULL); + + request->responseStatus = status; + + dynFsappend (request->responseReason, description); +} + +const char * +http_request_getToken (const HttpRequest *request) +{ + assert (request != NULL); + + return (dynFgetstr (request->token)); +} + +const char * +http_request_getUri (const HttpRequest *request) +{ + assert (request != NULL); + + return (http_request_getInternalString ( + stringdictionary_getValue (request->transactionVariables, + "uri"))); +} + +const char * +http_request_getQuery (const HttpRequest *request) +{ + assert (request != NULL); + + return (http_request_getInternalString ( + stringdictionary_getValue (request->transactionVariables, + "query"))); +} + +const char * +http_request_getRemoteIP (const HttpRequest *request) +{ + assert (request != NULL); + + return (dynFgetstr (request->remoteIP)); +} + +const dynTstring * +http_request_getVariableString (const HttpRequest *request, const char *variable) +{ + assert (request != NULL); + assert (variable != NULL); + + return (stringdictionary_getValue (request->transactionVariables, + variable)); +} + +const char * +http_request_getVariable (const HttpRequest *request, const char *variable) +{ + assert (request != NULL); + assert (variable != NULL); + + return (http_request_getInternalString ( + stringdictionary_getValue (request->transactionVariables, + variable))); +} + +const char * +http_request_getMethod (const HttpRequest *request) +{ + assert (request != NULL); + + return (http_request_getInternalString ( + stringdictionary_getValue (request->transactionVariables, + "method"))); +} + +bool +http_request_headersSent (const HttpRequest *request) +{ + assert (request != NULL); + + return (request->sentResponseHeaders); +} + +const dynTstring * +http_request_getRequestHeaderString (const HttpRequest *request, const char *key) +{ + assert (request != NULL); + + return (stringdictionary_getValue (request->requestHeaders, key)); +} + +hshTiterator * +http_request_getRequestHeaderIterator (const HttpRequest *request) +{ + return (stringdictionary_getIterator (request->requestHeaders)); +} + +const char * +http_request_getRequestHeader (const HttpRequest *request, const char *key) +{ + dynTstring *stringValue; + + assert (request != NULL); + assert (key != NULL); + + stringValue = stringdictionary_getValue (request->requestHeaders, key); + + if (stringValue == NULL) + { + return (NULL); + } + else + { + return (dynFgetstr (stringValue)); + } +} + +void +http_request_setResponseHeader (const HttpRequest *request, const char *key, const char *value) +{ + dynTstring *value_string = dynFinit(); + + assert (request != NULL); + assert (key != NULL); + assert (value != NULL); + + dynFsappend (value_string, value); + + stringdictionary_setValue (request->responseHeaders, key, value_string); +} + +void +http_request_setResponseHeaderData (const HttpRequest *request, const char *key, const char *value, int valueLen) +{ + dynTstring *value_string = dynFinit(); + + assert (request != NULL); + assert (key != NULL); + assert (value != NULL); + + dynFappend (value_string, value, valueLen); + + stringdictionary_setValue (request->responseHeaders, key, value_string); +} + +static void +http_request_populateInitial (HttpRequest *request, Message *requestMessage) +{ + dynTstring *serializedResponseHeaders; + dynTstring *status = dynFinit(); + + assert (request != NULL); + assert (requestMessage != NULL); + + /* insert responseHeaders */ + serializedResponseHeaders = serialization_serializeType ( + "StringDictionary", &request->responseHeaders); + + message_setParameterString (requestMessage, "responseHeaders", + serializedResponseHeaders); + + dynFfree (serializedResponseHeaders); + + /* insert status */ + dynFappend_print (status, "%d", request->responseStatus); + + message_setParameterString (requestMessage, "status", status); + + dynFfree (status); +} + +bool +http_request_writeData (HttpRequest *request, const char *data, const int dataLen) +{ + Message *requestMessage = message_newRequest ("HttpWrite"); + bool ret; + + assert (request != NULL); + assert (data != NULL); + + message_setParameterString (requestMessage, "token", request->token); + message_setParameterBinary (requestMessage, "data", data, dataLen); + + if (request->sentResponseHeaders == false) + { + http_request_populateInitial (request, requestMessage); + + request->sentResponseHeaders = true; + } + + ret = http_response_sendSimpleMessage (request->processor, + requestMessage); + + message_destroy (requestMessage); + + return (ret); +} + +bool +http_request_writeString (HttpRequest *request, const char *data) +{ + assert (request != NULL); + assert (data != NULL); + + return (http_request_writeData (request, data, strlen (data))); +} + +bool +http_request_finishStatus (const HttpRequest *request, int status) +{ + bool ret; + + assert (request != NULL); + + ret = http_response_sendFinishMessage (request->processor, + dynFgetstr (request->token), status); + + return (ret); +} + +bool +http_request_finish (const HttpRequest *request) +{ + bool ret; + + assert (request != NULL); + + ret = http_response_sendFinishMessage (request->processor, + dynFgetstr (request->token), STATUS_EXIT); + + return (ret); +} + +static bool +http_request_loadEntity (HttpRequest *instance) +{ + assert (instance != NULL); + + if (instance->entityRequested == false) + { + if (http_response_sendReadEntityBody (instance->processor, + dynFgetstr (instance->token), instance->entity) == false) + { + /* logFmsg (CONT_LOG_ERROR, "causality-client: Could not send entity body request."); */ + + return (false); + } + + instance->entityRequested = true; + } + + return (true); +} + +const dynTstring * +http_request_getEntireEntity (HttpRequest *instance) +{ + assert (instance != NULL); + + if (http_request_loadEntity (instance) == false) + { + return (NULL); + } + + return (instance->entity); +} + +int +http_request_getEntity (HttpRequest *request, char *outBuf, const int bufLen) +{ + int size; + + assert (request != NULL); + assert (outBuf != NULL); + + if (http_request_loadEntity (request) == false) + { + return (-1); + } + + size = dynFgetlen (request->entity) - request->entityReadOffset; + + if (size > bufLen) + { + size = bufLen; + } + + if (size > 0) + { + memcpy (outBuf, dynFgetstr (request->entity) + request->entityReadOffset, size); + + request->entityReadOffset += size; + } + + return (size); +} + +bool +http_request_isEntireEntityLoaded (const HttpRequest *request) +{ + assert (request != NULL); + + if (request->entityRequested == true && + request->entityReadOffset == dynFgetlen (request->entity)) + { + return (true); + } + else + { + return (false); + } +} + +static const char * +http_request_getInternalString (dynTstring *string) +{ + if (string == NULL) + { + return (""); + } + else + { + return (dynFgetstr (string)); + } +} + +static bool +http_request_setIfNotNull (dynTstring *dest, const dynTstring *src) +{ + assert (dest != NULL); + + if (src == NULL) + { + return (false); + } + + dynFappend_string (dest, src); + + return (true); +} + diff --git a/lc-continuity/mk4/lib/causality-client/src/http_request_handler.c b/lc-continuity/mk4/lib/causality-client/src/http_request_handler.c new file mode 100644 index 0000000000000000000000000000000000000000..b06a2588d386531f8c505687891fef739af5d77c --- /dev/null +++ b/lc-continuity/mk4/lib/causality-client/src/http_request_handler.c @@ -0,0 +1,67 @@ + +#include + +#include "processor.h" +#include "http_request_list.h" +#include "http_request_handler.h" + +#include "command.h" + +static const char *command_HttpRequestStart_RequiredParameters[] = { "token", "variables", "headers", "remoteIP", NULL }; +static const char *command_HttpRequestStart_OptionalParameters[] = { "method", "uri", "protocol", "query", NULL }; +CommandHandler command_HttpRequestStart = { "HttpRequestStart", http_request_handler_handleRequest, + command_HttpRequestStart_RequiredParameters, command_HttpRequestStart_OptionalParameters }; + +static const char *command_HttpRequestPing_RequiredParameters[] = { "token", NULL }; +static const char *command_HttpRequestPing_OptionalParamaters[] = { NULL }; +CommandHandler command_HttpRequestPing = { "HttpRequestPing", http_request_handler_handlePing, + command_HttpRequestPing_RequiredParameters, command_HttpRequestPing_OptionalParamaters }; + +static Message * +http_request_handler_createResponseMessage (Message *requestMessage) +{ + Message *responseMessage = message_makeResponse (requestMessage); + + message_setParameter (responseMessage, "message", "Request Queued."); + + return (responseMessage); +} + +Message * +http_request_handler_handleRequest (void *context, Message *requestMessage) +{ + Processor *proc = (Processor *) context; + HttpRequestList *handlerList = http_request_list_getRequestList(); + HttpRequest *request = http_request_new (requestMessage, proc); + + http_request_list_addRequest (handlerList, request); + + return (http_request_handler_createResponseMessage (requestMessage)); +} + +Message * +http_request_handler_handlePing (MECHA_UNUSED void *context, Message *requestMessage) +{ + HttpRequestList *handlerList = http_request_list_getRequestList(); + const char *token; + + token = message_getParameter (requestMessage, "token"); + + if (http_request_list_containsRequest (handlerList, token)) + { + Message *responseMessage = message_makeResponse (requestMessage); + + message_setParameter (responseMessage, "message", "Request found."); + + return (responseMessage); + } + else + { + Message *responseMessage = message_makeErrorResponse (requestMessage); + + message_setParameter (responseMessage, "message", "Request not found."); + + return (responseMessage); + } +} + diff --git a/lc-continuity/mk4/lib/causality-client/src/http_request_list.c b/lc-continuity/mk4/lib/causality-client/src/http_request_list.c new file mode 100644 index 0000000000000000000000000000000000000000..82715af33eb4ef7433aca08369329b7dc50cc924 --- /dev/null +++ b/lc-continuity/mk4/lib/causality-client/src/http_request_list.c @@ -0,0 +1,133 @@ + +#include +#include + +#include "http_request_queue.h" +#include "http_request_list.h" + +#include "http_request_list_entry.h" +#include "threadpool.h" + +struct s_HttpRequestList +{ + HttpRequestQueue *queue; + + HttpRequestHandlerDelegate handler; + void *handlerContext; + + hshTvoid_list *list; + pthread_rwlock_t listLock; +}; + +HttpRequestList *g_http_request_list = NULL; +static pthread_once_t g_http_request_list_once = PTHREAD_ONCE_INIT; + + +static void http_request_list_setupInstance (void); + +HttpRequestList * +http_request_list_new() +{ + HttpRequestList *request = malloc (sizeof (HttpRequestList)); + + request->list = hshFvoid_init (http_request_destroy); + request->queue = http_request_queue_new(); + request->handler = NULL; + + pthread_rwlock_init (&request->listLock, NULL); + + return (request); +} + +void +http_request_list_destroy (void *ptr) +{ + HttpRequestList *request = (HttpRequestList *) ptr; + + http_request_queue_destroy (request->queue); + + hshFvoid_destroy (request->list); + + free (request); +} + +void +http_request_list_setHandler (HttpRequestList *instance, + HttpRequestHandlerDelegate delegate, void *context) +{ + pthread_rwlock_wrlock (&instance->listLock); + + instance->handler = delegate; + instance->handlerContext = context; + + pthread_rwlock_unlock (&instance->listLock); +} + +bool +http_request_list_containsRequest (HttpRequestList *requestList, const char *token) +{ + bool ret; + + pthread_rwlock_rdlock (&requestList->listLock); + + ret = hshFvoid_contains (requestList->list, token); + + pthread_rwlock_unlock (&requestList->listLock); + + return (ret); +} + +static void +http_request_list_setupInstance() +{ + g_http_request_list = http_request_list_new(); +} + +HttpRequestList * +http_request_list_getRequestList() +{ + pthread_once (&g_http_request_list_once, http_request_list_setupInstance); + + return (g_http_request_list); +} + +void +http_request_list_addRequest (HttpRequestList *requestList, HttpRequest *request) +{ + pthread_rwlock_wrlock (&requestList->listLock); + + hshFvoid_add (requestList->list, http_request_getToken (request), request); + + if (requestList->handler != NULL) + { + HttpRequestListEntry *entry = + http_request_list_entry_new (requestList->handler, request, + requestList->handlerContext); + + /* entry will be cleaned up by itself after the call is completed */ + threadpool_queueUserWorkItem (threadpool_getInstance(), + http_request_list_entry_invokeEntry, entry); + } + else + { + http_request_queue_addRequest (requestList->queue, request); + } + + pthread_rwlock_unlock (&requestList->listLock); +} + +void +http_request_list_removeRequest (HttpRequestList *requestList, const char *token) +{ + pthread_rwlock_wrlock (&requestList->listLock); + + hshFvoid_del (requestList->list, token); + + pthread_rwlock_unlock (&requestList->listLock); +} + +HttpRequest * +http_request_list_getNextRequest (HttpRequestList *requestList) +{ + return (http_request_queue_getRequest (requestList->queue)); +} diff --git a/lc-continuity/mk4/lib/causality-client/src/http_request_list_entry.c b/lc-continuity/mk4/lib/causality-client/src/http_request_list_entry.c new file mode 100644 index 0000000000000000000000000000000000000000..f670a4141b59e3c8e6ece99afe415590685a84c0 --- /dev/null +++ b/lc-continuity/mk4/lib/causality-client/src/http_request_list_entry.c @@ -0,0 +1,44 @@ + +#include + +#include "http_request_list_entry.h" + +struct s_HttpRequestListEntry +{ + HttpRequestHandlerDelegate delegate; + HttpRequest *request; + void *context; +}; + +HttpRequestListEntry * +http_request_list_entry_new (HttpRequestHandlerDelegate delegate, + HttpRequest *request, void *context) +{ + HttpRequestListEntry *instance = (HttpRequestListEntry *) malloc (sizeof (HttpRequestListEntry)); + + instance->delegate = delegate; + instance->request = request; + instance->context = context; + + return (instance); +} + +void +http_request_list_entry_destroy (void *ptr) +{ + HttpRequestListEntry *instance = (HttpRequestListEntry *) ptr; + + /* free other fields */ + + free (instance); +} + +void +http_request_list_entry_invokeEntry (void *ptr) +{ + HttpRequestListEntry *instance = (HttpRequestListEntry *) ptr; + + instance->delegate (instance->request, instance->context); + + http_request_list_entry_destroy (instance); +} diff --git a/lc-continuity/mk4/lib/causality-client/src/http_request_queue.c b/lc-continuity/mk4/lib/causality-client/src/http_request_queue.c new file mode 100644 index 0000000000000000000000000000000000000000..1b741845e0529ba28212aa3ea8385b8bfe3ef19b --- /dev/null +++ b/lc-continuity/mk4/lib/causality-client/src/http_request_queue.c @@ -0,0 +1,75 @@ + + +#include +#include +#include +#include + +#include "http_request_queue.h" +#include "message.h" + +struct s_HttpRequestQueue +{ + lstTlist *queue; + pthread_mutex_t queueMutex; + sem_t queueSemaphore; +}; + +HttpRequestQueue * +http_request_queue_new() +{ + HttpRequestQueue *resp = malloc (sizeof (HttpRequestQueue)); + + sem_init (&resp->queueSemaphore, 0, 0); + pthread_mutex_init (&resp->queueMutex, NULL); + + resp->queue = lstFlist_create (NULL); + + return (resp); +} + +void +http_request_queue_destroy (void *ptr) +{ + HttpRequestQueue *resp = (HttpRequestQueue *) ptr; + + sem_destroy (&resp->queueSemaphore); + pthread_mutex_destroy (&resp->queueMutex); + + lstFlist_free (resp->queue); + + free (resp); +} + +HttpRequest * +http_request_queue_getRequest (HttpRequestQueue *resp) +{ + HttpRequest *request; + + /* this will block until it is 1 */ + sem_wait (&resp->queueSemaphore); + + pthread_mutex_lock (&resp->queueMutex); + + assert (lstFlist_size (resp->queue) > 0); + + lstFlist_remove (resp->queue, lstFlist_head (resp->queue), (void **) &request); + + pthread_mutex_unlock (&resp->queueMutex); + + return (request); +} + +void +http_request_queue_addRequest (HttpRequestQueue *resp, HttpRequest *request) +{ + pthread_mutex_lock (&resp->queueMutex); + + lstFlist_add_next (resp->queue, lstFlist_tail (resp->queue), request); + + pthread_mutex_unlock (&resp->queueMutex); + + /* this will increment the semaphore to 1 */ + sem_post (&resp->queueSemaphore); +} + diff --git a/lc-continuity/mk4/lib/causality-client/src/http_response.c b/lc-continuity/mk4/lib/causality-client/src/http_response.c new file mode 100644 index 0000000000000000000000000000000000000000..ad1212cc2a8fbf8ca9f9a8efb45d4d11af8cbc5f --- /dev/null +++ b/lc-continuity/mk4/lib/causality-client/src/http_response.c @@ -0,0 +1,124 @@ + +#include + +#include "processor.h" +#include "message.h" + +#include "http_response.h" + +bool +http_response_sendSimpleMessage (Processor *processor, Message *requestMessage) +{ + Message *responseMessage; + bool ret; + + ret = processor_sendMessage (processor, requestMessage, &responseMessage); + + if (ret == false) + { + logFmsg (CONT_LOG_ERROR, "%d/Could not send message.", getpid()); + } + else + { + if (message_getType (responseMessage) == MessageTypeErrorResponse) + { + logFmsg (CONT_LOG_DEBUG, "causality-client: An error was returned."); + + message_print (responseMessage); + + ret = false; + } + else + { + ret = true; + } + + message_destroy (responseMessage); + } + + return (ret); +} + +bool +http_response_sendFinishMessage (Processor *processor, const char *token, + int returnStatus) +{ + Message *requestMessage; + Message *responseMessage; + bool ret; + + requestMessage= message_newRequest ("HttpFinish"); + + message_setParameter (requestMessage, "token", token); + + message_setParameterInt (requestMessage, "returnStatus", returnStatus); + + ret = processor_sendMessage (processor, requestMessage, &responseMessage); + + if (ret == false) + { + logFmsg (CONT_LOG_ERROR, "%d/Could not send message.", getpid()); + } + else + { + if (message_getType (responseMessage) == MessageTypeErrorResponse) + { + logFmsg (CONT_LOG_DEBUG, "causality-client: An error was returned."); + + message_print (responseMessage); + + ret = false; + } + else + { + ret = true; + } + + message_destroy (responseMessage); + } + + message_destroy (requestMessage); + + return (ret); +} + +bool +http_response_sendReadEntityBody (Processor *processor, const char *token, dynTstring *entity) +{ + Message *requestMessage; + Message *responseMessage; + bool ret; + + requestMessage= message_newRequest ("HttpReadEntityBody"); + + message_setParameter (requestMessage, "token", token); + + ret = processor_sendMessage (processor, requestMessage, &responseMessage); + + if (ret == false) + { + logFmsg (CONT_LOG_ERROR, "%d/Could not send message.", getpid()); + } + else + { + if (message_getType (responseMessage) == MessageTypeErrorResponse) + { + ret = false; + } + else + { + ret = true; + + dynFappend_string (entity, + message_getParameterString (responseMessage, "data")); + } + + message_destroy (responseMessage); + } + + message_destroy (requestMessage); + + return (ret); +} + + diff --git a/lc-continuity/mk4/lib/causality/CVS/Entries b/lc-continuity/mk4/lib/causality/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..76ba71d128d688636b5e29803f98031620ccd535 --- /dev/null +++ b/lc-continuity/mk4/lib/causality/CVS/Entries @@ -0,0 +1,3 @@ +/Makefile/1.1/Thu May 13 21:05:12 2004//Tmk4_mod6_rc2 +D/include//// +D/src//// diff --git a/lc-continuity/mk4/lib/causality/CVS/Repository b/lc-continuity/mk4/lib/causality/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..58bf00e81053148862c5c6f02b3a95651f961c74 --- /dev/null +++ b/lc-continuity/mk4/lib/causality/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/lib/causality diff --git a/lc-continuity/mk4/lib/causality/CVS/Root b/lc-continuity/mk4/lib/causality/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/lib/causality/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/lib/causality/CVS/Tag b/lc-continuity/mk4/lib/causality/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/lib/causality/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/lib/causality/Makefile b/lc-continuity/mk4/lib/causality/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..a82a067fbc855e35a52a74d3b9e7bedc0e77d184 --- /dev/null +++ b/lc-continuity/mk4/lib/causality/Makefile @@ -0,0 +1,15 @@ +CONTINUITY = ../../continuity + +TARGET = causality +TARGETTYPE = shared static + +SOURCES = src/message.c src/processor.c src/sysvipc.c \ + src/responseholder.c src/responseholderlist.c \ + src/request_dispatcher.c src/request_handler_entry.c \ + src/command_handlers.c src/threadpool.c src/message_processor.c + +INCLUDES += -Iinclude -I../aura/include +STATIC_LIBS += ../aura/libaura.a +#LOCAL_CFLAGS += + +include $(CONTINUITY)/lib/build.mk diff --git a/lc-continuity/mk4/lib/causality/include/CVS/Entries b/lc-continuity/mk4/lib/causality/include/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..845904671eb5e538bd94f218f72cc16bfc8d430d --- /dev/null +++ b/lc-continuity/mk4/lib/causality/include/CVS/Entries @@ -0,0 +1,12 @@ +/command.h/1.1/Thu May 13 21:05:12 2004//Tmk4_mod6_rc2 +/command_handlers.h/1.1/Thu May 13 21:05:12 2004//Tmk4_mod6_rc2 +/message.h/1.1/Thu May 13 21:05:12 2004//Tmk4_mod6_rc2 +/message_processor.h/1.1/Thu May 13 21:05:12 2004//Tmk4_mod6_rc2 +/processor.h/1.2/Fri May 14 06:20:33 2004//Tmk4_mod6_rc2 +/request_dispatcher.h/1.1/Thu May 13 21:05:12 2004//Tmk4_mod6_rc2 +/request_handler_entry.h/1.1/Thu May 13 21:05:12 2004//Tmk4_mod6_rc2 +/responseholder.h/1.1/Thu May 13 21:05:12 2004//Tmk4_mod6_rc2 +/responseholderlist.h/1.1/Thu May 13 21:05:12 2004//Tmk4_mod6_rc2 +/sysvipc.h/1.1/Thu May 13 21:05:12 2004//Tmk4_mod6_rc2 +/threadpool.h/1.1/Thu May 13 21:05:12 2004//Tmk4_mod6_rc2 +D diff --git a/lc-continuity/mk4/lib/causality/include/CVS/Repository b/lc-continuity/mk4/lib/causality/include/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..9693b65c65a931a29d8008d0d322925721b67242 --- /dev/null +++ b/lc-continuity/mk4/lib/causality/include/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/lib/causality/include diff --git a/lc-continuity/mk4/lib/causality/include/CVS/Root b/lc-continuity/mk4/lib/causality/include/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/lib/causality/include/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/lib/causality/include/CVS/Tag b/lc-continuity/mk4/lib/causality/include/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/lib/causality/include/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/lib/causality/include/command.h b/lc-continuity/mk4/lib/causality/include/command.h new file mode 100644 index 0000000000000000000000000000000000000000..70a0daee8dc165ab4ac2ded22573f32c1832e918 --- /dev/null +++ b/lc-continuity/mk4/lib/causality/include/command.h @@ -0,0 +1,18 @@ +#ifndef __COMMAND_H__ +#define __COMMAND_H__ + +#include "message.h" + +typedef Message * (*CommandHandlerDelegate) (void *context, Message *requestMessage); + +struct s_CommandHandler +{ + const char *commandName; + CommandHandlerDelegate handler; + const char **requiredParameters; + const char **optionalParameters; +}; + +typedef struct s_CommandHandler CommandHandler; + +#endif diff --git a/lc-continuity/mk4/lib/causality/include/command_handlers.h b/lc-continuity/mk4/lib/causality/include/command_handlers.h new file mode 100644 index 0000000000000000000000000000000000000000..2593583cb7c6b382b35fd61c21ef06724cbfe264 --- /dev/null +++ b/lc-continuity/mk4/lib/causality/include/command_handlers.h @@ -0,0 +1,21 @@ +#ifndef __REQUESTHANDLERS_H_ +#define __REQUESTHANDLERS_H_ + +#include "message.h" +#include "processor.h" + +typedef struct s_CommandHandlers CommandHandlers; + +/* +typedef Message * (*RequestHandler) (Message *requestMessage); +*/ + +CommandHandlers * command_handlers_new (void); +void command_handlers_destroy (void *ptr); + +bool command_handlers_addHandler (CommandHandlers *reqs, const CommandHandler *handler, void *context); + + +void command_handlers_processMessage (CommandHandlers *reqs, Message *message, Processor *processor); + +#endif diff --git a/lc-continuity/mk4/lib/causality/include/message.h b/lc-continuity/mk4/lib/causality/include/message.h new file mode 100644 index 0000000000000000000000000000000000000000..eab0bb6609909df4de7c02621c2cbd31ef7e748a --- /dev/null +++ b/lc-continuity/mk4/lib/causality/include/message.h @@ -0,0 +1,43 @@ +#ifndef __MESSAGE_H_ +#define __MESSAGE_H_ + +#include + +enum e_MessageType +{ + MessageTypeRequest, + MessageTypeResponse, + MessageTypeErrorResponse +}; + +typedef enum e_MessageType MessageType; + +typedef struct s_Message Message; + +Message * message_new (const char *name, MessageType type); +void message_destroy (void *ptr); + +Message * message_newRequest (const char *command); + +void message_setParameter (Message *message, const char *key, const char *value); +const char * message_getParameter (Message *message, const char *key); + +void message_setParameterBinary (Message *message, const char *key, const char *value, int valueLen); +void message_setParameterString (Message *message, const char *key, const dynTstring *value); +void message_setParameterInt (Message *message, const char *key, const int value); + +const char * message_getCommand (Message *message); +MessageType message_getType (Message *message); + +void message_setSequence (Message *message, int sequence); +int message_getSequence (Message *message); + +Message * message_makeResponse (Message *request); +Message * message_makeErrorResponse (Message *request); + +void message_print (Message *message); + +dynTstring * message_getParameterString (Message *message, const char *key); + + +#endif diff --git a/lc-continuity/mk4/lib/causality/include/message_processor.h b/lc-continuity/mk4/lib/causality/include/message_processor.h new file mode 100644 index 0000000000000000000000000000000000000000..4a47e0b58a22467e113e85dbdb0905d17777dc36 --- /dev/null +++ b/lc-continuity/mk4/lib/causality/include/message_processor.h @@ -0,0 +1,19 @@ +#ifndef __MESSAGE_PROCESSOR_H__ +#define __MESSAGE_PROCESSOR_H__ + +#include "mecha.h" +#include "responseholderlist.h" +#include "command_handlers.h" +#include "processor.h" + +typedef struct s_MessageProcessor MessageProcessor; + +MessageProcessor * +message_processor_new (dynTstring *message, ResponseHolderList *responses, + CommandHandlers *commandHandlers, Processor *processor); + +void message_processor_destroy (void *ptr); +void message_processor_process (void *context); + + +#endif diff --git a/lc-continuity/mk4/lib/causality/include/processor.h b/lc-continuity/mk4/lib/causality/include/processor.h new file mode 100644 index 0000000000000000000000000000000000000000..5f3b73e53dca71cee09a480ecdf22ad6c8099867 --- /dev/null +++ b/lc-continuity/mk4/lib/causality/include/processor.h @@ -0,0 +1,22 @@ +#ifndef __PROCESSOR_H_ +#define __PROCESSOR_H_ + +#include "message.h" +#include "request_handler_entry.h" + +typedef struct s_Processor Processor; + +Processor * processor_new (const key_t ipcKey, bool isClient); +void processor_destroy (void *ptr); + +bool processor_sendMessage (Processor *proc, Message *msg, Message **receiveMessage); +Message * processor_getMessage (Processor *proc); + +bool processor_sendMessageResponse (Processor *proc, Message *msg); + +void processor_addRequestHandler (Processor *processor, const CommandHandler *handler, void *context); + +void processor_finishedInit (Processor *processor); + + +#endif diff --git a/lc-continuity/mk4/lib/causality/include/request_dispatcher.h b/lc-continuity/mk4/lib/causality/include/request_dispatcher.h new file mode 100644 index 0000000000000000000000000000000000000000..f80cc3a3bfb91256c1efbb376b078d852db66263 --- /dev/null +++ b/lc-continuity/mk4/lib/causality/include/request_dispatcher.h @@ -0,0 +1,12 @@ +#ifndef __REQUEST_DISPATCHER_H__ +#define __REQUEST_DISPATCHER_H__ + +typedef struct s_RequestDispatcher RequestDispatcher; + +RequestDispatcher * request_dispatcher_new (Processor *processor, RequestHandlerEntry *handlerEntry, Message *requestMessage); + +void request_dispatcher_destroy (void *ptr); + +void request_dispatcher_process (void *requestDispatcherPtr); + +#endif diff --git a/lc-continuity/mk4/lib/causality/include/request_handler_entry.h b/lc-continuity/mk4/lib/causality/include/request_handler_entry.h new file mode 100644 index 0000000000000000000000000000000000000000..44306c7d02bd7e3055a4d1564bf158df834b85ed --- /dev/null +++ b/lc-continuity/mk4/lib/causality/include/request_handler_entry.h @@ -0,0 +1,17 @@ +#ifndef __REQUEST_HANDLER_ENTRY_H__ +#define __REQUEST_HANDLER_ENTRY_H__ + +#include "message.h" +#include "command.h" + +typedef struct s_RequestHandlerEntry RequestHandlerEntry; + +typedef Message * (*RequestHandler) (void *context, Message *requestMessage); + +RequestHandlerEntry * request_handler_entry_new (const CommandHandler *handler, void *context); +void request_handler_entry_destroy (void *ptr); + +const CommandHandler *request_handler_entry_getHandler (RequestHandlerEntry *entry); +void * request_handler_entry_getContext (RequestHandlerEntry *entry); + +#endif diff --git a/lc-continuity/mk4/lib/causality/include/responseholder.h b/lc-continuity/mk4/lib/causality/include/responseholder.h new file mode 100644 index 0000000000000000000000000000000000000000..565a7d1d3fe1a7750cea3f283a5309040b92709e --- /dev/null +++ b/lc-continuity/mk4/lib/causality/include/responseholder.h @@ -0,0 +1,15 @@ +#ifndef __RESPONSEHOLDER_H_ +#define __RESPONSEHOLDER_H_ + +#include "message.h" + +typedef struct s_ResponseHolder ResponseHolder; + +ResponseHolder * responseholder_new (int seq); +void responseholder_destroy (void *ptr); +Message * responseholder_getResponse (ResponseHolder *resp); + +void responseholder_setResponse (ResponseHolder *resp, Message *message); + + +#endif diff --git a/lc-continuity/mk4/lib/causality/include/responseholderlist.h b/lc-continuity/mk4/lib/causality/include/responseholderlist.h new file mode 100644 index 0000000000000000000000000000000000000000..94dbcfd9f84833b531e447dad003bb887adcd6de --- /dev/null +++ b/lc-continuity/mk4/lib/causality/include/responseholderlist.h @@ -0,0 +1,16 @@ +#ifndef __RESPONSEHOLDERLIST_H_ +#define __RESPONSEHOLDERLIST_H_ + +#include "message.h" + +typedef struct s_ResponseHolderList ResponseHolderList; + +ResponseHolderList * responseholderlist_new (void); +void responseholderlist_destroy (void *ptr); + +Message * responseholderlist_getResponse (ResponseHolderList *response_list, int seq); +void responseholderlist_setResponse (ResponseHolderList *response_list, Message *response); +void responseholderlist_addResponseHolder (ResponseHolderList *response_list, int sequence); + + +#endif diff --git a/lc-continuity/mk4/lib/causality/include/sysvipc.h b/lc-continuity/mk4/lib/causality/include/sysvipc.h new file mode 100644 index 0000000000000000000000000000000000000000..e71c2d3a73e3c43d93625df2d23fa033ffc17680 --- /dev/null +++ b/lc-continuity/mk4/lib/causality/include/sysvipc.h @@ -0,0 +1,23 @@ +#ifndef __SYSVIPC_H_ +#define __SYSVIPC_H + +#include "mecha.h" + +enum e_IPCDisposition +{ + IPCClient, + IPCServer +}; + +typedef enum e_IPCDisposition IPCDisposition; + +typedef struct s_SysVIPC SysVIPC; + +SysVIPC * sysvipc_new (const key_t ipcKey, IPCDisposition disposition); +void sysvipc_destroy (void *ptr); + +bool sysvipc_sendData (SysVIPC *ipc, dynTstring *data); +dynTstring * sysvipc_getData (SysVIPC *ipc); + + +#endif diff --git a/lc-continuity/mk4/lib/causality/include/threadpool.h b/lc-continuity/mk4/lib/causality/include/threadpool.h new file mode 100644 index 0000000000000000000000000000000000000000..45882ec185edcd50eff5b3b56bc8a14258eecc29 --- /dev/null +++ b/lc-continuity/mk4/lib/causality/include/threadpool.h @@ -0,0 +1,15 @@ +#ifndef __THREADPOOL_H__ +#define __THREADPOOL_H__ + +#include "type.h" + +typedef struct s_ThreadPool ThreadPool; + +typedef void (*WorkItemDelegate) (void *context); + +ThreadPool * threadpool_new (void); +void threadpool_destroy (void *ptr); +ThreadPool * threadpool_getInstance (void); +bool threadpool_queueUserWorkItem (ThreadPool *pool, WorkItemDelegate delegate, void *context); + +#endif diff --git a/lc-continuity/mk4/lib/causality/src/CVS/Entries b/lc-continuity/mk4/lib/causality/src/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..6b3e1b025061aa76d02f24d4f04c2a948b18fb46 --- /dev/null +++ b/lc-continuity/mk4/lib/causality/src/CVS/Entries @@ -0,0 +1,12 @@ +/command.c/1.1/Thu May 13 21:05:12 2004//Tmk4_mod6_rc2 +/command_handlers.c/1.1/Thu May 13 21:05:12 2004//Tmk4_mod6_rc2 +/message.c/1.1/Thu May 13 21:05:12 2004//Tmk4_mod6_rc2 +/message_processor.c/1.2/Fri May 14 19:12:09 2004//Tmk4_mod6_rc2 +/processor.c/1.1/Thu May 13 21:05:12 2004//Tmk4_mod6_rc2 +/request_dispatcher.c/1.1/Thu May 13 21:05:12 2004//Tmk4_mod6_rc2 +/request_handler_entry.c/1.1/Thu May 13 21:05:12 2004//Tmk4_mod6_rc2 +/responseholder.c/1.1/Thu May 13 21:05:12 2004//Tmk4_mod6_rc2 +/responseholderlist.c/1.1/Thu May 13 21:05:12 2004//Tmk4_mod6_rc2 +/sysvipc.c/1.4/Thu Jun 24 15:45:47 2004//Tmk4_mod6_rc2 +/threadpool.c/1.2/Thu Jun 24 15:45:48 2004//Tmk4_mod6_rc2 +D diff --git a/lc-continuity/mk4/lib/causality/src/CVS/Repository b/lc-continuity/mk4/lib/causality/src/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..6490ffab98771138bc633b74d3cd2f9fae010c83 --- /dev/null +++ b/lc-continuity/mk4/lib/causality/src/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/lib/causality/src diff --git a/lc-continuity/mk4/lib/causality/src/CVS/Root b/lc-continuity/mk4/lib/causality/src/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/lib/causality/src/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/lib/causality/src/CVS/Tag b/lc-continuity/mk4/lib/causality/src/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/lib/causality/src/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/lib/causality/src/command.c b/lc-continuity/mk4/lib/causality/src/command.c new file mode 100644 index 0000000000000000000000000000000000000000..f119d9a33b3cf1b102b6a9f8570c6e33b5ecb98b --- /dev/null +++ b/lc-continuity/mk4/lib/causality/src/command.c @@ -0,0 +1,21 @@ + +#include + + +#include "command.h" + +static Message * test_command_handler (void *context, Message *requestMessage); + +static const char *requiredParameters[] = { "one", "two", NULL }; +static const char *optionalParameters[] = { NULL }; +CommandHandler test_command = { "test", test_command_handler, requiredParameters, optionalParameters }; + +Message * +test_command_handler (void *context, Message *requestMessage) +{ + + + return (NULL); +} + + diff --git a/lc-continuity/mk4/lib/causality/src/command_handlers.c b/lc-continuity/mk4/lib/causality/src/command_handlers.c new file mode 100644 index 0000000000000000000000000000000000000000..995b7ef3a4d4a9628399af4da71f3a41079b0d4f --- /dev/null +++ b/lc-continuity/mk4/lib/causality/src/command_handlers.c @@ -0,0 +1,68 @@ + +#include + +#include "mecha.h" + +#include "command_handlers.h" +#include "processor.h" +#include "request_dispatcher.h" + +#include "request_handler_entry.h" + +#include "threadpool.h" + +struct s_CommandHandlers +{ + hshTvoid_list *handlers; +}; + +CommandHandlers * +command_handlers_new() +{ + CommandHandlers *reqs = malloc (sizeof (CommandHandlers)); + + reqs->handlers = hshFvoid_init (request_handler_entry_destroy); + + return (reqs); +} + +void +command_handlers_destroy (void *ptr) +{ + CommandHandlers *reqs = (CommandHandlers *) ptr; + + hshFvoid_destroy (reqs->handlers); + + free (reqs); +} + +bool +command_handlers_addHandler (CommandHandlers *reqs, const CommandHandler *handler, void *context) +{ + RequestHandlerEntry *entry = request_handler_entry_new (handler, context); + + if (hshFvoid_add (reqs->handlers, handler->commandName, entry)) + { + return (true); + } + else + { + return (false); + } +} + +void +command_handlers_processMessage (CommandHandlers *reqs, Message *message, Processor *processor) +{ + RequestDispatcher *dispatcher; + RequestHandlerEntry *handlerEntry; + + handlerEntry = (RequestHandlerEntry *) hshFvoid_find (reqs->handlers, + message_getCommand (message)); + + dispatcher = request_dispatcher_new (processor, handlerEntry, message); + + threadpool_queueUserWorkItem ( + threadpool_getInstance(), request_dispatcher_process, dispatcher); +} + diff --git a/lc-continuity/mk4/lib/causality/src/message.c b/lc-continuity/mk4/lib/causality/src/message.c new file mode 100644 index 0000000000000000000000000000000000000000..437ec3c92ff9d8d41e76ce450ed5433c0b77d940 --- /dev/null +++ b/lc-continuity/mk4/lib/causality/src/message.c @@ -0,0 +1,226 @@ + +#include +#include + +#include + +#include "serialization.h" +#include "stringdictionary.h" +#include "message.h" + +struct s_Message +{ + char *command; + int sequence; + MessageType type; + StringDictionary *params; +}; + +static bool message_serialize (void *field, SerializationInfo *info); +static bool message_deserialize (void *field, SerializationInfo *info); + +Type type_declaration_Message = { "Message", message_serialize, message_deserialize }; + + +Message * +message_new (const char *command, MessageType type) +{ + Message *message = malloc (sizeof (Message)); + + message->command = strdup (command); + message->type = type; + message->params = stringdictionary_new(); + + return (message); +} + +void +message_destroy (void *ptr) +{ + Message *message = (Message *) ptr; + + free (message->command); + + stringdictionary_destroy (message->params); + + free (message); +} + +Message * +message_newRequest (const char *command) +{ + return (message_new (command, MessageTypeRequest)); +} + +MessageType +message_getType (Message *message) +{ + return (message->type); +} + +Message * +message_makeResponse (Message *request) +{ + Message *response = message_new (message_getCommand (request), MessageTypeResponse); + + response->sequence = request->sequence; + + return (response); +} + +Message * +message_makeErrorResponse (Message *request) +{ + Message *response = message_new (message_getCommand (request), MessageTypeErrorResponse); + + response->sequence = request->sequence; + + return (response); +} + +int +message_getSequence (Message *message) +{ + return (message->sequence); +} + +void +message_setSequence (Message *message, int sequence) +{ + message->sequence = sequence; +} + +void +message_setParameter (Message *message, const char *key, const char *value) +{ + dynTstring *stringValue = dynFinit(); + + dynFsappend (stringValue, value); + + stringdictionary_setValue (message->params, key, stringValue); +} + +void +message_setParameterInt (Message *message, const char *key, const int value) +{ + dynTstring *stringValue = dynFinit(); + + dynFappend_print (stringValue, "%d", value); + + stringdictionary_setValue (message->params, key, stringValue); +} + +void +message_setParameterString (Message *message, const char *key, const dynTstring *value) +{ + dynTstring *stringValue = dynFinit(); + + dynFappend_string (stringValue, value); + + stringdictionary_setValue (message->params, key, stringValue); +} + +void +message_setParameterBinary (Message *message, const char *key, const char *value, int valueLen) +{ + dynTstring *stringValue = dynFinit(); + + dynFappend (stringValue, value, valueLen); + + stringdictionary_setValue (message->params, key, stringValue); +} + +dynTstring * +message_getParameterString (Message *message, const char *key) +{ + return (stringdictionary_getValue (message->params, key)); +} + +const char * +message_getParameter (Message *message, const char *key) +{ + dynTstring *stringValue = stringdictionary_getValue (message->params, key); + + if (stringValue != NULL) + { + return (dynFgetstr (stringValue)); + } + else + { + return (NULL); + } +} + +const char * +message_getCommand (Message *message) +{ + return (message->command); +} + +void +message_print (Message *message) +{ + hshTiterator *iter; + + printf (" command: %s\n", message->command); + printf (" sequence: %d\n", message->sequence); + printf (" type: %d\n", message->type); + printf (" params:\n"); + + iter = stringdictionary_getIterator (message->params); + + while (hshFiterator_next (iter) == 1) + { + char *key = (char *) hshFiterator_current_key (iter); + dynTstring *value = (dynTstring *) hshFiterator_current_value (iter); + + printf (" %s: %s\n", key, dynFgetstr (value)); + } + + hshFiterator_free (iter); +} + +static bool +message_serialize (void *field, SerializationInfo *info) +{ + Message *message = DEREFERENCE_TYPE (Message, field); + + serializationinfo_addValue (info, "command", + serialization_serializeType ("String", &message->command)); + + serializationinfo_addValue (info, "sequence", + serialization_serializeType ("Int", &message->sequence)); + + serializationinfo_addValue (info, "type", + serialization_serializeType ("Int", &message->type)); + + serializationinfo_addValue (info, "params", + serialization_serializeType ("StringDictionary", &message->params)); + + return (true); +} + +static bool +message_deserialize (void *field, SerializationInfo *info) +{ + Message *message = malloc (sizeof (Message)); + Message **fieldPtr = (Message **) field; + + *fieldPtr = message; + /* DEREFERENCE_TYPE (Message, field) = message; */ + + serialization_deserializeType ("String", &message->command, + serializationinfo_getValue (info, "command")); + + serialization_deserializeType ("Int", &message->sequence, + serializationinfo_getValue (info, "sequence")); + + serialization_deserializeType ("Int", &message->type, + serializationinfo_getValue (info, "type")); + + serialization_deserializeType ("StringDictionary", &message->params, + serializationinfo_getValue (info, "params")); + + return (true); +} + diff --git a/lc-continuity/mk4/lib/causality/src/message_processor.c b/lc-continuity/mk4/lib/causality/src/message_processor.c new file mode 100644 index 0000000000000000000000000000000000000000..73eef40a77213cf0c3a3b7dc28208c25e2f4259d --- /dev/null +++ b/lc-continuity/mk4/lib/causality/src/message_processor.c @@ -0,0 +1,71 @@ + +#include "mecha.h" +#include "responseholderlist.h" +#include "command_handlers.h" +#include "processor.h" + +#include "serialization.h" + +#include "message_processor.h" + +struct s_MessageProcessor +{ + dynTstring *message; + ResponseHolderList *responses; + CommandHandlers *commandHandlers; + Processor *processor; +}; + +MessageProcessor * +message_processor_new (dynTstring *message, ResponseHolderList *responses, + CommandHandlers *commandHandlers, Processor *processor) +{ + MessageProcessor *mp = malloc (sizeof (MessageProcessor)); + + mp->message = message; + mp->responses = responses; + mp->commandHandlers = commandHandlers; + mp->processor = processor; + + return (mp); +} + +void +message_processor_destroy (void *ptr) +{ + MessageProcessor *mp = (MessageProcessor *) ptr; + + dynFfree (mp->message); + + free (mp); +} + +void +message_processor_process (void *context) +{ + MessageProcessor *mp = (MessageProcessor *) context; + Message *message; + bool ret; + + ret = serialization_deserializeType ("Message", &message, mp->message); + + if (ret == false) + { + logFmsg (CONT_LOG_ERROR, "Failed to deserialize message: %s", dynFgetstr (mp->message)); + } + else + { + if (message_getType (message) == MessageTypeRequest) + { + /* message will be destroyed when it is done being used */ + command_handlers_processMessage (mp->commandHandlers, message, mp->processor); + } + else + { + responseholderlist_setResponse (mp->responses, message); + } + } + + message_processor_destroy (mp); +} + diff --git a/lc-continuity/mk4/lib/causality/src/processor.c b/lc-continuity/mk4/lib/causality/src/processor.c new file mode 100644 index 0000000000000000000000000000000000000000..a42778eaa1986008da60f04c044a9f4d6d74adf7 --- /dev/null +++ b/lc-continuity/mk4/lib/causality/src/processor.c @@ -0,0 +1,243 @@ + +#include + +#include +#include +#include + + +#include +#include +#include + +#include "threadpool.h" +#include "message_processor.h" + +#include "message.h" +#include "processor.h" +#include "serialization.h" +#include "sysvipc.h" +#include "responseholder.h" +#include "responseholderlist.h" +#include "command_handlers.h" + +struct s_Processor +{ + SysVIPC *ipc; + + int last_sequence; + + ResponseHolderList *responses; + CommandHandlers *commandHandlers; + + pthread_t incoming_handler_thread; + + bool init_sync; + pthread_cond_t init_sync_cond; + pthread_mutex_t init_sync_mutex; +}; + +static void *processor_incomingHandler (void *arg); + +Processor * +processor_new (const key_t ipcKey, bool isClient) +{ + Processor *proc; + + proc = malloc (sizeof (Processor)); + + if (isClient == true) + { + proc->ipc = sysvipc_new (ipcKey, IPCClient); + } + else + { + proc->ipc = sysvipc_new (ipcKey, IPCServer); + } + + if (proc->ipc == NULL) + { + free (proc); + + return (NULL); + } + + proc->last_sequence = 0; + proc->responses = responseholderlist_new(); + proc->commandHandlers = command_handlers_new(); + + proc->init_sync = false; + + pthread_cond_init (&proc->init_sync_cond, NULL); + pthread_mutex_init (&proc->init_sync_mutex, NULL); + + pthread_create (&proc->incoming_handler_thread, NULL, processor_incomingHandler, proc); + + return (proc); +} + +void +processor_destroy (void *ptr) +{ + Processor *proc = (Processor *) ptr; + + pthread_cancel (proc->incoming_handler_thread); + pthread_join (proc->incoming_handler_thread, NULL); + + sysvipc_destroy (proc->ipc); + + pthread_cond_destroy (&proc->init_sync_cond); + pthread_mutex_destroy (&proc->init_sync_mutex); + + command_handlers_destroy (proc->commandHandlers); + + responseholderlist_destroy (proc->responses); + + free (proc); +} + +static int +processor_getNextSequence (Processor *proc) +{ + int next_seq = ++proc->last_sequence; + + return (next_seq); +} + +void +processor_finishedInit (Processor *processor) +{ + pthread_mutex_lock (&processor->init_sync_mutex); + + processor->init_sync = true; + + pthread_cond_broadcast (&processor->init_sync_cond); + pthread_mutex_unlock (&processor->init_sync_mutex); +} + +bool +processor_sendMessageResponse (Processor *proc, Message *msg) +{ + dynTstring *msgString; + bool ret; + + if (message_getType (msg) != MessageTypeResponse && + message_getType (msg) != MessageTypeErrorResponse) + { + return (false); + } + + msgString = serialization_serializeType ("Message", &msg); + + ret = sysvipc_sendData (proc->ipc, msgString); + + dynFfree (msgString); + + return (ret); +} + + +bool +processor_sendMessage (Processor *proc, Message *msg, Message **receiveMessage) +{ + dynTstring *msgString; + bool ret; + int seq; + + if (message_getType (msg) != MessageTypeRequest) + { + return (false); + } + + seq = processor_getNextSequence (proc); + + responseholderlist_addResponseHolder (proc->responses, seq); + + message_setSequence (msg, seq); + + msgString = serialization_serializeType ("Message", &msg); + + ret = sysvipc_sendData (proc->ipc, msgString); + + dynFfree (msgString); + + if (ret == false) + { + /* we're leaking ResponseHolders here */ + + abort(); + + return (false); + } + else + { + *receiveMessage = responseholderlist_getResponse (proc->responses, seq); + + if (*receiveMessage == NULL) + { + return (false); + } + else + { + return (true); + } + } +} + +void +processor_addRequestHandler (Processor *processor, const CommandHandler *handler, void *context) +{ + command_handlers_addHandler (processor->commandHandlers, handler, context); +} + +static void * +processor_incomingHandler (void *arg) +{ + Processor *proc = (Processor *) arg; + + { + /* + * we'll wait for 5 seconds until someone calls the signal + */ + struct timespec waitTime = { 0, 0 }; + + waitTime.tv_sec = time (0) + 5; + + pthread_mutex_lock (&proc->init_sync_mutex); + + if (proc->init_sync == false) + { + pthread_cond_timedwait (&proc->init_sync_cond, + &proc->init_sync_mutex, &waitTime); + } + + pthread_mutex_unlock (&proc->init_sync_mutex); + } + + while (true) + { + dynTstring *msgString; + MessageProcessor *msgProc; + + msgString = sysvipc_getData (proc->ipc); + + if (msgString == NULL) + { + logFmsg (CONT_LOG_ERROR, "IPC communication failed. Exiting handler."); + + return (NULL); + } + + /* + * there is obviously refactoring that needs to happen when we need to + * pass this much data in. + */ + msgProc = message_processor_new (msgString, proc->responses, + proc->commandHandlers, proc); + + threadpool_queueUserWorkItem ( + threadpool_getInstance(), message_processor_process, msgProc); + } + + return (NULL); +} diff --git a/lc-continuity/mk4/lib/causality/src/request_dispatcher.c b/lc-continuity/mk4/lib/causality/src/request_dispatcher.c new file mode 100644 index 0000000000000000000000000000000000000000..12321215f8a5ba3a2848c0e797bbc918ab558a58 --- /dev/null +++ b/lc-continuity/mk4/lib/causality/src/request_dispatcher.c @@ -0,0 +1,114 @@ + +#include +#include +#include + +#include "processor.h" +#include "command_handlers.h" +#include "request_dispatcher.h" +#include "request_handler_entry.h" + +struct s_RequestDispatcher +{ + Processor *processor; + RequestHandlerEntry *handlerEntry; + Message *requestMessage; +}; + + +RequestDispatcher * +request_dispatcher_new (Processor *processor, RequestHandlerEntry *handlerEntry, Message *requestMessage) +{ + RequestDispatcher *disp = malloc (sizeof (RequestDispatcher)); + + disp->processor = processor; + disp->handlerEntry = handlerEntry; + disp->requestMessage = requestMessage; + + return (disp); +} + +void +request_dispatcher_destroy (void *ptr) +{ + RequestDispatcher *disp = (RequestDispatcher *) ptr; + + message_destroy (disp->requestMessage); + + free (disp); +} + +static Message * +request_dispatcher_validateMessage (const CommandHandler *handler, + Message *requestMessage) +{ + Message *responseMessage = NULL; + dynTstring *errorMessage = dynFinit(); + int i; + + for (i = 0; handler->requiredParameters[i] != NULL; i++) + { + const char *value = message_getParameter (requestMessage, + handler->requiredParameters[i]); + + if (value == NULL) + { + dynFappend_print (errorMessage, "\nCould not find required parameter '%s'.", + handler->requiredParameters[i]); + } + } + + if (dynFgetlen (errorMessage) > 0) + { + responseMessage = message_makeErrorResponse (requestMessage); + + message_setParameterString (responseMessage, "message", errorMessage); + } + + dynFfree (errorMessage); + + return (responseMessage); +} + +void +request_dispatcher_process (void *requestDispatcherPtr) +{ + RequestDispatcher *dispatcher = (RequestDispatcher *) requestDispatcherPtr; + Message *responseMessage = NULL; + + if (dispatcher->handlerEntry == NULL) + { + responseMessage = message_makeErrorResponse (dispatcher->requestMessage); + + message_setParameter (responseMessage, "message", "Could not find command."); + } + else + { + const CommandHandler *handler = request_handler_entry_getHandler (dispatcher->handlerEntry); + void *context = request_handler_entry_getContext (dispatcher->handlerEntry); + + responseMessage = request_dispatcher_validateMessage (handler, + dispatcher->requestMessage); + + if (responseMessage == NULL) + { + responseMessage = handler->handler (context, dispatcher->requestMessage); + + if (responseMessage == NULL) + { + responseMessage = message_makeErrorResponse (dispatcher->requestMessage); + + message_setParameter (responseMessage, "message", "Could not execute handler."); + } + } + } + + if (processor_sendMessageResponse (dispatcher->processor, responseMessage) == false) + { + logFmsg (CONT_LOG_ERROR, "causality: could not send message."); + } + + message_destroy (responseMessage); + + request_dispatcher_destroy (dispatcher); +} diff --git a/lc-continuity/mk4/lib/causality/src/request_handler_entry.c b/lc-continuity/mk4/lib/causality/src/request_handler_entry.c new file mode 100644 index 0000000000000000000000000000000000000000..2f707da2ddb196bcdb4a34faa7f631485875a09e --- /dev/null +++ b/lc-continuity/mk4/lib/causality/src/request_handler_entry.c @@ -0,0 +1,43 @@ + +#include + +#include "request_handler_entry.h" +#include "command.h" + + +struct s_RequestHandlerEntry +{ + const CommandHandler *handler; + void *context; +}; + +RequestHandlerEntry * +request_handler_entry_new (const CommandHandler *handler, void *context) +{ + RequestHandlerEntry *entry = malloc (sizeof (RequestHandlerEntry)); + + entry->handler = handler; + entry->context = context; + + return (entry); +} + +void +request_handler_entry_destroy (void *ptr) +{ + RequestHandlerEntry *entry = (RequestHandlerEntry *) ptr; + + free (entry); +} + +const CommandHandler * +request_handler_entry_getHandler (RequestHandlerEntry *entry) +{ + return (entry->handler); +} + +void * +request_handler_entry_getContext (RequestHandlerEntry *entry) +{ + return (entry->context); +} diff --git a/lc-continuity/mk4/lib/causality/src/responseholder.c b/lc-continuity/mk4/lib/causality/src/responseholder.c new file mode 100644 index 0000000000000000000000000000000000000000..3ab4adb50442945285c7e0734f937ea5e4577baa --- /dev/null +++ b/lc-continuity/mk4/lib/causality/src/responseholder.c @@ -0,0 +1,84 @@ + +#include +#include + +#include "responseholder.h" + +#define MESSAGE_WAIT_SECONDS (5 * 60) + +struct s_ResponseHolder +{ + int sequence; + + pthread_cond_t cond; + pthread_mutex_t mutex; + + Message *response; +}; + +ResponseHolder * +responseholder_new (int seq) +{ + ResponseHolder *resp = malloc (sizeof (ResponseHolder)); + + resp->sequence = seq; + + pthread_cond_init (&resp->cond, NULL); + pthread_mutex_init (&resp->mutex, NULL); + + resp->response = NULL; + + return (resp); +} + +void +responseholder_destroy (void *ptr) +{ + ResponseHolder *resp = (ResponseHolder *) ptr; + + pthread_cond_destroy (&resp->cond); + pthread_mutex_destroy (&resp->mutex); + + free (resp); +} + +Message * +responseholder_getResponse (ResponseHolder *resp) +{ + Message *messageResponse = NULL; + + pthread_mutex_lock (&resp->mutex); + + if (resp->response == NULL) + { + struct timespec timeout; + + timeout.tv_sec = time(0) + MESSAGE_WAIT_SECONDS; + timeout.tv_nsec = 0; + + /* + * if this returns, we've either got our signal, or we timed out, + * either way, we're done waiting. + */ + pthread_cond_timedwait (&resp->cond, &resp->mutex, &timeout); + } + + messageResponse = resp->response; + + pthread_mutex_unlock (&resp->mutex); + + return (messageResponse); +} + +void +responseholder_setResponse (ResponseHolder *resp, Message *message) +{ + pthread_mutex_lock (&resp->mutex); + + resp->response = message; + + pthread_mutex_unlock (&resp->mutex); + + pthread_cond_signal (&resp->cond); +} + diff --git a/lc-continuity/mk4/lib/causality/src/responseholderlist.c b/lc-continuity/mk4/lib/causality/src/responseholderlist.c new file mode 100644 index 0000000000000000000000000000000000000000..b9eff484b0588d5bd67f3ac817129c53b9ec3c97 --- /dev/null +++ b/lc-continuity/mk4/lib/causality/src/responseholderlist.c @@ -0,0 +1,106 @@ + +#include +#include + +#include "responseholder.h" +#include "responseholderlist.h" + +struct s_ResponseHolderList +{ + hshTvoid_list *list; + + pthread_rwlock_t list_lock; + +}; + +ResponseHolderList * +responseholderlist_new() +{ + ResponseHolderList *response_list = malloc (sizeof (ResponseHolderList)); + + response_list->list = hshFvoid_int_init (responseholder_destroy); + + pthread_rwlock_init (&response_list->list_lock, NULL); + + return (response_list); +} + +void +responseholderlist_destroy (void *ptr) +{ + ResponseHolderList *response_list = (ResponseHolderList *) ptr; + + pthread_rwlock_destroy (&response_list->list_lock); + + hshFvoid_destroy (response_list->list); + + free (response_list); +} + + +void +responseholderlist_addResponseHolder (ResponseHolderList *response_list, int sequence) +{ + ResponseHolder *resp = responseholder_new (sequence); + + pthread_rwlock_wrlock (&response_list->list_lock); + + hshFvoid_int_add (response_list->list, sequence, resp); + + pthread_rwlock_unlock (&response_list->list_lock); +} + + +static ResponseHolder * +responseholderlist_getResponseHolder (ResponseHolderList *response_list, int sequence) +{ + ResponseHolder *resp; + + pthread_rwlock_rdlock (&response_list->list_lock); + + resp = (ResponseHolder *) hshFvoid_int_find (response_list->list, sequence); + + pthread_rwlock_unlock (&response_list->list_lock); + + return (resp); +} + +static void +responseholderlist_removeResponseHolder (ResponseHolderList *response_list, int sequence) +{ + pthread_rwlock_wrlock (&response_list->list_lock); + + hshFvoid_int_del (response_list->list, sequence); + + pthread_rwlock_unlock (&response_list->list_lock); +} + +Message * +responseholderlist_getResponse (ResponseHolderList *response_list, int seq) +{ + Message *responseMessage; + ResponseHolder *resp = responseholderlist_getResponseHolder (response_list, seq); + + responseMessage = responseholder_getResponse (resp); + + responseholderlist_removeResponseHolder (response_list, seq); + + return (responseMessage); +} + +void +responseholderlist_setResponse (ResponseHolderList *response_list, Message *response) +{ + ResponseHolder *resp = responseholderlist_getResponseHolder (response_list, + message_getSequence (response)); + + if (resp != NULL) + { + responseholder_setResponse (resp, response); + } + else + { + /* we don't know what this is responding to */ + } +} + diff --git a/lc-continuity/mk4/lib/causality/src/sysvipc.c b/lc-continuity/mk4/lib/causality/src/sysvipc.c new file mode 100644 index 0000000000000000000000000000000000000000..fc6654b586c82871a62829918add3dfef18e707c --- /dev/null +++ b/lc-continuity/mk4/lib/causality/src/sysvipc.c @@ -0,0 +1,321 @@ +#define _GNU_SOURCE 1 + +#include +#include +#include +#include + +#include +#include +#include + +#include "mecha.h" + +#include "sysvipc.h" + + +#define IPC_CLIENT_SEND_ID 1 +#define IPC_SERVER_SEND_ID 2 + +struct s_SysVIPC +{ + int queue_id; + IPCDisposition disposition; + + int last_seq; + pthread_mutex_t last_seq_mutex; + + hshTvoid_list *message_queue; + pthread_rwlock_t message_queue_lock; +}; + +typedef struct s_IPCMessage IPCMessage; + +struct s_IPCMessage +{ + int seq; + bool last; + int data_len; + char data[1]; +}; + + +#ifndef MSGMAX +#define MSGMAX 8192 +#endif + +static const unsigned int MAX_PAYLOAD = MSGMAX - sizeof (IPCMessage); + +void sysvipc_cleanup (int sig, void *ptr); + +SysVIPC * +sysvipc_new (const key_t ipcKey, IPCDisposition disposition) +{ + SysVIPC *ipc; + int queue_id; + + if ((queue_id = msgget (ipcKey, IPC_CREAT | 0600)) == -1) + { + perror ("msgget"); + + return (NULL); + } + + ipc = malloc (sizeof (SysVIPC)); + ipc->last_seq = 1; + ipc->queue_id = queue_id; + ipc->message_queue = hshFvoid_init ((void (*) (void *)) dynFfree); + ipc->disposition = disposition; + + pthread_mutex_init (&ipc->last_seq_mutex, NULL); + pthread_rwlock_init (&ipc->message_queue_lock, NULL); + +#ifdef HAVE_ON_EXIT + on_exit (sysvipc_cleanup, ipc); +#endif + + return (ipc); +} + +void +sysvipc_destroy (void *ptr) +{ + SysVIPC *ipc = (SysVIPC *) ptr; + + if (ipc->disposition == IPCServer) + { + msgctl (ipc->queue_id, IPC_RMID, NULL); + } + + pthread_rwlock_wrlock (&ipc->message_queue_lock); + + hshFvoid_destroy (ipc->message_queue); + + pthread_rwlock_unlock (&ipc->message_queue_lock); + + pthread_mutex_destroy (&ipc->last_seq_mutex); + pthread_rwlock_destroy (&ipc->message_queue_lock); + + free (ipc); +} + +void +sysvipc_cleanup (int sig MECHA_UNUSED, void *ptr) +{ + logFmsg (CONT_LOG_DEBUG, "sysvipc: Cleaning up resources."); + + sysvipc_destroy (ptr); +} + +static struct msgbuf * +sysvipc_createMessage (const char *data, size_t size, bool isLast, size_t *bufSize, int sequence) +{ + struct msgbuf *tmpBuf; + IPCMessage *message; + size_t allocSize; + + *bufSize = sizeof (IPCMessage) + size; + allocSize = sizeof (struct msgbuf) + *bufSize; + + tmpBuf = malloc (allocSize); + + memset (tmpBuf, 0, allocSize); + + message = (IPCMessage *) tmpBuf->mtext; + + message->seq = sequence; + message->last = isLast; + message->data_len = size; + memcpy (message->data, data, size); + + return (tmpBuf); +} + +static int +sysvipc_getNextSequence (SysVIPC *ipc) +{ + int seq; + + pthread_mutex_lock (&ipc->last_seq_mutex); + + seq = ++ipc->last_seq; + + pthread_mutex_unlock (&ipc->last_seq_mutex); + + return (seq); +} + +bool +sysvipc_sendData (SysVIPC *ipc, dynTstring *data) +{ + long msgtyp; + int dataOffset = 0; + int sequence = sysvipc_getNextSequence (ipc); + + if (ipc->disposition == IPCClient) + { + msgtyp = IPC_CLIENT_SEND_ID; + } + else + { + msgtyp = IPC_SERVER_SEND_ID; + } + + while ((dynFgetlen (data) - dataOffset) > 0) + { + struct msgbuf *tmpBuf; + bool isLast = true; + size_t dataSize = dynFgetlen (data) - dataOffset; + size_t bufSize; + int msgsndRet; + + if (dataSize > MAX_PAYLOAD) + { + dataSize = MAX_PAYLOAD; + isLast = false; + } + + tmpBuf = sysvipc_createMessage (dynFgetstr (data) + dataOffset, dataSize, isLast, &bufSize, sequence); + + tmpBuf->mtype = msgtyp; + + do + { + msgsndRet = msgsnd (ipc->queue_id, tmpBuf, bufSize, 0); + } + while (msgsndRet == -1 && errno == EINTR); + + if (msgsndRet == -1) + { + perror ("msgsnd"); + free (tmpBuf); + + abort(); + + return (false); + } + + free (tmpBuf); + + dataOffset += dataSize; + } + + return (true); +} + +static dynTstring * +sysvipc_getPendingMessage (SysVIPC *ipc, int sequence) +{ + dynTstring *partString; + + pthread_rwlock_rdlock (&ipc->message_queue_lock); + + partString = (dynTstring *) hshFvoid_int_find (ipc->message_queue, sequence); + + pthread_rwlock_unlock (&ipc->message_queue_lock); + + return (partString); +} + +static void +sysvipc_addPendingMessage (SysVIPC *ipc, int sequence, dynTstring *data) +{ + pthread_rwlock_wrlock (&ipc->message_queue_lock); + + hshFvoid_int_add (ipc->message_queue, sequence, data); + + pthread_rwlock_unlock (&ipc->message_queue_lock); +} + +static void +sysvipc_removePendingMessage (SysVIPC *ipc, int sequence) +{ + pthread_rwlock_wrlock (&ipc->message_queue_lock); + + /* this doesn't free the string, it just removes it from the hashtable */ + hshFvoid_int_remove (ipc->message_queue, sequence); + + pthread_rwlock_unlock (&ipc->message_queue_lock); +} + +dynTstring * +sysvipc_getData (SysVIPC *ipc) +{ + long msgtyp; + + if (ipc->disposition == IPCClient) + { + msgtyp = IPC_SERVER_SEND_ID; + } + else + { + msgtyp = IPC_CLIENT_SEND_ID; + } + + while (1) + { + struct msgbuf *tmpBuf = malloc (sizeof (struct msgbuf) + MSGMAX); + IPCMessage *message; + dynTstring *partString; + int ret; + + do + { + pthread_testcancel(); + ret = msgrcv (ipc->queue_id, tmpBuf, MSGMAX, msgtyp, 0); + pthread_testcancel(); + } + while (ret == -1 && errno == EINTR); + + if (ret == -1) + { + perror ("msgrcv"); + + free (tmpBuf); + + return (NULL); + } + + message = (IPCMessage *) tmpBuf->mtext; + + partString = sysvipc_getPendingMessage (ipc, message->seq); + + if (partString == NULL) + { + dynTstring *retString = dynFinit(); + + dynFappend (retString, message->data, message->data_len); + + if (message->last == true) + { + free (tmpBuf); + + return (retString); + } + else + { + sysvipc_addPendingMessage (ipc, message->seq, retString); + } + } + else + { + dynFappend (partString, message->data, message->data_len); + + if (message->last == true) + { + /* + * this doesn't free the string, it just removes it from the + * hashtable + */ + sysvipc_removePendingMessage (ipc, message->seq); + + free (tmpBuf); + + return (partString); + } + } + + free (tmpBuf); + } +} + diff --git a/lc-continuity/mk4/lib/causality/src/threadpool.c b/lc-continuity/mk4/lib/causality/src/threadpool.c new file mode 100644 index 0000000000000000000000000000000000000000..688c4447d399e4c65f062f57f408d68caab8b499 --- /dev/null +++ b/lc-continuity/mk4/lib/causality/src/threadpool.c @@ -0,0 +1,96 @@ + +#include + +#include "mecha.h" + +#include "threadpool.h" +#include "processor.h" +#include "request_dispatcher.h" + +#include "request_handler_entry.h" + +struct s_ThreadPool +{ + thrTtpool *pool; +}; + + +static ThreadPool *g_threadpool = NULL; +static pthread_rwlock_t g_threadpool_lock = PTHREAD_RWLOCK_INITIALIZER; + +#undef CLEANUP_THREADPOOL + +#ifdef CLEANUP_THREADPOOL +static void threadpool_cleanup (int sig, void *ptr); +#endif + + +ThreadPool * +threadpool_new() +{ + ThreadPool *threads = malloc (sizeof (ThreadPool)); + + threads->pool = thrFinit (64, 64, 1); + +#ifdef CLEANUP_THREADPOOL +#ifdef HAVE_ON_EXIT + on_exit (threadpool_cleanup, threads); +#endif +#endif + + return (threads); +} + +void +threadpool_destroy (void *ptr) +{ + ThreadPool *threads = (ThreadPool *) ptr; + + thrFdestroy (threads->pool, 0); + + free (threads); +} + +#ifdef CLEANUP_THREADPOOL +static void +threadpool_cleanup (__attribute__ ((unused)) int sig, void *ptr) +{ + logFmsg (CONT_LOG_DEBUG, "threadpool: Cleaning up resources."); + + threadpool_destroy (ptr); +} +#endif + +ThreadPool * +threadpool_getInstance() +{ + pthread_rwlock_rdlock (&g_threadpool_lock); + + if (g_threadpool == NULL) + { + pthread_rwlock_unlock (&g_threadpool_lock); + pthread_rwlock_wrlock (&g_threadpool_lock); + + if (g_threadpool == NULL) + { + g_threadpool = threadpool_new(); + } + } + + pthread_rwlock_unlock (&g_threadpool_lock); + + return (g_threadpool); +} + +bool +threadpool_queueUserWorkItem (ThreadPool *pool, WorkItemDelegate delegate, void *context) +{ + if (thrFadd_work (pool->pool, delegate, context) == 1) + { + return (true); + } + else + { + return (false); + } +} diff --git a/lc-continuity/mk4/mobility-client/CVS/Entries b/lc-continuity/mk4/mobility-client/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..7f1522a8be89946c0667fdcea112d893cc120ec4 --- /dev/null +++ b/lc-continuity/mk4/mobility-client/CVS/Entries @@ -0,0 +1,3 @@ +/Makefile.in/1.1/Wed May 19 21:02:58 2004//Tmk4_mod6_rc2 +D/modcgi//// +D/modmono//// diff --git a/lc-continuity/mk4/mobility-client/CVS/Repository b/lc-continuity/mk4/mobility-client/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..304ba45109ce97b77a7b815dabf429a28830dd02 --- /dev/null +++ b/lc-continuity/mk4/mobility-client/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/mobility-client diff --git a/lc-continuity/mk4/mobility-client/CVS/Root b/lc-continuity/mk4/mobility-client/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/mobility-client/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/mobility-client/CVS/Tag b/lc-continuity/mk4/mobility-client/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/mobility-client/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/mobility-client/Makefile.in b/lc-continuity/mk4/mobility-client/Makefile.in new file mode 100644 index 0000000000000000000000000000000000000000..a3068517d4d6a8988b70b7fa21ac1cb329ffa674 --- /dev/null +++ b/lc-continuity/mk4/mobility-client/Makefile.in @@ -0,0 +1,12 @@ + +SUBDIRS = modcgi modmono + +default: all + + +all clean: + for dir in $(SUBDIRS); do \ + $(MAKE) -C $$dir $@; \ + done +depend: + echo No depends, I can go to the bathroom thanks. diff --git a/lc-continuity/mk4/mobility-client/modcgi/.cvsignore b/lc-continuity/mk4/mobility-client/modcgi/.cvsignore new file mode 100644 index 0000000000000000000000000000000000000000..2ba3218e66f61379e0d63f7c2abdb5ee952b08e9 --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modcgi/.cvsignore @@ -0,0 +1,14 @@ +.svn +modcgi-client +modcgi-client-dmalloc.sh +build.h +.dep +test-cgi.sh +.rev +.build +modcgi-client-valgrind.sh +modcgi-client-check.sh +modcgi-client-valgrind-addrcheck.sh +modcgi-client-valgrind-helgrind.sh +modcgi-client-valgrind-vgprof.sh +modcgi diff --git a/lc-continuity/mk4/mobility-client/modcgi/CVS/Entries b/lc-continuity/mk4/mobility-client/modcgi/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..23d3b723d9c0838946dee145da0e0b1f0f3992b9 --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modcgi/CVS/Entries @@ -0,0 +1,4 @@ +/.cvsignore/1.1/Thu May 13 21:52:14 2004//Tmk4_mod6_rc2 +/Makefile/1.3/Fri May 14 19:12:09 2004//Tmk4_mod6_rc2 +D/include//// +D/src//// diff --git a/lc-continuity/mk4/mobility-client/modcgi/CVS/Repository b/lc-continuity/mk4/mobility-client/modcgi/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..2d2eb11ce3621ee65a8c2484301d8cb86a876716 --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modcgi/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/mobility-client/modcgi diff --git a/lc-continuity/mk4/mobility-client/modcgi/CVS/Root b/lc-continuity/mk4/mobility-client/modcgi/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modcgi/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/mobility-client/modcgi/CVS/Tag b/lc-continuity/mk4/mobility-client/modcgi/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modcgi/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/mobility-client/modcgi/Makefile b/lc-continuity/mk4/mobility-client/modcgi/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..526f52f687af89320b16dd8350aaece183511f7e --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modcgi/Makefile @@ -0,0 +1,16 @@ +CONTINUITY = ../../continuity + +TARGET = modcgi +TARGETTYPE = executable + +SOURCES = src/modcgi.c src/remote_process.c src/string_collection.c \ + src/cgi_request.c src/fd_watcher_entry.c src/fd_watcher.c \ + src/fd_reader.c src/process_watcher_entry.c src/process_watcher.c + +INCLUDES += -Iinclude -I../../lib/aura/include -I../../lib/causality/include -I../../lib/causality-client/include +#STATIC_LIBS += $(CONTINUITY)/lib/libcausality-client.a $(CONTINUITY)/lib/mechanism.a + +STATIC_LIBS += $(CONTINUITY)/lib/libcausality-client.a $(CONTINUITY)/lib/mechanism.a +WHOLE_STATIC_LIBS += $(CONTINUITY)/lib/libaura.a $(CONTINUITY)/lib/libcausality.a + +include $(CONTINUITY)/lib/build.mk diff --git a/lc-continuity/mk4/mobility-client/modcgi/include/.cvsignore b/lc-continuity/mk4/mobility-client/modcgi/include/.cvsignore new file mode 100644 index 0000000000000000000000000000000000000000..90ec22bee124705a9164f46a994cad1890bd92b5 --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modcgi/include/.cvsignore @@ -0,0 +1 @@ +.svn diff --git a/lc-continuity/mk4/mobility-client/modcgi/include/CVS/Entries b/lc-continuity/mk4/mobility-client/modcgi/include/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..e1c50fe933aae6f6ddfd7f4e4d90224948cb5a8e --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modcgi/include/CVS/Entries @@ -0,0 +1,10 @@ +/.cvsignore/1.1/Thu May 13 21:52:14 2004//Tmk4_mod6_rc2 +/cgi_request.h/1.1/Thu May 13 21:38:06 2004//Tmk4_mod6_rc2 +/fd_reader.h/1.1/Thu May 13 21:38:06 2004//Tmk4_mod6_rc2 +/fd_watcher.h/1.1/Thu May 13 21:38:06 2004//Tmk4_mod6_rc2 +/fd_watcher_entry.h/1.1/Thu May 13 21:38:06 2004//Tmk4_mod6_rc2 +/process_watcher.h/1.1/Thu May 13 21:38:06 2004//Tmk4_mod6_rc2 +/process_watcher_entry.h/1.1/Thu May 13 21:38:06 2004//Tmk4_mod6_rc2 +/remote_process.h/1.2/Sun May 16 20:31:59 2004//Tmk4_mod6_rc2 +/string_collection.h/1.1/Thu May 13 21:38:06 2004//Tmk4_mod6_rc2 +D diff --git a/lc-continuity/mk4/mobility-client/modcgi/include/CVS/Repository b/lc-continuity/mk4/mobility-client/modcgi/include/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..26ba1fcc0d71e958e568d507d5108e18c84874c3 --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modcgi/include/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/mobility-client/modcgi/include diff --git a/lc-continuity/mk4/mobility-client/modcgi/include/CVS/Root b/lc-continuity/mk4/mobility-client/modcgi/include/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modcgi/include/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/mobility-client/modcgi/include/CVS/Tag b/lc-continuity/mk4/mobility-client/modcgi/include/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modcgi/include/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/mobility-client/modcgi/include/cgi_request.h b/lc-continuity/mk4/mobility-client/modcgi/include/cgi_request.h new file mode 100644 index 0000000000000000000000000000000000000000..42f22e9d0bba231c143026fbdc057fe7aee2b5e0 --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modcgi/include/cgi_request.h @@ -0,0 +1,16 @@ + +#ifndef __CGI_REQUEST_H__ +#define __CGI_REQUEST_H__ + +#include "http_request.h" + +typedef struct s_CgiRequest CgiRequest; + +CgiRequest * cgi_request_new (HttpRequest *request); +void cgi_request_destroy (void *ptr); + +bool cgi_request_start (CgiRequest *instance); + +void cgi_request_handler (HttpRequest *request, void *context); + +#endif diff --git a/lc-continuity/mk4/mobility-client/modcgi/include/fd_reader.h b/lc-continuity/mk4/mobility-client/modcgi/include/fd_reader.h new file mode 100644 index 0000000000000000000000000000000000000000..52f88c4548a652c5fb49ae5735b87c78669cbef1 --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modcgi/include/fd_reader.h @@ -0,0 +1,15 @@ + +#ifndef __FD_READER_H__ +#define __FD_READER_H__ + +#include + +typedef struct s_FDReader FDReader; + +FDReader * fd_reader_new (int fd); +void fd_reader_destroy (void *ptr); + +ssize_t fd_reader_readLine (FDReader *instance, char *buf, int len); +ssize_t fd_reader_read (FDReader *instance, char *buf, int len); + +#endif diff --git a/lc-continuity/mk4/mobility-client/modcgi/include/fd_watcher.h b/lc-continuity/mk4/mobility-client/modcgi/include/fd_watcher.h new file mode 100644 index 0000000000000000000000000000000000000000..ce68e3e40a4ef4e0a14cfb3ec103fdf80766723c --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modcgi/include/fd_watcher.h @@ -0,0 +1,21 @@ + +#ifndef __FD_WATCHER_H__ +#define __FD_WATCHER_H__ + +#include "fd_watcher_entry.h" + +typedef struct s_FDWatcher FDWatcher; + +FDWatcher * fd_watcher_new (void); +void fd_watcher_destroy (void *ptr); + +FDWatcher * fd_watcher_getInstance (void); + +void fd_watcher_watchRead (FDWatcher *instance, int fd, FDWatcherDelegate delegate, void *context); +void fd_watcher_watchWrite (FDWatcher *instance, int fd, FDWatcherDelegate delegate, void *context); + +void fd_watcher_watchFD (FDWatcher *instance, int fd, FDWatcherDelegate delegate, void *context, short events); +void fd_watcher_removeWatchFD (FDWatcher *instance, int fd); + + +#endif diff --git a/lc-continuity/mk4/mobility-client/modcgi/include/fd_watcher_entry.h b/lc-continuity/mk4/mobility-client/modcgi/include/fd_watcher_entry.h new file mode 100644 index 0000000000000000000000000000000000000000..26dd50b5a07b2f30b8e3e80c2040ea8e75740753 --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modcgi/include/fd_watcher_entry.h @@ -0,0 +1,19 @@ + +#ifndef __FD_WATCHER_ENTRY_H__ +#define __FD_WATCHER_ENTRY_H__ + +typedef struct s_FDWatcherEntry FDWatcherEntry; + +typedef void (*FDWatcherDelegate) (void *context, int fd, short events); + +FDWatcherEntry * fd_watcher_entry_new (int fd, FDWatcherDelegate function, void *context, short events); +void fd_watcher_entry_destroy (void *ptr); + +void fd_watcher_entry_addEvent (FDWatcherEntry *instance, short event); + +void fd_watcher_entry_invoke (FDWatcherEntry *instance, short events); + +int fd_watcher_entry_getFD (FDWatcherEntry *instance); +short fd_watcher_entry_getEvents (FDWatcherEntry *instance); + +#endif diff --git a/lc-continuity/mk4/mobility-client/modcgi/include/process_watcher.h b/lc-continuity/mk4/mobility-client/modcgi/include/process_watcher.h new file mode 100644 index 0000000000000000000000000000000000000000..4c039bf390cd66a8b080ac1edcf826402ebd62bc --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modcgi/include/process_watcher.h @@ -0,0 +1,19 @@ + +#ifndef __PROCESS_WATCHER_H__ +#define __PROCESS_WATCHER_H__ + +typedef struct s_ProcessWatcher ProcessWatcher; + +ProcessWatcher * process_watcher_new (void); +void process_watcher_destroy (void *ptr); + +typedef void (*ProcessWatcherDelegate) (void *context, int status); + +ProcessWatcher * process_watcher_getInstance (void); + +void process_watcher_watchPid (ProcessWatcher *instance, int pid, + ProcessWatcherDelegate delegate, void *context); + +void process_watcher_removeWatchPid (ProcessWatcher *instance, int pid); + +#endif diff --git a/lc-continuity/mk4/mobility-client/modcgi/include/process_watcher_entry.h b/lc-continuity/mk4/mobility-client/modcgi/include/process_watcher_entry.h new file mode 100644 index 0000000000000000000000000000000000000000..6db056cdaa14bd296a51f35f96be798438d0f168 --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modcgi/include/process_watcher_entry.h @@ -0,0 +1,16 @@ + +#ifndef __PROCESS_WATCHER_ENTRY_H__ +#define __PROCESS_WATCHER_ENTRY_H__ + +#include + +#include "process_watcher.h" + +typedef struct s_ProcessWatcherEntry ProcessWatcherEntry; + +ProcessWatcherEntry * process_watcher_entry_new (int pid, ProcessWatcherDelegate delegate, void *context); +void process_watcher_entry_destroy (void *ptr); + +void process_watcher_entry_invoke (ProcessWatcherEntry *instance, int status); + +#endif diff --git a/lc-continuity/mk4/mobility-client/modcgi/include/remote_process.h b/lc-continuity/mk4/mobility-client/modcgi/include/remote_process.h new file mode 100644 index 0000000000000000000000000000000000000000..d6e09661248279e4bc6e47924e7648415d082750 --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modcgi/include/remote_process.h @@ -0,0 +1,27 @@ +#ifndef __REMOTE_PROCESS_H__ +#define __REMOTE_PROCESS_H__ + +#include "mecha.h" + +typedef struct s_RemoteProcess RemoteProcess; + +RemoteProcess * remote_process_new (const char *executable); +void remote_process_destroy (void *ptr); + +void remote_process_addEnvironment (RemoteProcess *instance, const char *variable); +void remote_process_addEnvironmentData (RemoteProcess *instance, const char *variable, int len); + +void remote_process_addArgument (RemoteProcess *instance, const char *argument); + +bool remote_process_start (RemoteProcess *instance); + +int remote_process_getStdIn (RemoteProcess *instance); +int remote_process_getStdOut (RemoteProcess *instance); +int remote_process_getStdErr (RemoteProcess *instance); + +bool remote_process_closeStdOut (RemoteProcess *instance); +bool remote_process_closeStdIn (RemoteProcess *instance); + +const char *remote_process_get_executable (RemoteProcess *instance); + +#endif diff --git a/lc-continuity/mk4/mobility-client/modcgi/include/string_collection.h b/lc-continuity/mk4/mobility-client/modcgi/include/string_collection.h new file mode 100644 index 0000000000000000000000000000000000000000..6fd9ba2ef733df638b1b118299e67ff736ff9e4d --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modcgi/include/string_collection.h @@ -0,0 +1,15 @@ + +#ifndef __STRING_COLLECTION_H__ +#define __STRING_COLLECTION_H__ + +typedef struct s_StringCollection StringCollection; + +StringCollection * string_collection_new (void); +void string_collection_destroy (void *ptr); + +void string_collection_addString (StringCollection *instance, const char *string); +void string_collection_addData (StringCollection *instance, const char *string, int len); +char ** string_collection_getInternal (StringCollection *instance); + + +#endif diff --git a/lc-continuity/mk4/mobility-client/modcgi/src/.cvsignore b/lc-continuity/mk4/mobility-client/modcgi/src/.cvsignore new file mode 100644 index 0000000000000000000000000000000000000000..12fa2a060cbbb43fe43b3f9d980f18fe42f637da --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modcgi/src/.cvsignore @@ -0,0 +1,3 @@ +*.sw? +.deps +.svn diff --git a/lc-continuity/mk4/mobility-client/modcgi/src/CVS/Entries b/lc-continuity/mk4/mobility-client/modcgi/src/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..f11a01a0bd7bb4fc2be8af816f85c669c8922f34 --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modcgi/src/CVS/Entries @@ -0,0 +1,11 @@ +/.cvsignore/1.1/Thu May 13 21:52:15 2004//Tmk4_mod6_rc2 +/cgi_request.c/1.2/Sun May 16 20:31:59 2004//Tmk4_mod6_rc2 +/fd_reader.c/1.2/Fri May 14 06:20:33 2004//Tmk4_mod6_rc2 +/fd_watcher.c/1.1/Thu May 13 21:38:06 2004//Tmk4_mod6_rc2 +/fd_watcher_entry.c/1.1/Thu May 13 21:38:06 2004//Tmk4_mod6_rc2 +/modcgi.c/1.1/Thu May 13 21:38:06 2004//Tmk4_mod6_rc2 +/process_watcher.c/1.1/Thu May 13 21:38:06 2004//Tmk4_mod6_rc2 +/process_watcher_entry.c/1.1/Thu May 13 21:38:06 2004//Tmk4_mod6_rc2 +/remote_process.c/1.3/Sun May 16 20:31:59 2004//Tmk4_mod6_rc2 +/string_collection.c/1.1/Thu May 13 21:38:06 2004//Tmk4_mod6_rc2 +D diff --git a/lc-continuity/mk4/mobility-client/modcgi/src/CVS/Repository b/lc-continuity/mk4/mobility-client/modcgi/src/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..ded7df8378498686dde2e480a216996cf1628de3 --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modcgi/src/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/mobility-client/modcgi/src diff --git a/lc-continuity/mk4/mobility-client/modcgi/src/CVS/Root b/lc-continuity/mk4/mobility-client/modcgi/src/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modcgi/src/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/mobility-client/modcgi/src/CVS/Tag b/lc-continuity/mk4/mobility-client/modcgi/src/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modcgi/src/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/mobility-client/modcgi/src/cgi_request.c b/lc-continuity/mk4/mobility-client/modcgi/src/cgi_request.c new file mode 100644 index 0000000000000000000000000000000000000000..252c37e0bf422309a6d43424ad9d3c81d0010358 --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modcgi/src/cgi_request.c @@ -0,0 +1,651 @@ + +#include +#include + + +#include "cgi_request.h" + +#include "remote_process.h" +#include "http_request.h" +#include "string_collection.h" +#include "fd_reader.h" +#include "fd_watcher.h" + +struct s_CgiRequest +{ + HttpRequest *request; + RemoteProcess *process; + + FDReader *stdoutReader; + FDReader *stderrReader; + + bool readHeaders; + bool finished; + + unsigned int entityOffset; +}; + +static void cgi_request_addEnvFromVariable (CgiRequest *instance, + const char *envName, int envLen, const char *varName); + +static void cgi_request_addEnv (CgiRequest *instance, const char *envName, + int envLen, const char *value, int valLen); + +static void cgi_request_addEnvFromHeader (CgiRequest *instance, + const char *envName, int envLen, const char *varName); + +static void cgi_request_initEnvironment (CgiRequest *instance); + +static void cgi_request_addRequestVars (CgiRequest *instance); + +static void cgi_request_handleStdError (void *context, int fd, short events); + +static void cgi_request_add_env_from_parent (CgiRequest *instance, const char *name, int len); + +CgiRequest * +cgi_request_new (HttpRequest *request) +{ + CgiRequest *instance = (CgiRequest *) malloc (sizeof (CgiRequest)); + + instance->request = request; + + instance->process = NULL; + + instance->readHeaders = false; + + instance->stdoutReader = NULL; + + instance->stderrReader = NULL; + + instance->entityOffset = 0; + + instance->finished = false; + + return (instance); +} + +void +cgi_request_destroy (void *ptr) +{ + CgiRequest *instance = (CgiRequest *) ptr; + + /* + * even if getStdOut or getStdIn return -1, it shouldn't hurt to remove + * that + */ + if (instance->process != NULL) + { + fd_watcher_removeWatchFD (fd_watcher_getInstance(), + remote_process_getStdOut (instance->process)); + + fd_watcher_removeWatchFD (fd_watcher_getInstance(), + remote_process_getStdIn (instance->process)); + + remote_process_destroy (instance->process); + } + + http_request_destroy (instance->request); + + if (instance->stdoutReader != NULL) + { + fd_reader_destroy (instance->stdoutReader); + } + + if (instance->stderrReader != NULL) + { + fd_reader_destroy (instance->stderrReader); + } + + free (instance); +} + +void +cgi_request_handler (HttpRequest *request, __attribute__((unused)) void *context) +{ + CgiRequest *cgiReq = cgi_request_new (request); + + cgi_request_start (cgiReq); +} + +static void +cgi_request_finish (CgiRequest *instance, int status) +{ + assert (instance->finished == false); + + /* If we got headers but never sent them (if we didn't have a body) */ + if (instance->readHeaders == true && http_request_headersSent (instance->request) == false) + { + /* BUGBUG: We should be using something better than sending an empty + * string to flush the headers. + * + * -eric@5stops.com 5.15.2004 + */ + http_request_writeData (instance->request, "", 0); + } + + instance->finished = true; + + http_request_finishStatus (instance->request, status); + + cgi_request_destroy (instance); +} + +static bool +cgi_request_setNonBlocking (int fd) +{ + int fdFlags; + + assert (fd >= 0); + + if ((fdFlags = fcntl (fd, F_GETFL)) == -1) + { + return (false); + } + + fdFlags |= O_NONBLOCK; + + if (fcntl (fd, F_SETFL, fdFlags) == -1) + { + return (false); + } + + return (true); +} + +static int +cgi_request_readHeaders (CgiRequest *instance) +{ + while (true) + { + char reqLine[1024]; + + char *name_p; + char *value_p; + char *state_p; + + ssize_t ret = fd_reader_readLine (instance->stdoutReader, reqLine, sizeof (reqLine)); + + if (ret < 1) + { + return (ret); + } + + if (reqLine[0] == '\n') + { + break; + } + + name_p = strtok_r (reqLine, ":", &state_p); + value_p = state_p; + + if (value_p != NULL) + { + while (*value_p == ' ' && *value_p != '\n' && *value_p != '\0') + { + value_p++; + } + } + else + { + /* could not parse headers */ + return (-1); + } + + if (name_p != NULL && value_p != NULL) + { + int value_len = (reqLine + ret) - value_p; + + strFstrip_crlf (value_p, value_len); + + if (strcasecmp (name_p, "Status") == 0) + { + char *status = strtok_r (NULL, " ", &value_p); + + http_request_setHttpStatus (instance->request, atoi (status), value_p); + } + else + { + http_request_setResponseHeaderData (instance->request, name_p, value_p, value_len); + } + } + } + + return (0); +} + +static ssize_t +cgi_request_readContent (CgiRequest *instance) +{ + char buffer[1024]; + + while (true) + { + ssize_t ret = fd_reader_read (instance->stdoutReader, buffer, sizeof (buffer)); + + if (ret > 0) + { + if (http_request_writeData (instance->request, buffer, ret) == false) + { + /* if we couldn't write, we're obviously done here */ + return (0); + } + } + else + { + return (ret); + } + } +} + +static void +cgi_request_handleStdError (void *context, MECHA_UNUSED_ARGUMENT int fd, MECHA_UNUSED_ARGUMENT short events) +{ + CgiRequest *instance = (CgiRequest *) context; + char lineBuf[1024]; + + while (true) + { + ssize_t ret = fd_reader_readLine (instance->stderrReader, lineBuf, sizeof (lineBuf)); + + if (ret == 0) + { + return; + } + + if (ret < 0 && ret == -EAGAIN) + { + fd_watcher_watchFD (fd_watcher_getInstance(), + remote_process_getStdErr (instance->process), + cgi_request_handleStdError, instance, POLLIN); + + return; + } + + if (ret == 1) + { + continue; + } + + lineBuf[ret - 1] = 0; + + logFmsg (CONT_LOG_ERROR, "%s: %s", remote_process_get_executable (instance->process), lineBuf); + } +} + +static void +cgi_request_handleStdOut (void *context, MECHA_UNUSED_ARGUMENT int fd, MECHA_UNUSED_ARGUMENT short events) +{ + CgiRequest *instance = context; + ssize_t ret; + + if (instance->readHeaders == false) + { + ret = cgi_request_readHeaders (instance); + + if (ret == 0) + { + /* we're done finding headers */ + instance->readHeaders = true; + } + } + + if (instance->readHeaders == true) + { + ret = cgi_request_readContent (instance); + + if (ret == 0) + { + /* we're done with the request */ + cgi_request_finish (instance, STATUS_EXIT); + + return; + } + } + + if (ret < 0 && ret != -EAGAIN) + { + char buf[1024]; + + snprintf (buf, sizeof (buf), "Error while processing cgi: %s (%d)", strerror (-ret), -ret); + + logFmsg (CONT_LOG_DEBUG, "mod/cgi: %s", buf); + + if (http_request_headersSent (instance->request) == false) + { + http_request_setHttpStatus (instance->request, 500, "Error"); + + http_request_writeString (instance->request, buf); + } + + /* we have to bail */ + cgi_request_finish (instance, STATUS_ERROR); + } + else + { + fd_watcher_watchFD (fd_watcher_getInstance(), + remote_process_getStdOut (instance->process), + cgi_request_handleStdOut, instance, POLLIN); + } +} + +static void +cgi_request_handleStdIn (void *context, __attribute__((unused)) int fd, __attribute__((unused)) short events) +{ + CgiRequest *instance = context; + const dynTstring *entity; + int len; + + entity = http_request_getEntireEntity (instance->request); + + if (entity == NULL) + { + remote_process_closeStdIn (instance->process); + + return; + } + + len = write (remote_process_getStdIn (instance->process), + dynFgetstr (entity) + instance->entityOffset, + dynFgetlen (entity) - instance->entityOffset); + + if (len < 1) + { + remote_process_closeStdIn (instance->process); + + return; + } + + instance->entityOffset += len; + + if (dynFgetlen (entity) == instance->entityOffset) + { + remote_process_closeStdIn (instance->process); + + return; + } + + fd_watcher_watchFD (fd_watcher_getInstance(), + remote_process_getStdIn (instance->process), + cgi_request_handleStdIn, instance, POLLOUT); + +} + +bool +cgi_request_start (CgiRequest *instance) +{ + bool ret; + + const dynTstring *path = http_request_getVariableString ( + instance->request, "path"); + + if (path == NULL) + { + /* we'll just let this fall through */ + cgi_request_finish (instance, STATUS_PROCEED); + + return (false); + } + + { + struct stat sbuf; + + if (lstat (dynFgetstr (path), &sbuf) == -1 || + !S_ISREG (sbuf.st_mode) || + (sbuf.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) == 0) + { + /* we can't run this, so we won't try */ + cgi_request_finish (instance, STATUS_PROCEED); + + return (false); + } + } + + instance->process = remote_process_new ( + dynFgetstr (path)); + + cgi_request_initEnvironment (instance); + + ret = remote_process_start (instance->process); + + if (ret == false) + { + /* we'll just let this fall through */ + cgi_request_finish (instance, STATUS_PROCEED); + + return (false); + } + + cgi_request_setNonBlocking (remote_process_getStdIn (instance->process)); + + cgi_request_setNonBlocking (remote_process_getStdOut (instance->process)); + + cgi_request_setNonBlocking (remote_process_getStdErr (instance->process)); + + instance->stdoutReader = fd_reader_new ( + remote_process_getStdOut (instance->process)); + + instance->stderrReader = fd_reader_new ( + remote_process_getStdErr (instance->process)); + + http_request_setHttpStatus (instance->request, 200, "OK OK"); + + { + const dynTstring *method = http_request_getVariableString ( + instance->request, "method"); + + if (method != NULL && strcmp (dynFgetstr (method), "POST") == 0) + { + fd_watcher_watchFD (fd_watcher_getInstance(), + remote_process_getStdIn (instance->process), + cgi_request_handleStdIn, instance, POLLOUT); + } + else + { + remote_process_closeStdIn (instance->process); + } + } + + fd_watcher_watchFD (fd_watcher_getInstance(), + remote_process_getStdOut (instance->process), + cgi_request_handleStdOut, instance, POLLIN); + + fd_watcher_watchFD (fd_watcher_getInstance(), + remote_process_getStdErr (instance->process), + cgi_request_handleStdError, instance, POLLIN); + + return (true); +} + +static void +cgi_request_initEnvironment (CgiRequest *instance) +{ + cgi_request_add_env_from_parent (instance, "LD_PRELOAD", 10); + cgi_request_add_env_from_parent (instance, "LD_LIBRARY_PATH", 15); + cgi_request_add_env_from_parent (instance, "VG_ARGS", 7); + + cgi_request_add_env_from_parent (instance, "TERM", 4); + cgi_request_add_env_from_parent (instance, "PATH", 4); + cgi_request_add_env_from_parent (instance, "HOSTTYPE", 8); + cgi_request_add_env_from_parent (instance, "VENDOR", 6); + cgi_request_add_env_from_parent (instance, "OSTYPE", 6); + cgi_request_add_env_from_parent (instance, "LANG", 4); + cgi_request_add_env_from_parent (instance, "MACHTYPE", 8); + cgi_request_add_env_from_parent (instance, "PWD", 3); + cgi_request_add_env_from_parent (instance, "HOST", 4); + cgi_request_add_env_from_parent (instance, "HOSTNAME", 8); + cgi_request_add_env_from_parent (instance, "TZ", 2); + + cgi_request_addEnvFromVariable (instance, "SERVER_SOFTWARE", + 15, "server"); + + /* SERVER_NAME */ + + cgi_request_addEnv (instance, "GATEWAY_INTERFACE", + 17, "CGI/1.1", 7); + + cgi_request_addEnvFromVariable (instance, "SERVER_PROTOCOL", + 15, "protocol"); + + /* + cgi_request_addEnvFromVariable (instance, "SERVER_PORT", + 11, ""); + */ + + cgi_request_addEnvFromVariable (instance, "REQUEST_METHOD", + 14, "method"); + + cgi_request_addEnvFromVariable (instance, "PATH_INFO", + 9, "path_info"); + + cgi_request_addEnvFromVariable (instance, "PATH_TRANSLATED", + 15, "path_translated"); + + cgi_request_addEnvFromVariable (instance, "SCRIPT_NAME", + 11, "uri"); + + cgi_request_addEnvFromVariable (instance, "QUERY_STRING", + 12, "query"); + + /* + * we don't have the resolved version of REMOTE_ADDR from the webserver, + * and there isn't any benefit of resolving it ourselves. + * + * ---- + * + cgi_request_addEnvFromVariable (instance, "REMOTE_HOST", + 11, ""); + */ + + cgi_request_addEnv (instance, "REMOTE_ADDR", + 11, http_request_getRemoteIP (instance->request), + strlen (http_request_getRemoteIP (instance->request))); + + /* + cgi_request_addEnvFromVariable (instance, "AUTH_TYPE", + 9, ""); + */ + + /* + cgi_request_addEnvFromVariable (instance, "REMOTE_USER", + 11, ""); + */ + + /* + cgi_request_addEnvFromVariable (instance, "REMOTE_IDENT", + 12, ""); + */ + + cgi_request_addEnvFromHeader (instance, "CONTENT_TYPE", + 12, "content-type"); + + cgi_request_addEnvFromHeader (instance, "CONTENT_LENGTH", + 14, "content-length"); + + /* This is added by apache and seems like a good idea */ + cgi_request_addEnvFromVariable (instance, "SCRIPT_FILENAME", + 15, "path"); + + cgi_request_addRequestVars (instance); +} + +static void +cgi_request_add_env_from_parent (CgiRequest *instance, const char *name, int len) +{ + char *e = getenv (name); + + if (e != NULL) + { + cgi_request_addEnv (instance, name, len, e, strlen (e)); + } +} + +static void +cgi_request_addRequestVars (CgiRequest *instance) +{ + hshTiterator *iter = http_request_getRequestHeaderIterator ( + instance->request); + + dynTstring *newKey = dynFinit(); + + while (hshFiterator_next (iter) == 1) + { + const char *key = (const char *) hshFiterator_current_key (iter); + const dynTstring *value = (const dynTstring *) + hshFiterator_current_value (iter); + + dynFreset (newKey); + dynFappend (newKey, "HTTP_", 5); + + while (*key != 0) + { + if (*key == '-') + { + dynFappend (newKey, "_", 1); + } + else + { + char c = toupper (*key); + + dynFappend (newKey, &c, 1); + } + + key++; + } + + cgi_request_addEnv (instance, dynFgetstr (newKey), + dynFgetlen (newKey), dynFgetstr (value), + dynFgetlen (value)); + } + + hshFiterator_free (iter); + dynFfree (newKey); +} + +static void +cgi_request_addEnv (CgiRequest *instance, const char *envName, + int envLen, const char *value, int valLen) +{ + dynTstring *envString = dynFinit(); + + dynFappend (envString, envName, envLen); + + dynFappend (envString, "=", 1); + + if (valLen > 0) + { + dynFappend (envString, value, valLen); + } + + remote_process_addEnvironmentData (instance->process, + dynFgetstr (envString), dynFgetlen (envString)); + + dynFfree (envString); +} + +static void +cgi_request_addEnvFromHeader (CgiRequest *instance, const char *envName, + int envLen, const char *varName) +{ + const dynTstring *value = http_request_getRequestHeaderString ( + instance->request, varName); + + if (value != NULL) + { + cgi_request_addEnv (instance, envName, envLen, + dynFgetstr (value), dynFgetlen (value)); + } +} + +static void +cgi_request_addEnvFromVariable (CgiRequest *instance, const char *envName, + int envLen, const char *varName) +{ + const dynTstring *value = http_request_getVariableString ( + instance->request, varName); + + if (value != NULL) + { + cgi_request_addEnv (instance, envName, envLen, + dynFgetstr (value), dynFgetlen (value)); + } +} diff --git a/lc-continuity/mk4/mobility-client/modcgi/src/fd_reader.c b/lc-continuity/mk4/mobility-client/modcgi/src/fd_reader.c new file mode 100644 index 0000000000000000000000000000000000000000..2a20f047bfe91ab8b05885c8978d34bdf8777347 --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modcgi/src/fd_reader.c @@ -0,0 +1,229 @@ + +#include +#include +#include +#include + +#include "mecha.h" + +#include "fd_reader.h" + +#define READER_CHUNK_SZ 1024 + +struct s_FDReader +{ + char *buf; + + int allocSize; + + ssize_t startOffset; + ssize_t endOffset; + + int fd; + + bool foundEnd; +}; + +FDReader * +fd_reader_new (int fd) +{ + FDReader *instance = (FDReader *) malloc (sizeof (FDReader)); + + instance->buf = malloc (sizeof (char) * READER_CHUNK_SZ); + instance->allocSize = READER_CHUNK_SZ; + + instance->startOffset = 0; + instance->endOffset = 0; + + instance->fd = fd; + + instance->foundEnd = FALSE; + + return (instance); +} + +void +fd_reader_destroy (void *ptr) +{ + FDReader *instance = (FDReader *) ptr; + + free (instance->buf); + + free (instance); +} + +static int +fd_reader_populateBuffer (FDReader *instance, int requestedLen, bool guarantee) +{ + /* if we have more in our buffer than is requested, we're okay. */ + if (instance->endOffset - instance->startOffset > requestedLen) + { + return (0); + } + + if (instance->foundEnd == TRUE) + { + return (0); + } + + /* reset the offsets if we have an empty buffer */ + if (instance->startOffset == instance->endOffset) + { + instance->startOffset = 0; + instance->endOffset = 0; + } + + /* we don't have enough room to write what we want to onto our buffer */ + if (instance->startOffset + requestedLen > instance->allocSize) + { + /* + * if we're just too close to the end, lets move back to the beginning + * of the buffer + */ + if (requestedLen <= instance->allocSize) + { + memmove (instance->buf, instance->buf + instance->startOffset, + instance->endOffset - instance->startOffset); + + instance->endOffset = instance->endOffset - instance->startOffset; + instance->startOffset = 0; + } + else + { + int newLen = sizeof (char) * (instance->startOffset + + requestedLen + READER_CHUNK_SZ); + + /* we need to get more buffer space */ + instance->buf = realloc (instance->buf, newLen); + + logFmsg (CONT_LOG_DEBUG, "modcgi/fd_reader: resizing from %d -> %d", + instance->allocSize, newLen); + + instance->allocSize = newLen; + } + } + + do + { + ssize_t len = read (instance->fd, instance->buf + instance->endOffset, + instance->allocSize - instance->endOffset); + + if (len == -1) + { + return (errno); + } + else if (len == 0) + { + instance->foundEnd = TRUE; + + break; + } + + instance->endOffset += len; + } + while (requestedLen > instance->endOffset - instance->startOffset && guarantee == TRUE); + + return (0); +} + + +ssize_t +fd_reader_readLine (FDReader *instance, char *buf, int len) +{ + char *p; + ssize_t i; + int status; + + status = fd_reader_populateBuffer (instance, len, TRUE); + + if (status != 0) + { + return (-status); + } + + p = instance->buf + instance->startOffset; + + for (i = 0; i < (len - 1) && instance->startOffset < instance->endOffset; i++) + { + instance->startOffset++; + + if (p[i] == '\r') + { + buf[i] = '\n'; + + buf[i + 1] = 0; + + /* if we're using windows, which uses: \r\n */ + if (p[i + 1] == '\n') + { + instance->startOffset++; + } + + /* + * if "i" is the offset of our last character, we have to add one + * to get the length + */ + return (i + 1); + } + else if (p[i] == '\n') + { + buf[i] = '\n'; + + buf[i + 1] = 0; + + /* if we're using a mac, which uses: \n\r */ + if (p[i + 1] == '\r') + { + instance->startOffset++; + } + + /* + * if "i" is the offset of our last character, we have to add one + * to get the length + */ + return (i + 1); + } + else + { + buf[i] = p[i]; + } + } + + /* make sure we always end in a NULL */ + buf[i] = 0; + + return (i); +} + +ssize_t +fd_reader_read (FDReader *instance, char *buf, int len) +{ + int status; + + status = fd_reader_populateBuffer (instance, len, FALSE); + + if (status != 0) + { + return (-status); + } + + /* + * if we have less bytes to return than the buffer has room, we need to + * only return what we have. + * + * this will happen if we have found the end of the file + */ + if (len > instance->endOffset - instance->startOffset) + { + len = instance->endOffset - instance->startOffset; + } + + if (len != 0) + { + memcpy (buf, instance->buf + instance->startOffset, len); + + instance->startOffset += len; + } + + return (len); +} diff --git a/lc-continuity/mk4/mobility-client/modcgi/src/fd_watcher.c b/lc-continuity/mk4/mobility-client/modcgi/src/fd_watcher.c new file mode 100644 index 0000000000000000000000000000000000000000..af8d87176e5c1331c1b38e92c8fdc2c7a8bf9f1c --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modcgi/src/fd_watcher.c @@ -0,0 +1,172 @@ + +#include +#include + +#include "mecha.h" + +#include "fd_watcher.h" + +#include "fd_watcher_entry.h" + +static FDWatcher *g_instance = NULL; +static pthread_once_t g_instanceOnce = PTHREAD_ONCE_INIT; + +struct s_FDWatcher +{ + hshTvoid_list *fdList; + + pthread_mutex_t fdListMutex; + pthread_cond_t fdListCond; + + pthread_t pollerThread; +}; + +static void *fd_watcher_dispatcher (void *context); +static void fd_watcher_setupInstance (void); + +FDWatcher * +fd_watcher_new (void) +{ + FDWatcher *instance = (FDWatcher *) malloc (sizeof (FDWatcher)); + + instance->fdList = hshFvoid_int_init (fd_watcher_entry_destroy); + + pthread_mutex_init (&instance->fdListMutex, NULL); + pthread_cond_init (&instance->fdListCond, NULL); + + pthread_create (&instance->pollerThread, NULL, fd_watcher_dispatcher, instance); + + return (instance); +} + +void +fd_watcher_destroy (void *ptr) +{ + FDWatcher *instance = (FDWatcher *) ptr; + + pthread_cancel (instance->pollerThread); + pthread_join (instance->pollerThread, NULL); + + hshFvoid_destroy (instance->fdList); + + pthread_mutex_destroy (&instance->fdListMutex); + pthread_cond_destroy (&instance->fdListCond); + + free (instance); +} + +static void +fd_watcher_setupInstance() +{ + g_instance = fd_watcher_new(); +} + +FDWatcher * +fd_watcher_getInstance() +{ + pthread_once (&g_instanceOnce, fd_watcher_setupInstance); + + return (g_instance); +} + +static void * +fd_watcher_dispatcher (void *context) +{ + FDWatcher *instance = (FDWatcher *) context; + + while (1) + { + struct pollfd *ufds; + hshTiterator *iter; + int i = 0; + int listSize; + + pthread_mutex_lock (&instance->fdListMutex); + + if (hshFvoid_size (instance->fdList) == 0) + { + pthread_cond_wait (&instance->fdListCond, &instance->fdListMutex); + } + + listSize = hshFvoid_size (instance->fdList); + + ufds = malloc (sizeof (struct pollfd) * + listSize); + + iter = hshFiterator_init (instance->fdList); + + while (hshFiterator_next (iter) == 1) + { + FDWatcherEntry *entry = hshFiterator_current_value (iter); + + ufds[i].fd = fd_watcher_entry_getFD (entry); + ufds[i].events = fd_watcher_entry_getEvents (entry); + + i++; + } + + hshFiterator_free (iter); + + pthread_mutex_unlock (&instance->fdListMutex); + + { + int rfds = poll (ufds, listSize, 300); + + for (i = 0; i < listSize && rfds > 0; i++) + { + if (ufds[i].revents != 0) + { + FDWatcherEntry *entry; + + pthread_mutex_lock (&instance->fdListMutex); + + entry = hshFvoid_int_remove (instance->fdList, ufds[i].fd); + + pthread_mutex_unlock (&instance->fdListMutex); + + if (entry != NULL) + { + /* + * this will destroy the entry as soon as it is completed + */ + fd_watcher_entry_invoke (entry, ufds[i].revents); + } + } + } + } + + free (ufds); + } + + return (NULL); +} + +void +fd_watcher_removeWatchFD (FDWatcher *instance, int fd) +{ + pthread_mutex_lock (&instance->fdListMutex); + + hshFvoid_int_del (instance->fdList, fd); + + pthread_mutex_unlock (&instance->fdListMutex); +} + +void +fd_watcher_watchFD (FDWatcher *instance, int fd, FDWatcherDelegate delegate, void *context, short events) +{ + pthread_mutex_lock (&instance->fdListMutex); + + hshFvoid_int_add (instance->fdList, fd, + fd_watcher_entry_new (fd, delegate, context, events)); + + /* + * if the size is 1, that means it was at 0 before we added ourselves, + * which means we should notify the watcher. + */ + if (hshFvoid_size (instance->fdList) == 1) + { + pthread_cond_signal (&instance->fdListCond); + } + + pthread_mutex_unlock (&instance->fdListMutex); +} diff --git a/lc-continuity/mk4/mobility-client/modcgi/src/fd_watcher_entry.c b/lc-continuity/mk4/mobility-client/modcgi/src/fd_watcher_entry.c new file mode 100644 index 0000000000000000000000000000000000000000..6a2f25bf1a9edbc92f0605e6d3cd58671a69e1aa --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modcgi/src/fd_watcher_entry.c @@ -0,0 +1,77 @@ + +#include +#include + +#include "fd_watcher_entry.h" +#include "threadpool.h" + +struct s_FDWatcherEntry +{ + int fd; + + short events; + short revents; + + FDWatcherDelegate function; + + void *context; +}; + +FDWatcherEntry * +fd_watcher_entry_new (int fd, FDWatcherDelegate function, void *context, short events) +{ + FDWatcherEntry *instance = (FDWatcherEntry *) malloc (sizeof (FDWatcherEntry)); + + instance->fd = fd; + instance->function = function; + instance->context = context; + instance->events = events; + + return (instance); +} + +void +fd_watcher_entry_destroy (void *ptr) +{ + FDWatcherEntry *instance = (FDWatcherEntry *) ptr; + + free (instance); +} + +int +fd_watcher_entry_getFD (FDWatcherEntry *instance) +{ + return (instance->fd); +} + +short +fd_watcher_entry_getEvents (FDWatcherEntry *instance) +{ + return (instance->events); +} + +void +fd_watcher_entry_addEvent (FDWatcherEntry *instance, short event) +{ + instance->events |= event; +} + +static void +fd_watcher_entry_internalInvoke (void *context) +{ + FDWatcherEntry *instance = context; + + instance->function (instance->context, instance->fd, instance->revents); + + fd_watcher_entry_destroy (instance); +} + +void +fd_watcher_entry_invoke (FDWatcherEntry *instance, short events) +{ + instance->revents = events; + + threadpool_queueUserWorkItem (threadpool_getInstance(), + fd_watcher_entry_internalInvoke, instance); +} + diff --git a/lc-continuity/mk4/mobility-client/modcgi/src/modcgi.c b/lc-continuity/mk4/mobility-client/modcgi/src/modcgi.c new file mode 100644 index 0000000000000000000000000000000000000000..503511b6038e64eb0973cde8144d4c439e49edc3 --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modcgi/src/modcgi.c @@ -0,0 +1,36 @@ +#include +#include + +#include +#include + +#include "type.h" + +#include "remote_process.h" +#include "http_request_list.h" + +#include "cgi_request.h" + +#include "client.h" + +int main (int argc, char **argv) +{ + if (argc < 2) + { + printf ("usage: %s \n", argv[0]); + return (2); + } + + signal (SIGPIPE, SIG_IGN); + + client_init (atoi (argv[1])); + + http_request_list_setHandler (http_request_list_getRequestList(), + cgi_request_handler, NULL); + + while (TRUE) + { + thrFsleep (60 * 1000); + } +} + diff --git a/lc-continuity/mk4/mobility-client/modcgi/src/process_watcher.c b/lc-continuity/mk4/mobility-client/modcgi/src/process_watcher.c new file mode 100644 index 0000000000000000000000000000000000000000..7c353fd97771e535a7c0e682ee9ced5857c72862 --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modcgi/src/process_watcher.c @@ -0,0 +1,253 @@ +#define _GNU_SOURCE +#include + +#include +#include +#include +#include +#include +#include + + +#include "process_watcher.h" +#include "process_watcher_entry.h" + +#include "mecha.h" + +static ProcessWatcher *g_instance = NULL; +static pthread_once_t g_instanceOnce = PTHREAD_ONCE_INIT; + +static void * process_watcher_watchChildren (void *context); +static void process_watcher_setupInstance (void); + +static void process_watcher_sigchildHandler (int signum, siginfo_t *siginfo, __attribute__ ((unused)) void *data); + +static void process_watcher_setupPipes (ProcessWatcher *instance); +static void process_watcher_installHandlers (void); + +struct s_ProcessWatcher +{ + hshTvoid_list *children; + pthread_mutex_t childrenMutex; + pthread_t watcherThread; + + int readFD; + int writeFD; +}; + +ProcessWatcher * +process_watcher_new (void) +{ + ProcessWatcher *instance = (ProcessWatcher *) malloc (sizeof (ProcessWatcher)); + + instance->children = hshFvoid_int_init (process_watcher_entry_destroy); + + pthread_mutex_init (&instance->childrenMutex, NULL); + + process_watcher_setupPipes (instance); + + pthread_create (&instance->watcherThread, NULL, process_watcher_watchChildren, instance); + + process_watcher_installHandlers(); + + return (instance); +} + +void +process_watcher_destroy (void *ptr) +{ + ProcessWatcher *instance = (ProcessWatcher *) ptr; + + pthread_cancel (instance->watcherThread); + pthread_join (instance->watcherThread, NULL); + + close (instance->readFD); + close (instance->writeFD); + + pthread_mutex_destroy (&instance->childrenMutex); + + hshFvoid_destroy (instance->children); + + free (instance); +} + +static void +process_watcher_setupInstance() +{ + g_instance = process_watcher_new(); +} + +ProcessWatcher * +process_watcher_getInstance() +{ + pthread_once (&g_instanceOnce, process_watcher_setupInstance); + + return (g_instance); +} + +void +process_watcher_removeWatchPid (ProcessWatcher *instance, int pid) +{ + pthread_mutex_lock (&instance->childrenMutex); + + hshFvoid_int_del (instance->children, pid); + + pthread_mutex_unlock (&instance->childrenMutex); +} + +void +process_watcher_watchPid (ProcessWatcher *instance, int pid, + ProcessWatcherDelegate delegate, void *context) +{ + pthread_mutex_lock (&instance->childrenMutex); + + hshFvoid_int_add (instance->children, pid, + process_watcher_entry_new (pid, delegate, context)); + + pthread_mutex_unlock (&instance->childrenMutex); +} + +static void +process_watcher_installHandlers() +{ +#if 0 + signal (SIGHUP, process_watcher_sigchildHandler); + signal (SIGINT, process_watcher_sigchildHandler); + signal (SIGQUIT, process_watcher_sigchildHandler); +#endif + + /* + * It seems that with linux 2.4, you won't get called unless you use + * SA_SIGINFO. + * + * -eric@5stops.com 1.18.2004 + */ + { + struct sigaction action; + + action.sa_handler = NULL; + action.sa_sigaction = process_watcher_sigchildHandler; + action.sa_flags = SA_NOCLDSTOP | SA_RESTART | SA_SIGINFO | SA_NODEFER; + action.sa_restorer = NULL; + + sigemptyset (&action.sa_mask); + + if (sigaction (SIGCHLD, &action, NULL) != 0) + { + logFmsg (CONT_LOG_ERROR, "Could not install signal handler for SIGCHLD: %s", + strerror (errno)); + + return; + } + } +} + +static void +process_watcher_setupPipes (ProcessWatcher *instance) +{ + int fdpipes[2]; + + if (pipe (fdpipes) != 0) + { + perror ("pipe"); + } + + instance->readFD = fdpipes[0]; + instance->writeFD = fdpipes[1]; +} + + +struct process_watcher_data +{ + int status; + pid_t pid; +}; + +static void +process_watcher_sigchildHandler (int signum, __attribute__ ((unused)) siginfo_t *siginfo, __attribute__ ((unused)) void *extraData) +{ + struct process_watcher_data data; + + if (signum != SIGCHLD) + { + logFmsg (CONT_LOG_DEBUG, "modcgi/process_watcher: Received signal %d. Exiting.", signum); + + exit (0); + } + + while (TRUE) + { + data.pid = waitpid (0, &data.status, WNOHANG); + + if (data.pid == 0 || (data.pid == -1 && errno == ECHILD)) + { + /* we apparently don't have any more children to wait on */ + + return; + } + + if (data.pid == -1) + { + logFmsg (CONT_LOG_DEBUG, "modcgi/process_watcher: wait: %d: %s", errno, strerror (errno)); + + return; + } + +#if PROCESS_DEBUGGING + logFmsg (CONT_LOG_DEBUG, "modcgi/process_watcher: reaped process %d.", data.pid); +#endif + + /* + * BUGBUG: This really shouldn't be using g_instance directly, but we + * can't use mutexes in here (which process_watcher_getInstance() does). + */ + if (write (g_instance->writeFD, &data, sizeof (data)) != sizeof (data)) + { + logFmsg (CONT_LOG_ERROR, "modcgi/process_watcher: Could not write to fd: %s", strerror (errno)); + + return; + } + } +} + + +/* + * Because sigwait() seems to not work properly for SIGCHLD on linux 2.4, we + * are resorting to using a signal handler write the required information to a + * pipe + * + * -eric@5stops.com 1.18.2004 + */ +static void * +process_watcher_watchChildren (void *context) +{ + ProcessWatcher *instance = context; + + while (TRUE) + { + ProcessWatcherEntry *entry; + struct process_watcher_data data; + + if (read (instance->readFD, &data, sizeof (data)) != sizeof (data)) + { + logFmsg (CONT_LOG_ERROR, "modcgi/process_watcher: Could not read from fd: %s", strerror (errno)); + + return (NULL); + } + + pthread_mutex_lock (&instance->childrenMutex); + + entry = hshFvoid_int_remove (instance->children, data.pid); + + if (entry != NULL) + { + process_watcher_entry_invoke (entry, data.status); + } + + pthread_mutex_unlock (&instance->childrenMutex); + } + + return (NULL); +} + + diff --git a/lc-continuity/mk4/mobility-client/modcgi/src/process_watcher_entry.c b/lc-continuity/mk4/mobility-client/modcgi/src/process_watcher_entry.c new file mode 100644 index 0000000000000000000000000000000000000000..b429b0070570526ea15fcd4d598e822c7f8dafae --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modcgi/src/process_watcher_entry.c @@ -0,0 +1,58 @@ + +#include +#include + +#include "process_watcher_entry.h" +#include "threadpool.h" + +struct s_ProcessWatcherEntry +{ + int pid; + ProcessWatcherDelegate delegate; + void *context; + int status; +}; + +ProcessWatcherEntry * +process_watcher_entry_new (int pid, ProcessWatcherDelegate delegate, void *context) +{ + ProcessWatcherEntry *instance = (ProcessWatcherEntry *) malloc (sizeof (ProcessWatcherEntry)); + + instance->pid = pid; + instance->delegate = delegate; + instance->context = context; + instance->status = 0; + + return (instance); +} + +void +process_watcher_entry_destroy (void *ptr) +{ + ProcessWatcherEntry *instance = (ProcessWatcherEntry *) ptr; + + free (instance); +} + +static void +process_watcher_entry_internalInvoke (void *context) +{ + ProcessWatcherEntry *instance = (ProcessWatcherEntry *) context; + + instance->delegate (instance->context, instance->status); + + process_watcher_entry_destroy (instance); +} + +void +process_watcher_entry_invoke (ProcessWatcherEntry *instance, + int status) +{ + instance->status = status; + + /* + threadpool_queueUserWorkItem (threadpool_getInstance(), + process_watcher_entry_internalInvoke, instance); + */ + process_watcher_entry_internalInvoke (instance); +} diff --git a/lc-continuity/mk4/mobility-client/modcgi/src/remote_process.c b/lc-continuity/mk4/mobility-client/modcgi/src/remote_process.c new file mode 100644 index 0000000000000000000000000000000000000000..b55f614655bea2c03ab72b65c362cc99b1485399 --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modcgi/src/remote_process.c @@ -0,0 +1,491 @@ + +#include +#include +#include +#include +#include + +#include "type.h" + +#include "remote_process.h" +#include "string_collection.h" + +#include "process_watcher.h" + +static void remote_process_closeFDs (RemoteProcess *instance); + +struct s_RemoteProcess +{ + int pid; + + char *executable; + + StringCollection *arguments; + + StringCollection *environment; + + int stdin; + int stdout; + int stderr; + + bool exited; + int exitCode; + + pthread_mutex_t processMutex; +}; + +RemoteProcess * +remote_process_new (const char *executable) +{ + RemoteProcess *instance = (RemoteProcess *) malloc (sizeof (RemoteProcess)); + + /* make sure the executable is not NULL */ + assert (executable != NULL); + /* make sure the executable is not an empty string */ + assert (*executable != 0); + + instance->executable = strdup (executable); + + instance->pid = -1; + instance->stdin = -1; + instance->stdout = -1; + instance->stderr = -1; + + instance->exitCode = 0; + instance->exited = FALSE; + + instance->arguments = string_collection_new(); + + instance->environment = string_collection_new(); + + string_collection_addString (instance->arguments, instance->executable); + + pthread_mutex_init (&instance->processMutex, NULL); + + return (instance); +} + +void +remote_process_destroy (void *ptr) +{ + RemoteProcess *instance = (RemoteProcess *) ptr; + + process_watcher_removeWatchPid (process_watcher_getInstance(), + instance->pid); + + pthread_mutex_lock (&instance->processMutex); + + string_collection_destroy (instance->arguments); + string_collection_destroy (instance->environment); + + if (instance->exited == FALSE) + { + kill (instance->pid, SIGKILL); + } + + remote_process_closeFDs (instance); + + pthread_mutex_unlock (&instance->processMutex); + + pthread_mutex_destroy (&instance->processMutex); + + free (instance->executable); + + free (instance); +} + +static void +remote_process_closeFDs (RemoteProcess *instance) +{ + if (instance->stdin != -1) + { + close (instance->stdin); + + instance->stdin = -1; + } + + if (instance->stdout != -1) + { + close (instance->stdout); + + instance->stdout = -1; + } + + if (instance->stderr != -1) + { + close (instance->stderr); + + instance->stderr = -1; + } +} + +const char * +remote_process_get_executable (RemoteProcess *instance) +{ + return (instance->executable); +} + +void +remote_process_addEnvironment (RemoteProcess *instance, const char *variable) +{ + pthread_mutex_lock (&instance->processMutex); + + string_collection_addString (instance->environment, variable); + + pthread_mutex_unlock (&instance->processMutex); +} + +void +remote_process_addEnvironmentData (RemoteProcess *instance, const char *variable, int len) +{ + pthread_mutex_lock (&instance->processMutex); + + string_collection_addData (instance->environment, variable, len); + + pthread_mutex_unlock (&instance->processMutex); +} + +void +remote_process_addArgument (RemoteProcess *instance, const char *argument) +{ + pthread_mutex_lock (&instance->processMutex); + + string_collection_addString (instance->arguments, argument); + + pthread_mutex_unlock (&instance->processMutex); +} + +int +remote_process_getStdIn (RemoteProcess *instance) +{ + int fd; + + pthread_mutex_lock (&instance->processMutex); + + fd = instance->stdin; + + pthread_mutex_unlock (&instance->processMutex); + + return (fd); +} + +int +remote_process_getStdOut (RemoteProcess *instance) +{ + int fd; + + pthread_mutex_lock (&instance->processMutex); + + fd = instance->stdout; + + pthread_mutex_unlock (&instance->processMutex); + + return (fd); +} + +bool +remote_process_closeStdOut (RemoteProcess *instance) +{ + bool ret; + + pthread_mutex_lock (&instance->processMutex); + + if (instance->stdout != -1) + { + close (instance->stdout); + + instance->stdout = -1; + + ret = TRUE; + } + else + { + ret = FALSE; + } + + pthread_mutex_unlock (&instance->processMutex); + + return (ret); +} + +bool +remote_process_closeStdIn (RemoteProcess *instance) +{ + bool ret; + + pthread_mutex_lock (&instance->processMutex); + + if (instance->stdin != -1) + { + close (instance->stdin); + + instance->stdin = -1; + + ret = TRUE; + } + else + { + ret = FALSE; + } + + pthread_mutex_unlock (&instance->processMutex); + + return (ret); +} + +int +remote_process_getStdErr (RemoteProcess *instance) +{ + int fd; + + pthread_mutex_lock (&instance->processMutex); + + fd = instance->stderr; + + pthread_mutex_unlock (&instance->processMutex); + + return (fd); +} + +static void +remote_process_cleanupProcess (void *context, int status) +{ + RemoteProcess *instance = (RemoteProcess *) context; + + pthread_mutex_lock (&instance->processMutex); + + instance->exited = TRUE; + + if (WIFEXITED (status)) + { + instance->exitCode = WEXITSTATUS (status); + } + + pthread_mutex_unlock (&instance->processMutex); +} + +bool +remote_process_start (RemoteProcess *instance) +{ + int stdin_pipe[2]; + int stdout_pipe[2]; + int stderr_pipe[2]; + int pid; + struct stat statb; + + pthread_mutex_lock (&instance->processMutex); + + if (stat (instance->executable, &statb) == -1) + { + perror ("stat"); + + pthread_mutex_unlock (&instance->processMutex); + + return (FALSE); + } + + if (pipe (stdin_pipe) != 0) + { + perror ("pipe"); + + pthread_mutex_unlock (&instance->processMutex); + return (FALSE); + } + + if (pipe (stdout_pipe) != 0) + { + perror ("pipe"); + + close (stdin_pipe[0]); + close (stdin_pipe[1]); + + pthread_mutex_unlock (&instance->processMutex); + + return (FALSE); + } + + if (pipe (stderr_pipe) != 0) + { + perror ("pipe"); + + close (stdin_pipe[0]); + close (stdin_pipe[1]); + close (stdout_pipe[0]); + close (stdout_pipe[1]); + + pthread_mutex_unlock (&instance->processMutex); + + return (FALSE); + } + + if ((pid = fork()) == -1) + { + /* we couldn't fork */ + perror ("fork"); + + close (stdin_pipe[0]); + close (stdin_pipe[1]); + close (stdout_pipe[0]); + close (stdout_pipe[1]); + close (stderr_pipe[0]); + close (stderr_pipe[1]); + + pthread_mutex_unlock (&instance->processMutex); + + return (FALSE); + } + + if (pid == 0) + { + /* + * HACK: syncronize with the calling process by reading a single char + * from stdin + */ + { + char buf; + + if (read (stdin_pipe[0], &buf, 1) != 1) + { + perror ("read"); + } + } + + char *dir = strFcopy (instance->executable); + + char *lastSlash = rindex (dir, '/'); + + if (lastSlash != NULL) + { + *lastSlash = 0; + + chdir (dir); + } + else + { + logFmsg (CONT_LOG_WARN, "Could not change directory for: %s", instance->executable); + } + + /* close the write side of the stdin fd */ + close (stdin_pipe[1]); + + /* close the read side of stdout fd */ + close (stdout_pipe[0]); + + /* close the read side of stderr fd */ + close (stderr_pipe[0]); + + /* set our stdin pipe to STDIN */ + if (dup2 (stdin_pipe[0], STDIN_FILENO) == -1) + { + perror ("dup2"); + return (errno); + } + + /* close the "higher" fd num */ + close (stdin_pipe[0]); + + /* set our stdout pipe to STDOUT */ + if (dup2 (stdout_pipe[1], STDOUT_FILENO) == -1) + { + perror ("dup2"); + return (errno); + } + + /* close the "higher" fd num */ + close (stdout_pipe[1]); + + /* set our stderr pipe to STDERR */ + if (dup2 (stderr_pipe[1], STDERR_FILENO) == -1) + { + perror ("dup2"); + return (errno); + } + + /* close the "higher" fd num */ + close (stderr_pipe[1]); + + if (getuid() == 0) + { + if (setregid (statb.st_gid, statb.st_gid) != 0) + { + int e = errno; + + perror ("setregid"); + + return (e); + } + + if (setreuid (statb.st_uid, statb.st_uid) != 0) + { + int e = errno; + + perror ("setreuid"); + + return (e); + } + } + + execve (instance->executable, + string_collection_getInternal (instance->arguments), + string_collection_getInternal (instance->environment)); + + /* we should never reach this */ + + perror (instance->executable); + + return (errno); + } + else + { + instance->pid = pid; + + process_watcher_watchPid (process_watcher_getInstance(), + instance->pid, remote_process_cleanupProcess, instance); + + /* close the read side of the stdin fd */ + close (stdin_pipe[0]); + + /* save the write side of the stdin fd */ + instance->stdin = stdin_pipe[1]; + + /* mark this fd to be closed if we fork again */ + fleFset_close_exec (instance->stdin); + + /* close the write side of stdout fd */ + close (stdout_pipe[1]); + + /* save the read side of the stdout fd */ + instance->stdout = stdout_pipe[0]; + + /* mark this fd to be closed if we fork again */ + fleFset_close_exec (instance->stdout); + + /* close the write side of stderr fd */ + close (stderr_pipe[1]); + + /* save the read side of the stderr fd */ + instance->stderr = stderr_pipe[0]; + + /* mark this fd to be closed if we fork again */ + fleFset_close_exec (instance->stderr); + + /* + * HACK: syncronize with the child process by writing a single char + * to stdin -- the child should block until this is written + */ + { + char buf = '1'; + + if (write (instance->stdin, &buf, 1) != 1) + { + perror ("write"); + + return (FALSE); + } + } + + pthread_mutex_unlock (&instance->processMutex); + + return (TRUE); + } +} diff --git a/lc-continuity/mk4/mobility-client/modcgi/src/string_collection.c b/lc-continuity/mk4/mobility-client/modcgi/src/string_collection.c new file mode 100644 index 0000000000000000000000000000000000000000..a4678972253489f62a9ada7498c7169f4e6632ac --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modcgi/src/string_collection.c @@ -0,0 +1,108 @@ + +#include +#include +#include + +#include + +#include "string_collection.h" + +struct s_StringCollection +{ + int numStrings; + char **strings; +}; + +static void string_collection_growArray (StringCollection *instance, int newLength); + + +StringCollection * +string_collection_new (void) +{ + StringCollection *instance = (StringCollection *) malloc (sizeof (StringCollection)); + + instance->numStrings = 0; + instance->strings = NULL; + + /* + * this will allocate the initial array + * + * from execvp man page: + * The array of pointers _must_ be terminated by a NULL pointer. + */ + string_collection_growArray (instance, 0); + + return (instance); +} + +void +string_collection_destroy (void *ptr) +{ + StringCollection *instance = (StringCollection *) ptr; + + if (instance->numStrings > 0) + { + int i; + + for (i = 0; i < instance->numStrings; i++) + { + free (instance->strings[i]); + } + } + + free (instance->strings); + + free (instance); +} + +static void +string_collection_growArray (StringCollection *instance, int newLength) +{ + int i; + + assert (newLength >= 0); + assert (newLength >= instance->numStrings); + + instance->strings = realloc (instance->strings, sizeof (char *) * (newLength + 1)); + + /* set each new entry to NULL */ + for (i = instance->numStrings; i <= newLength; i++) + { + instance->strings[i] = NULL; + } +} + +void +string_collection_addString (StringCollection *instance, const char *string) +{ + assert (string != NULL); + + string_collection_addData (instance, string, strlen (string)); +} + +void +string_collection_addData (StringCollection *instance, const char *string, int len) +{ + assert (string != NULL); + assert (len > 0); + + /* allocate one for the added entry */ + string_collection_growArray (instance, instance->numStrings + 1); + + /* allocate an extra one for the NULL */ + instance->strings[instance->numStrings] = malloc (sizeof (char) * (len + 1)); + + /* add the NULL to the end of the string */ + instance->strings[instance->numStrings][len] = 0; + + /* copy the string to the array */ + memcpy (instance->strings[instance->numStrings], string, len); + + instance->numStrings++; +} + +char ** +string_collection_getInternal (StringCollection *instance) +{ + return (instance->strings); +} diff --git a/lc-continuity/mk4/mobility-client/modmono/.cvsignore b/lc-continuity/mk4/mobility-client/modmono/.cvsignore new file mode 100644 index 0000000000000000000000000000000000000000..b6b8dcd14f06f267fb3afa44fd8cf62064fc15ed --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modmono/.cvsignore @@ -0,0 +1,7 @@ +poke_ltmono.sh +poke_mono.sh +.svn +.dep +w3wp-profile.sh +w3wp-mint.sh +w3wp.sh diff --git a/lc-continuity/mk4/mobility-client/modmono/CVS/Entries b/lc-continuity/mk4/mobility-client/modmono/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..60a0316e3a2af4a2de1272c808c631c6e9eb7e22 --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modmono/CVS/Entries @@ -0,0 +1,3 @@ +/.cvsignore/1.1/Thu May 13 21:52:15 2004//Tmk4_mod6_rc2 +/Makefile/1.2/Fri May 14 16:51:25 2004//Tmk4_mod6_rc2 +D/src//// diff --git a/lc-continuity/mk4/mobility-client/modmono/CVS/Repository b/lc-continuity/mk4/mobility-client/modmono/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..3959b89b5211b0589f856f5031a5e2c87cea854d --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modmono/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/mobility-client/modmono diff --git a/lc-continuity/mk4/mobility-client/modmono/CVS/Root b/lc-continuity/mk4/mobility-client/modmono/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modmono/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/mobility-client/modmono/CVS/Tag b/lc-continuity/mk4/mobility-client/modmono/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modmono/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/mobility-client/modmono/Makefile b/lc-continuity/mk4/mobility-client/modmono/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..d9b7905a786b0bc95ea68172960cdb6c1a9b833f --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modmono/Makefile @@ -0,0 +1,45 @@ +# $Id: Makefile,v 1.2 2004/05/14 16:51:25 eric Exp $ + +CONTINUITY = ../../continuity + +MCS_LOCATION := $(shell which mcs 2>&1) + +ifeq (,$(findstring no mcs in,$(MCS_LOCATION))) + +include $(CONTINUITY)/lib/env.mk + +PROJECT = modmono + +MANAGED_BINARY = $(PROJECT).exe + +MANAGED_SRC = src/CausalityClient.cs src/OxideApplicationHost.cs \ + src/OxideMain.cs src/OxideWorkerRequest.cs \ + src/CausalityRequest.cs src/CThreadPool.cs \ + src/OxideApplicationPool.cs + +CSC = mcs +CS_FLAGS = -debug -g -r:System.Web -target:exe + + +.PHONY: clean distclean buildtar count buildcount all depend + +all: $(MANAGED_BINARY) + + +$(MANAGED_BINARY): $(MANAGED_SRC) + $(CSC) $(CS_FLAGS) -out:$(MANAGED_BINARY) $(MANAGED_SRC) + +clean: + -rm -f src/*.o src/*~ include/*~ *~ core $(MANAGED_BINARY) + +distclean: + -rm -f src/*.o src/*~ include/*~ core $(BINARY) .dep + +else +# +# we don't have mcs installed +# +all: +$(warning Could not find mcs in path. Skipping build of mod/mono.) + +endif diff --git a/lc-continuity/mk4/mobility-client/modmono/src/.cvsignore b/lc-continuity/mk4/mobility-client/modmono/src/.cvsignore new file mode 100644 index 0000000000000000000000000000000000000000..90ec22bee124705a9164f46a994cad1890bd92b5 --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modmono/src/.cvsignore @@ -0,0 +1 @@ +.svn diff --git a/lc-continuity/mk4/mobility-client/modmono/src/CThreadPool.cs b/lc-continuity/mk4/mobility-client/modmono/src/CThreadPool.cs new file mode 100644 index 0000000000000000000000000000000000000000..27d9122b3bd53c99822b60251b5bf19b46b234b3 --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modmono/src/CThreadPool.cs @@ -0,0 +1,296 @@ +// +// System.Threading.ThreadPool +// +// Author: +// Patrik Torstensson +// Dick Porter (dick@ximian.com) +// +// (C) Ximian, Inc. http://www.ximian.com +// (C) Patrik Torstensson +// +using System; +using System.Collections; +using System.Threading; + +namespace Fivestops.Oxide { + /// (Patrik T notes) + /// This threadpool is focused on saving resources not giving max performance. + /// + /// Note, this class is not perfect but it works. ;-) Should also replace + /// the queue with an internal one (performance) + /// + /// This class should also use a specialized queue to increase performance.. + /// + /// + public sealed class CThreadPool { + internal struct ThreadPoolWorkItem { + public WaitCallback _CallBack; + public object _Context; + } + + private int _ThreadTimeout; + + private long _MaxThreads; + private long _CurrentThreads; + private long _ThreadsInUse; + private long _RequestInQueue; + private long _ThreadCreateTriggerRequests; + + // private Thread _MonitorThread; + private Queue _RequestQueue; + + private ArrayList _Threads; + private ManualResetEvent _DataInQueue; + + static CThreadPool _Threadpool; + + static CThreadPool() { + _Threadpool = new CThreadPool(); + } + + private CThreadPool() { + // 30 sec timeout default + _ThreadTimeout = 30 * 1000; + + // Used to signal that there is data in the queue + _DataInQueue = new ManualResetEvent(false); + + _Threads = ArrayList.Synchronized(new ArrayList()); + + // Holds requests.. + _RequestQueue = new Queue(128); + // _RequestQueue = Queue.Synchronized(new Queue(128)); + + // TODO: This should be 2 x number of CPU:s in the box + _MaxThreads = 16; + _CurrentThreads = 0; + _RequestInQueue = 0; + _ThreadsInUse = 0; + _ThreadCreateTriggerRequests = 5; + + // TODO: This temp starts one thread, remove this.. + CheckIfStartThread(); + + // Keeps track of requests in the queue and increases the number of threads if needed + + // PT: Disabled - causes problems during shutdown + //_MonitorThread = new Thread(new ThreadStart(MonitorThread)); + //_MonitorThread.Start(); + } + + internal void RemoveThread() { + Interlocked.Decrement(ref _CurrentThreads); + _Threads.Remove(Thread.CurrentThread); + } + + internal void CheckIfStartThread() { + bool bCreateThread = false; + + if (_CurrentThreads == 0) { + bCreateThread = true; + } + + if (( _MaxThreads == -1 || _CurrentThreads < _MaxThreads) && + _ThreadsInUse > 0 && + _RequestInQueue >= _ThreadCreateTriggerRequests) { + bCreateThread = true; + } + + if (bCreateThread) { + Interlocked.Increment(ref _CurrentThreads); + + Thread Start = new Thread(new ThreadStart(WorkerThread)); + Start.IsBackground = true; + Start.Start(); + + _Threads.Add(Start); + } + } + + internal void AddItem(ref ThreadPoolWorkItem Item) { + lock (_RequestQueue) + { + _RequestQueue.Enqueue(Item); + + Interlocked.Increment(ref _RequestInQueue); + + _DataInQueue.Set(); + } + } + + // Work Thread main function + internal void WorkerThread() + { + while (true) { + if (!_DataInQueue.WaitOne(_ThreadTimeout, false)) { + // Keep one thread running + if (_CurrentThreads > 1) { + // timeout + RemoveThread(); + return; + } + continue; + } + + Interlocked.Increment(ref _ThreadsInUse); + + // TODO: Remove when we know how to stop the watch thread + CheckIfStartThread(); + + try + { + ThreadPoolWorkItem oItem; + + lock (_RequestQueue) + { + if (_RequestQueue.Count < 1) + { + _DataInQueue.Reset(); + continue; + } + + oItem = (ThreadPoolWorkItem) _RequestQueue.Dequeue(); + } + + Interlocked.Decrement(ref _RequestInQueue); + + oItem._CallBack(oItem._Context); + } + catch (InvalidOperationException) { + // Queue empty + } + catch (ThreadAbortException) { + // We will leave here.. (thread abort can't be handled) + RemoveThread(); + } + finally { + Interlocked.Decrement(ref _ThreadsInUse); + } + } + } + + /* This is currently not in use + + internal void MonitorThread() { + while (true) { + if (_DataInQueue.WaitOne ()) { + CheckIfStartThread(); + } + + Thread.Sleep(500); + } + } + + */ + internal bool QueueUserWorkItemInternal(WaitCallback callback) { + return QueueUserWorkItem(callback, null); + } + + internal bool QueueUserWorkItemInternal(WaitCallback callback, object context) { + ThreadPoolWorkItem Item = new ThreadPoolWorkItem(); + + Item._CallBack = callback; + Item._Context = context; + + AddItem(ref Item); + + // LAMESPEC: Return value? should use exception here if anything goes wrong + return true; + } + + public static bool BindHandle(IntPtr osHandle) { + throw new NotSupportedException("This is a win32 specific method, not supported Mono"); + } + + public static bool QueueUserWorkItem(WaitCallback callback) { + return _Threadpool.QueueUserWorkItemInternal(callback); + } + + public static bool QueueUserWorkItem(WaitCallback callback, object state) { + return _Threadpool.QueueUserWorkItemInternal(callback, state); + } + + public static bool UnsafeQueueUserWorkItem(WaitCallback callback, object state) { + return _Threadpool.QueueUserWorkItemInternal(callback, state); + } + + static TimeSpan GetTSFromMS (long ms) + { + if (ms < -1) + throw new ArgumentOutOfRangeException ("millisecondsTimeOutInterval", "timeout < -1"); + + return new TimeSpan (0, 0, 0, 0, (int) ms); + } + +#if NEEDED + public static RegisteredWaitHandle RegisterWaitForSingleObject (WaitHandle waitObject, + WaitOrTimerCallback callback, + object state, + int millisecondsTimeOutInterval, + bool executeOnlyOnce) + { + TimeSpan ts = GetTSFromMS ((long) millisecondsTimeOutInterval); + return RegisterWaitForSingleObject (waitObject, callback, state, ts, executeOnlyOnce); + } + + public static RegisteredWaitHandle RegisterWaitForSingleObject (WaitHandle waitObject, + WaitOrTimerCallback callback, + object state, + long millisecondsTimeOutInterval, + bool executeOnlyOnce) + { + TimeSpan ts = GetTSFromMS (millisecondsTimeOutInterval); + return RegisterWaitForSingleObject (waitObject, callback, state, ts, executeOnlyOnce); + } + + public static RegisteredWaitHandle RegisterWaitForSingleObject (WaitHandle waitObject, + WaitOrTimerCallback callback, + object state, + TimeSpan timeout, + bool executeOnlyOnce) + { + long ms = (long) timeout.TotalMilliseconds; + if (ms < -1) + throw new ArgumentOutOfRangeException ("timeout", "timeout < -1"); + + if (ms > Int32.MaxValue) + throw new NotSupportedException ("Timeout is too big. Maximum is Int32.MaxValue"); + + RegisteredWaitHandle waiter = new RegisteredWaitHandle (waitObject, callback, state, timeout, executeOnlyOnce); + _Threadpool.QueueUserWorkItemInternal (new WaitCallback (waiter.Wait), null); + return waiter; + } + + [CLSCompliant(false)] + public static RegisteredWaitHandle RegisterWaitForSingleObject (WaitHandle waitObject, + WaitOrTimerCallback callback, + object state, + uint millisecondsTimeOutInterval, + bool executeOnlyOnce) + { + TimeSpan ts = GetTSFromMS ((long) millisecondsTimeOutInterval); + return RegisterWaitForSingleObject (waitObject, callback, state, ts, executeOnlyOnce); + } + + [MonoTODO] + public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callback, object state, int millisecondsTimeOutInterval, bool executeOnlyOnce) { + throw new NotImplementedException(); + } + + [MonoTODO] + public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callback, object state, long millisecondsTimeOutInterval, bool executeOnlyOnce) { + throw new NotImplementedException(); + } + + [MonoTODO] + public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callback, object state, TimeSpan timeout, bool executeOnlyOnce) { + throw new NotImplementedException(); + } + + [CLSCompliant(false)][MonoTODO] + public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callback, object state, uint millisecondsTimeOutInterval, bool executeOnlyOnce) { + throw new NotImplementedException(); + } +#endif + } +} diff --git a/lc-continuity/mk4/mobility-client/modmono/src/CVS/Entries b/lc-continuity/mk4/mobility-client/modmono/src/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..67a73e1c73b82fa5349205f384159c48822cc4f7 --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modmono/src/CVS/Entries @@ -0,0 +1,10 @@ +/.cvsignore/1.1/Thu May 13 21:52:15 2004//Tmk4_mod6_rc2 +/CThreadPool.cs/1.1/Thu May 13 21:48:08 2004//Tmk4_mod6_rc2 +/CausalityClient.cs/1.1/Thu May 13 21:48:08 2004//Tmk4_mod6_rc2 +/CausalityRequest.cs/1.1/Thu May 13 21:48:08 2004//Tmk4_mod6_rc2 +/OxideApplicationHost.cs/1.1/Thu May 13 21:48:08 2004//Tmk4_mod6_rc2 +/OxideApplicationPool.cs/1.1/Thu May 13 21:48:08 2004//Tmk4_mod6_rc2 +/OxideMain.cs/1.1/Thu May 13 21:48:08 2004//Tmk4_mod6_rc2 +/OxideThreadPool.cs/1.1/Thu May 13 21:48:08 2004//Tmk4_mod6_rc2 +/OxideWorkerRequest.cs/1.1/Thu May 13 21:48:08 2004//Tmk4_mod6_rc2 +D diff --git a/lc-continuity/mk4/mobility-client/modmono/src/CVS/Repository b/lc-continuity/mk4/mobility-client/modmono/src/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..d9fecd0eaaeb0c4a4045b2de144d498a2f066fd3 --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modmono/src/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/mobility-client/modmono/src diff --git a/lc-continuity/mk4/mobility-client/modmono/src/CVS/Root b/lc-continuity/mk4/mobility-client/modmono/src/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modmono/src/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/mobility-client/modmono/src/CVS/Tag b/lc-continuity/mk4/mobility-client/modmono/src/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modmono/src/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/mobility-client/modmono/src/CausalityClient.cs b/lc-continuity/mk4/mobility-client/modmono/src/CausalityClient.cs new file mode 100644 index 0000000000000000000000000000000000000000..8a78cd94582893c486213dc9590b089b2aeac0f6 --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modmono/src/CausalityClient.cs @@ -0,0 +1,59 @@ +using System; +using System.Runtime.InteropServices; + +namespace Fivestops.Oxide +{ + public class CausalityClient + { + const string LIBRARY_LOCATION = "/home/eric/src/depot/src/main/causality-client/"; + + // [DllImport (LIBRARY_LOCATION + "libcausality-client.so", CallingConvention=CallingConvention.Cdecl, EntryPoint="client_init")] + [DllImport (LIBRARY_LOCATION + "libcausality-client.so", CallingConvention=CallingConvention.StdCall, CharSet=CharSet.Ansi, EntryPoint="client_init")] + public static extern void Init (int key); + + [DllImport (LIBRARY_LOCATION + "libcausality-client.so", EntryPoint="client_get_request")] + public static extern IntPtr GetRequest(); + + [DllImport (LIBRARY_LOCATION + "libcausality-client.so", EntryPoint="client_write_string")] + public static extern bool WriteString (IntPtr request, string data); + + [DllImport (LIBRARY_LOCATION + "libcausality-client.so", EntryPoint="client_write_data")] + public static extern bool WriteData (IntPtr request, [MarshalAs(UnmanagedType.LPArray)] byte[] data, int dataLen); + + [DllImport (LIBRARY_LOCATION + "libcausality-client.so", EntryPoint="client_get_uri")] + public static extern string GetUri (IntPtr request); + + [DllImport (LIBRARY_LOCATION + "libcausality-client.so", EntryPoint="client_get_query")] + public static extern string GetQuery (IntPtr request); + + [DllImport (LIBRARY_LOCATION + "libcausality-client.so", EntryPoint="client_finish")] + public static extern bool Finish (IntPtr request); + + [DllImport (LIBRARY_LOCATION + "libcausality-client.so", EntryPoint="client_get_entity")] + public static extern int ReadEntityBody (IntPtr request, [Out] [MarshalAs(UnmanagedType.LPArray)] byte[] bufOut, int bufLen); + + [DllImport (LIBRARY_LOCATION + "libcausality-client.so", EntryPoint="client_is_entire_entity_loaded")] + public static extern bool IsEntireEntityLoaded (IntPtr request); + + [DllImport (LIBRARY_LOCATION + "libcausality-client.so", EntryPoint="client_get_method")] + public static extern string GetMethod (IntPtr request); + + [DllImport (LIBRARY_LOCATION + "libcausality-client.so", EntryPoint="client_get_request_header")] + public static extern string GetRequestHeader (IntPtr request, string key); + + [DllImport (LIBRARY_LOCATION + "libcausality-client.so", EntryPoint="client_set_response_header")] + public static extern void SetResponseHeader (IntPtr request, string key, string value); + + [DllImport (LIBRARY_LOCATION + "libcausality-client.so", EntryPoint="client_set_status")] + public static extern void SetStatus (IntPtr request, int status, string description); + + [DllImport (LIBRARY_LOCATION + "libcausality-client.so", EntryPoint="client_headers_sent")] + public static extern bool HeadersSent (IntPtr request); + + [DllImport (LIBRARY_LOCATION + "libcausality-client.so", EntryPoint="client_get_variable")] + public static extern string GetTransactionVariable (IntPtr request, string key); + + [DllImport (LIBRARY_LOCATION + "libcausality-client.so", EntryPoint="client_get_remote_ip")] + public static extern string GetRemoteIP (IntPtr request); + } +} diff --git a/lc-continuity/mk4/mobility-client/modmono/src/CausalityRequest.cs b/lc-continuity/mk4/mobility-client/modmono/src/CausalityRequest.cs new file mode 100644 index 0000000000000000000000000000000000000000..266f3317972f73b64ae3339ecf11056663b02c1d --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modmono/src/CausalityRequest.cs @@ -0,0 +1,137 @@ +using System; + +namespace Fivestops.Oxide +{ + public class CausalityRequest : IDisposable + { + private IntPtr m_ipRequest; + private bool m_bDisposed = false; + + public string Page + { + get + { + return (CausalityClient.GetUri (m_ipRequest)); + } + } + + public string Query + { + get + { + return (CausalityClient.GetQuery (m_ipRequest)); + } + } + + public string Method + { + get + { + return (CausalityClient.GetMethod (m_ipRequest)); + } + } + + public CausalityRequest (IntPtr request) + { + if (request == IntPtr.Zero) + { + throw (new ArgumentNullException ("request")); + } + + m_ipRequest = request; + } + + public string GetVariable (string key) + { + return (CausalityClient.GetTransactionVariable (m_ipRequest, key)); + } + + public int ReadEntityBody (byte[] outBuf, int bufLen) + { + if (outBuf.Length != bufLen) + { + throw (new ApplicationException ( + "outBuf.Length != bufLen: " + outBuf.Length.ToString() + + " " + bufLen.ToString())); + } + + return (CausalityClient.ReadEntityBody (m_ipRequest, outBuf, bufLen)); + } + + public bool IsEntireEntityLoaded() + { + return (CausalityClient.IsEntireEntityLoaded (m_ipRequest)); + } + + public string GetRequestHeader (string key) + { + return (CausalityClient.GetRequestHeader (m_ipRequest, key)); + } + + public void SetResponseHeader (string key, string value) + { + CausalityClient.SetResponseHeader (m_ipRequest, key, value); + } + + public void SetStatus (int status, string description) + { + CausalityClient.SetStatus (m_ipRequest, status, description); + } + + public bool Write (byte[] data, int dataLen) + { + return (CausalityClient.WriteData (m_ipRequest, data, dataLen)); + } + + public bool Write (string data) + { + return (CausalityClient.WriteString (m_ipRequest, data)); + } + + public bool HeadersSent() + { + return (CausalityClient.HeadersSent (m_ipRequest)); + } + + public string GetRemoteIP() + { + return (CausalityClient.GetRemoteIP (m_ipRequest)); + } + + public void Finish() + { + this.Dispose (true); + + GC.SuppressFinalize (this); + } + + public void Dispose() + { + this.Dispose (true); + + GC.SuppressFinalize (this); + } + + private void Dispose (bool disposing) + { + if (m_bDisposed == false) + { + if (disposing) + { + // release managed components + } + + CausalityClient.Finish (m_ipRequest); + + m_ipRequest = IntPtr.Zero; + + m_bDisposed = true; + } + } + + ~CausalityRequest() + { + Dispose (false); + } + } +} diff --git a/lc-continuity/mk4/mobility-client/modmono/src/OxideApplicationHost.cs b/lc-continuity/mk4/mobility-client/modmono/src/OxideApplicationHost.cs new file mode 100644 index 0000000000000000000000000000000000000000..1b9dd2134ac9cdf999d26b4dbb5615a694c54768 --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modmono/src/OxideApplicationHost.cs @@ -0,0 +1,61 @@ +using System; +using System.Web; +using System.IO; +using System.Web.Hosting; +using System.Threading; +using System.Runtime.Remoting.Lifetime; + + +namespace Fivestops.Oxide +{ + public class OxideApplicationHost : MarshalByRefObject + { + // tell the GC that we don't ever want to be collected. + public override object InitializeLifetimeService () + { + return (null); + } + + public string Path + { + get + { + return (AppDomain.CurrentDomain.GetData (".appPath").ToString()); + } + } + + public string VPath + { + get + { + return (AppDomain.CurrentDomain.GetData (".appVPath").ToString()); + } + } + + private void DispatchRequest (object stateObject) + { + OxideWorkerRequest owrRequest = (OxideWorkerRequest) stateObject; + + HttpRuntime.ProcessRequest (owrRequest); + } + + public void HandleRequest (IntPtr request) + { + OxideWorkerRequest owrRequest = new OxideWorkerRequest ( + new CausalityRequest (request)); + + Fivestops.Oxide.CThreadPool.QueueUserWorkItem ( + new WaitCallback (this.DispatchRequest), owrRequest); + } + + public static OxideApplicationHost CreateApplicationHost ( + string virtualdir, string basedir) + { + OxideApplicationHost o = (OxideApplicationHost) + ApplicationHost.CreateApplicationHost ( + typeof (OxideApplicationHost), virtualdir, basedir); + + return (o); + } + } +} diff --git a/lc-continuity/mk4/mobility-client/modmono/src/OxideApplicationPool.cs b/lc-continuity/mk4/mobility-client/modmono/src/OxideApplicationPool.cs new file mode 100644 index 0000000000000000000000000000000000000000..5b3c469ee7fb82de653caa8aa6acabca58f76263 --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modmono/src/OxideApplicationPool.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections; +using System.Runtime.Remoting; +using System.Runtime.Remoting.Lifetime; + +namespace Fivestops.Oxide +{ + class OxideApplicationPool + { + private Hashtable m_htApplications = new Hashtable(); + private ClientSponsor m_csSponsor = new ClientSponsor(); + + public void ProcessRequests() + { + while (true) + { + try + { + this.ProcessRequest (CausalityClient.GetRequest()); + } + catch (Exception e) + { + Console.WriteLine ("ex: {0}", e); + } + } + } + + private void ProcessRequest (IntPtr request) + { + OxideApplicationHost oahHost = this.GetHost ( + CausalityClient.GetTransactionVariable (request, "docroot")); + + oahHost.HandleRequest (request); + } + + private OxideApplicationHost GetHost (string docroot) + { + OxideApplicationHost oahHost = (OxideApplicationHost) + m_htApplications[docroot]; + + if (oahHost == null) + { + oahHost = OxideApplicationHost.CreateApplicationHost ( + "/", docroot); + + m_csSponsor.Register (oahHost); + + m_htApplications[docroot] = oahHost; + } + + return (oahHost); + } + } +} diff --git a/lc-continuity/mk4/mobility-client/modmono/src/OxideMain.cs b/lc-continuity/mk4/mobility-client/modmono/src/OxideMain.cs new file mode 100644 index 0000000000000000000000000000000000000000..0644e39a5c2c7649f67c1528fec5c196f56017f7 --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modmono/src/OxideMain.cs @@ -0,0 +1,25 @@ +using System; +using System.Runtime.Remoting; +using System.Runtime.Remoting.Lifetime; + +namespace Fivestops.Oxide +{ + public class OxideMain + { + public static void Main (string[] argv) + { + try + { + CausalityClient.Init (int.Parse (argv[0])); + + OxideApplicationPool oapPool = new OxideApplicationPool(); + + oapPool.ProcessRequests(); + } + catch (Exception e) + { + Console.WriteLine ("ex:\n{0}", e); + } + } + } +} diff --git a/lc-continuity/mk4/mobility-client/modmono/src/OxideThreadPool.cs b/lc-continuity/mk4/mobility-client/modmono/src/OxideThreadPool.cs new file mode 100644 index 0000000000000000000000000000000000000000..f73781c8e3a43d504052168b4651e737575f208c --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modmono/src/OxideThreadPool.cs @@ -0,0 +1,87 @@ + +namespace Fivestops.Oxide +{ + class OxideThreadPool + { + private static OxideThreadPool s_otpPool = null; + + private Queue m_qRequestQueue; + + private long m_lThreadsInUse = 0; + private long m_lCurrentThreads = 0; + + + static OxideThreadPool() + { + s_otpPool = new OxideThreadPool(); + } + + private OxideThreadPool() + { + m_qRequestQueue = Queue.Synchronized (new Queue()); + } + + private void QueueUserWorkItem (WaitCallback callback, object context) + { + OxideThreadPoolItem otpiItem = new OxideThreadPoolItem(); + + otpiItem.Callback = callback; + otpiItem.Context = context; + + m_qRequestQueue.Enqueue (otpiItem); + } + + public static void QueueUserWorkItem (WaitCallback callback) + { + s_otpPool.QueueUserWorkItem (callback, null); + } + + public static void QueueUserWorkItem (WaitCallback callback, object context) + { + s_otpPool.QueueUserWorkItem (callback, context); + } + + private void WorkerThread() + { + bool bWaitFor = false; + + try + { + Interlocked.Increment (ref m_lCurrentThreads); + + while (true) + { + try + { + OxideThreadPoolItem otpiItem = (OxideThreadPoolItem) m_qRequestQueue.Dequeue(); + + try + { + Interlocked.Increment (ref m_lThreadsInUse); + + otpiItem.Callback (otpiItem.Context); + } + finally + { + Interlocked.Decrement (ref m_lThreadsInUse); + } + } + catch (InvalidOperationException) + { + bWait = true; + } + } + } + finally + { + Interlocked.Decrement (ref m_lCurrentThreads); + } + } + + struct OxideThreadPoolItem + { + public WaitCallback Callback; + public object Context; + } + } +} diff --git a/lc-continuity/mk4/mobility-client/modmono/src/OxideWorkerRequest.cs b/lc-continuity/mk4/mobility-client/modmono/src/OxideWorkerRequest.cs new file mode 100644 index 0000000000000000000000000000000000000000..7cae3fe23ab98214ec421d85ef3f1c5e194a70b0 --- /dev/null +++ b/lc-continuity/mk4/mobility-client/modmono/src/OxideWorkerRequest.cs @@ -0,0 +1,267 @@ + +// #define DEBUG + +using System; +using System.Text; +using System.Web; +using System.IO; +using System.Web.Hosting; + +namespace Fivestops.Oxide +{ + public class OxideWorkerRequest : HttpWorkerRequest + { + CausalityRequest m_crRequest; + + public OxideWorkerRequest (CausalityRequest request) + { + if (request == null) + { + throw (new ArgumentNullException ("request")); + } + + m_crRequest = request; + + if (m_crRequest.Page == "/exit.w3wp.aspx") + { + Environment.Exit (1); + } + } + + public override void CloseConnection() + { + m_crRequest.Finish(); + } + + public override void EndOfRequest() + { + m_crRequest.Finish(); + } + + public override void FlushResponse (bool finalFlush) + { + // currently does nothing -- we send our data back as soon as we + // get it + } + + public override string GetAppPath() + { + return ((string) AppDomain.CurrentDomain.GetData (".hostingVirtualPath")); + } + + public override string GetAppPathTranslated() + { + return ((string) AppDomain.CurrentDomain.GetData (".appPath")); + } + + public override string GetFilePath() + { + string path = m_crRequest.GetVariable ("path"); + + string strAppPath = this.GetAppPathTranslated().TrimEnd ('/'); + + if (path.StartsWith (strAppPath)) + { + return (path.Substring (strAppPath.Length)); + } + else + { + return (m_crRequest.GetVariable ("uri")); + } + } + + public override string GetFilePathTranslated() + { + string path = m_crRequest.GetVariable ("path"); + + return (path); + } + + public override string GetHttpVerbName() + { + return (m_crRequest.GetVariable ("method")); + } + + public override string GetHttpVersion() + { + return (m_crRequest.GetVariable ("protocol")); + } + + public override string GetKnownRequestHeader (int index) + { + string strKey = HttpWorkerRequest.GetKnownRequestHeaderName (index); + + // temporarily not passing on Accept-Encoding until we are passing + // response headers back + if (strKey == "Accept-Encoding") + { + return (null); + } + + return (GetUnknownRequestHeader (strKey)); + } + + public override string GetLocalAddress() + { + return ("(unknown)"); + } + + public override int GetLocalPort() + { + return (0); + } + + public override string GetPathInfo() + { + return (m_crRequest.GetVariable ("path_info")); + } + + // we don't preload anything in this process until it's requested + public override byte[] GetPreloadedEntityBody() + { + return (new byte[0]); + } + + public override string GetProtocol() + { + if (this.IsSecure() == true) + { + return ("HTTPS"); + } + else + { + return ("HTTP"); + } + } + + public override string GetQueryString() + { + return (m_crRequest.Query); + } + + public override byte[] GetQueryStringRawBytes() + { + return (Encoding.UTF8.GetBytes (m_crRequest.Query)); + } + + public override string GetRawUrl() + { + string strUrl = this.GetUriPath(); + + if (this.GetPathInfo() != null && this.GetPathInfo() != string.Empty) + { + strUrl += this.GetPathInfo(); + } + + if (this.GetQueryString() != null && this.GetQueryString() != string.Empty) + { + strUrl += "?" + this.GetQueryString(); + } + + return (strUrl); + } + + public override string GetRemoteAddress() + { + return (m_crRequest.GetRemoteIP()); + } + + // we don't currently have the remote port. + public override int GetRemotePort() + { + return (0); + } + + public override string GetUriPath() + { + return (m_crRequest.GetVariable ("uri")); + } + + public override string GetUnknownRequestHeader (string name) + { + string strValue = m_crRequest.GetRequestHeader (name.ToLower()); + + return (strValue); + } + + public override bool HeadersSent() + { + return (m_crRequest.HeadersSent()); + } + + // THIS IS NOT WINDOWS AWARE + public override string MapPath (string virtualPath) + { + string strPath = this.GetAppPathTranslated(); + + // make sure we're dealing with a path within our application + if (virtualPath.StartsWith (this.GetAppPath()) == false) + { + return (null); + } + + if (virtualPath[0] == '/') + { + if (virtualPath.Length == 1) + { + return (strPath); + } + + virtualPath = virtualPath.Substring (1); + } + + return (Path.Combine (strPath, virtualPath)); + } + + public override void SendResponseFromMemory (byte[] data, int len) + { + if (m_crRequest.Write (data, len) == false) + { + // if we can't write, we'll assume the connection is dead. + HttpContext.Current.ApplicationInstance.CompleteRequest(); + } + } + + public override void SendResponseFromFile (IntPtr handle, long offset, long length) + { + throw (new NotImplementedException ()); + } + + public override void SendResponseFromFile (string filename, long offset, long length) + { + throw (new NotImplementedException ()); + } + + public override void SendStatus (int status, string description) + { + m_crRequest.SetStatus (status, description); + } + + public override void SendKnownResponseHeader (int index, string value) + { + string strKey = HttpWorkerRequest.GetKnownRequestHeaderName (index); + + this.SendUnknownResponseHeader (strKey, value); + } + + public override void SendUnknownResponseHeader (string key, string value) + { + m_crRequest.SetResponseHeader (key, value); + } + + public override int ReadEntityBody (byte[] buffer, int size) + { + return (m_crRequest.ReadEntityBody (buffer, size)); + } + + public override void SendCalculatedContentLength (int length) + { + this.SendUnknownResponseHeader ("Content-Length", length.ToString()); + } + + public override bool IsEntireEntityBodyIsPreloaded() + { + return (m_crRequest.IsEntireEntityLoaded()); + } + } +} diff --git a/lc-continuity/mk4/modbeacon/CVS/Entries b/lc-continuity/mk4/modbeacon/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..c495212b2b5ac8e74f1e57c91e96fd2209933d62 --- /dev/null +++ b/lc-continuity/mk4/modbeacon/CVS/Entries @@ -0,0 +1,5 @@ +/Makefile.in/1.3/Wed May 12 13:56:52 2004//Tmk4_mod6_rc2 +/beacon.c/1.8/Tue Jun 22 15:55:38 2004//Tmk4_mod6_rc2 +/beacon.xml/1.2/Wed May 12 15:09:20 2004//Tmk4_mod6_rc2 +/kstat.h/1.1.1.1/Mon Nov 17 21:05:41 2003//Tmk4_mod6_rc2 +D diff --git a/lc-continuity/mk4/modbeacon/CVS/Repository b/lc-continuity/mk4/modbeacon/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..ded1fcdd07f2d785b419203893d68d54a145e1d4 --- /dev/null +++ b/lc-continuity/mk4/modbeacon/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/modbeacon diff --git a/lc-continuity/mk4/modbeacon/CVS/Root b/lc-continuity/mk4/modbeacon/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/modbeacon/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/modbeacon/CVS/Tag b/lc-continuity/mk4/modbeacon/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/modbeacon/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/modbeacon/Makefile.in b/lc-continuity/mk4/modbeacon/Makefile.in new file mode 100644 index 0000000000000000000000000000000000000000..15cc885a47be930db363ea92ab04d4f83fd076a7 --- /dev/null +++ b/lc-continuity/mk4/modbeacon/Makefile.in @@ -0,0 +1,24 @@ +# $Header: /san01/cvs/ashpool/csrc/modbeacon/Attic/Makefile.in,v 1.3 2004/05/12 13:56:52 aleigh Exp $ + +include ../continuity/lib/env.mk + +SRCS=beacon.c +OBJS=beacon.o +OUT=beacon.so + +CFLAGS=-I../continuity/include $(CONT_FLAGS) + +world: install + +$(OUT): $(OBJS) + $(LD_SHARECMD) -o $(OUT) $(OBJS) +clean: + $(RM) $(OBJS) *~ $(OUT) + +install: $(OUT) + cp $(OUT) ../continuity/lib + cp beacon.xml ../continuity/lib + + +depend: + $(MAKEDEPEND) $(DEPFLAGS) -I ../continuity/include $(SRCS) diff --git a/lc-continuity/mk4/modbeacon/beacon.c b/lc-continuity/mk4/modbeacon/beacon.c new file mode 100644 index 0000000000000000000000000000000000000000..628262d01b711608a2f0cceff21ec487cab80acb --- /dev/null +++ b/lc-continuity/mk4/modbeacon/beacon.c @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2004 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Use, disclosure, copying, distribution, or transmission of this code without + * express permission is prohibited. + */ + +#include +#include + +struct tasSstat { + unsigned int tas_ctime; + struct tasSstat *tas_next; + + char tas_module[TA_STAT_STRLEN]; + int tas_instance; + char tas_name[TA_STAT_STRLEN]; + int tas_type; + char tas_class[TA_STAT_STRLEN]; + unsigned char tas_flags; + void *tas_data; + size_t tas_data_size; + unsigned int tas_ndata; +}; + +struct tasSctl { + struct tasSstat *chain; +}; + +int beaconFstatpage(httpTtrans *t, lstTset *set) +{ + tasTstat *p; + char *v1 = "TAS Chain empty.\n"; + char buf[1024]; + struct timeval tv; + const char *uri; + + uri = lstFset_get(t->vars, "uri"); + + if (strcmp(uri, "/.sc_stat") != 0) + return STATUS_PROCEED; + + lstFset_update(t->res_hdrs, "Content-Type", "text/plain"); + httpFset_status(t, 200, NULL); + httpFstart_response(t); + + p = tasFget_chain(); + + if (p == NULL) { + httpFwrite(t, v1, strlen(v1)); + return STATUS_EXIT; + } + while (1) { + gettimeofday(&tv, NULL); /* $$$ but accurate */ + + sprintf(buf, + "ta,%s.%d.%s,", + p->tas_module, p->tas_instance, p->tas_name); + + httpFwrite(t, buf, strlen(buf)); + + if (p->tas_type == TA_STAT_INT) { + int *ip; + ip = p->tas_data; + sprintf(buf, "%d", *ip); + httpFwrite(t, buf, strlen(buf)); + } + if (p->tas_type == TA_STAT_UINT) { + unsigned int *ip; + ip = p->tas_data; + sprintf(buf, "%u", *ip); + httpFwrite(t, buf, strlen(buf)); + } + sprintf(buf, ",%lu,%lu\n", tv.tv_sec, tv.tv_usec); + httpFwrite(t, buf, strlen(buf)); + + if (p->tas_next == NULL) + break; + p = p->tas_next; + } + + return STATUS_EXIT; +} + +static void beaconFthread(void) +{ + uint32_t pages_total, pages_free, phys_mem, availr_mem, free_mem; + uint32_t idle, user, kernel, wait; + uint32_t n_idle, n_user, n_kernel, n_wait; + uint32_t o_idle, o_user, o_kernel, o_wait; + uint32_t ibytes, obytes, ipkts, opkts; + + /* Since we are dealing with deltas, we will load the "old" values + * and do nothing about them. This will prevent an apparently huge + * spike appearing in the graphs when the first response from the server + * are the since-rollover values. + */ + sysFcpu_usage(&o_idle,&o_user,&o_kernel,&o_wait); + + while(1) { + sysFmem_usage(&pages_total,&pages_free, + &phys_mem,&availr_mem,&free_mem); + tasFstat_set("sys",0,"pagestotal",pages_total); + tasFstat_set("sys",0,"pagesfree",pages_free); + tasFstat_set("sys",0,"physmem",phys_mem); + tasFstat_set("sys",0,"availrmem",availr_mem); + tasFstat_set("sys",0,"freemem",free_mem); + + + sysFcpu_usage(&idle,&user,&kernel,&wait); + n_idle=idle-o_idle; + n_user=user-o_user; + n_kernel=kernel-o_kernel; + n_wait=wait-o_wait; + + tasFstat_set("cpu",0,"idle_time",n_idle); + tasFstat_set("cpu",0,"user_time",n_user); + tasFstat_set("cpu",0,"kernel_time",n_kernel); + tasFstat_set("cpu",0,"wait_time",n_wait); + tasFstat_set("cpu",0,"total_time",n_idle+n_user+n_kernel+n_wait); + + o_idle=idle; + o_user=user; + o_kernel=kernel; + o_wait=wait; + + sysFnet_usage(&obytes, &ibytes, &opkts, &ipkts); + tasFstat_set("net",0,"bytes_out",obytes); + tasFstat_set("net",0,"bytes_in",ibytes); + + thrFsleep(5000); + } +} + + +int beaconFinit(void *p, lstTset * o) +{ + pthread_t tid; + + logFmsg(0,"mod/beacon: System metrics beacon."); + logFmsg(0,"Copyright (c) 2004, Alex Leigh"); + + pthread_create(&tid,NULL,(void *(*)(void *))&beaconFthread,NULL); + + return STATUS_PROCEED; +} + +int tasFrts_stream(httpTtrans * t, lstTset * opts) +{ + tasTstat *p; + char *v1 = "TAS Chain empty.\n"; + char buf[1024]; + struct timeval tv; + char *uri; + + uri = lstFset_get(t->vars, "uri"); + if (strcmp(uri, "/continuity.rts") != 0) + return STATUS_PROCEED; + + lstFset_update(t->res_hdrs, "Content-Type", "text/plain"); + httpFset_status(t, 200, NULL); + httpFstart_response(t); + + p = tasFget_chain(); + + if (p == NULL) { + httpFwrite(t, v1, strlen(v1)); + return STATUS_EXIT; + } + while (1) { + p = tasFget_chain(); + + while (1) { + gettimeofday(&tv, NULL); /* $$$ but accurate */ + + sprintf(buf, + "ty=u&na=%s.%d.%s", + p->tas_module, p->tas_instance, p->tas_name); + + httpFwrite(t, buf, strlen(buf)); + + if (p->tas_type == TA_STAT_INT) { + int *ip; + ip = p->tas_data; + sprintf(buf, "&va=%d", *ip); + httpFwrite(t, buf, strlen(buf)); + } + if (p->tas_type == TA_STAT_UINT) { + unsigned int *ip; + ip = p->tas_data; + sprintf(buf, "&va=%u", *ip); + httpFwrite(t, buf, strlen(buf)); + } + sprintf(buf, "&ti=%lu.%lu\n", tv.tv_sec, tv.tv_usec); + httpFwrite(t, buf, strlen(buf)); + + if (p->tas_next == NULL) + break; + p = p->tas_next; + } + thrFsleep(1000); + } + return STATUS_EXIT; +} + diff --git a/lc-continuity/mk4/modbeacon/beacon.xml b/lc-continuity/mk4/modbeacon/beacon.xml new file mode 100644 index 0000000000000000000000000000000000000000..abdcec5c2d8ee6bb30cd80454acdb139f3308c18 --- /dev/null +++ b/lc-continuity/mk4/modbeacon/beacon.xml @@ -0,0 +1,4 @@ + + beacon + beaconFinit + diff --git a/lc-continuity/mk4/modbeacon/kstat.h b/lc-continuity/mk4/modbeacon/kstat.h new file mode 100644 index 0000000000000000000000000000000000000000..0cd3c421f683578e4910e4b5e6254e2a803513d6 --- /dev/null +++ b/lc-continuity/mk4/modbeacon/kstat.h @@ -0,0 +1,23 @@ +#ifndef TA_KSTAT_H +#define TA_KSTAT_H + +#pragma ident "@(#) $Header: /san01/cvs/ashpool/csrc/modbeacon/Attic/kstat.h,v 1.1.1.1 2003/11/17 21:05:41 aleigh Exp $" + +/* + * These descriptions are assumptions and are not entirely + * accurate. Most solaris systems have an 8k page size. + */ + +struct taSmemuse { + unsigned int pagestotal; /* Total pages on the system */ + unsigned int pagesfree; /* Pages free on the system */ + unsigned int physmem; /* Physical Memory installed in the machine */ + unsigned int availrmem; /* Available physical memory, not including fscache */ + unsigned int freemem; /* Available physical memoroy, including fscache */ +}; +typedef struct taSmemuse taTmemuse; + +double kstatFget_load(void); + +#endif + diff --git a/lc-continuity/mk4/modcommand/CVS/Entries b/lc-continuity/mk4/modcommand/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..3d1b31f113ccd43a8bdba560ecf288b4ebd0fe59 --- /dev/null +++ b/lc-continuity/mk4/modcommand/CVS/Entries @@ -0,0 +1,5 @@ +/Makefile.in/1.2/Wed May 12 13:49:25 2004//Tmk4_mod6_rc2 +/cmd.c/1.16/Tue May 11 15:36:17 2004//Tmk4_mod6_rc2 +/cmd.h/1.7/Tue May 11 15:36:17 2004//Tmk4_mod6_rc2 +/cmd.xml/1.2/Wed May 12 14:29:44 2004//Tmk4_mod6_rc2 +D diff --git a/lc-continuity/mk4/modcommand/CVS/Repository b/lc-continuity/mk4/modcommand/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..4452104036d3661062a1cb96e4d93e72956943a4 --- /dev/null +++ b/lc-continuity/mk4/modcommand/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/modcommand diff --git a/lc-continuity/mk4/modcommand/CVS/Root b/lc-continuity/mk4/modcommand/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/modcommand/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/modcommand/CVS/Tag b/lc-continuity/mk4/modcommand/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/modcommand/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/modcommand/Makefile.in b/lc-continuity/mk4/modcommand/Makefile.in new file mode 100644 index 0000000000000000000000000000000000000000..d66d38e1c21375b262918ec4d08809ff534fb1b1 --- /dev/null +++ b/lc-continuity/mk4/modcommand/Makefile.in @@ -0,0 +1,24 @@ +# $Header: /san01/cvs/ashpool/csrc/modcommand/Attic/Makefile.in,v 1.2 2004/05/12 13:49:25 aleigh Exp $ + +include ../continuity/lib/env.mk + +SRCS=cmd.c +OBJS=cmd.o + +CFLAGS=-I../continuity/include $(CONT_FLAGS) -fPIC + +world: install + +cmd.so: $(OBJS) + $(LD_SHARECMD) -o cmd.so $(OBJS) +clean: + $(RM) $(OBJS) *~ cmd.so + +install: cmd.so cmd.h + (rm -f ../continuity/lib/cmd.so ; cp cmd.so ../continuity/lib) + cp cmd.h ../continuity/include + cp cmd.xml ../continuity/lib + + +depend: + $(MAKEDEPEND) -I../continuity/include $(DEPFLAGS) $(SRCS) diff --git a/lc-continuity/mk4/modcommand/cmd.c b/lc-continuity/mk4/modcommand/cmd.c new file mode 100644 index 0000000000000000000000000000000000000000..018b409abe21fd52a51bb5daf5b2a8f42a4b16e2 --- /dev/null +++ b/lc-continuity/mk4/modcommand/cmd.c @@ -0,0 +1,430 @@ +/* $Id: cmd.c,v 1.16 2004/05/11 15:36:17 aleigh Exp $ */ + +/* + * Copyright (c) 1994, 2001 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Use, disclosure, copying, distribution, or transmission of this code without + * express permission is prohibited. + */ + +#include "cmd.h" + +static char cmdGhostname[64]; + +#define CMDLEN 256 + +struct cmdSop { + const char *op_name; + int (*op_func)(netTconn *conn, int argc, char **argv); + const char *helpmsg; + struct cmdSop *sub_ops; + struct cmdSop *next; +}; +/* typedef in cmd.h */ + +struct cmdSstate { + char cmd[CMDLEN]; + int len; +}; +typedef struct cmdSstate cmdTstate; + +#define CMDPROTO(x) static int x(netTconn *conn, int argc, char **argv) + +CMDPROTO(cmdFop_quit); +CMDPROTO(cmdFop_show_version); +CMDPROTO(cmdFop_show_time); +CMDPROTO(cmdFop_reload); +CMDPROTO(cmdFop_halt); + +cmdTop *cmdGops = NULL; +lstTset *cmdGusers=NULL; + +cmdTop *cmdFroot(void) { + return cmdGops; +} + +void cmdFbind_stub(cmdTop *parent, + const char *cmd, + const char *helpmsg) { + cmdTop *newop; + + newop=(cmdTop *)malloc(sizeof(cmdTop)); + newop->op_name=strFcopy(cmd); + newop->sub_ops=NULL; + newop->helpmsg=strFcopy(helpmsg); + + if(parent->sub_ops==NULL) { + newop->next=NULL; + parent->sub_ops=newop; + } else { + newop->next=parent->sub_ops; + parent->sub_ops=newop; + } +} + +void cmdFbind_command(cmdTop *parent, + const char *cmd, + int(*op_func)(netTconn *conn, int argc, char **argv), const char *helpmsg) { + cmdTop *newop; + + newop=(cmdTop *)malloc(sizeof(cmdTop)); + newop->op_func=op_func; + newop->op_name=strFcopy(cmd); + newop->sub_ops=NULL; + newop->helpmsg=strFcopy(helpmsg); + + if(parent->sub_ops==NULL) { + newop->next=NULL; + parent->sub_ops=newop; + } else { + newop->next=parent->sub_ops; + parent->sub_ops=newop; + } +} + +int cmdFinit(lstTset *opt) +{ + cmdTop *op; + cmdTop *newop; + + logFmsg(0,"mod/cmd: Command Interpreter"); + logFmsg(0,"Copyright (c) 2004, Alex Leigh"); + + gethostname(cmdGhostname,64); + + cmdGusers=lstFset_init(); + + newop=(cmdTop *)malloc(sizeof(cmdTop)); + memFclear((void *)newop,sizeof(cmdTop)); + newop->op_name=strFcopy("root"); + cmdGops=newop; + + cmdFbind_command(cmdGops,"quit",cmdFop_quit, "Disconnect session."); + cmdFbind_command(cmdGops,"reload",cmdFop_reload, "Reload this Continuity instance."); + cmdFbind_command(cmdGops,"halt",cmdFop_halt, "Halt this Continuity instance."); + + cmdFbind_stub(cmdGops,"show", "Show information."); + op=cmdFmatch("show",cmdGops); + cmdFbind_command(op,"version",cmdFop_show_version, "Show version information."); + cmdFbind_command(op,"time",cmdFop_show_time, "Show current time."); + + cmdFbind_stub(op,"dl", "Dynamic Loader"); + op=cmdFmatch("dl",op); + cmdFbind_command(op,"loads",dlFop_show_dl_loads, "Show current module loads."); + cmdFbind_command(op,"symbols",dlFop_show_dl_symbols, "Show currently mapped funcions."); + + return STATUS_OK; +} + +static void cmdFecho_on(netTconn *conn) +{ + char off_string[] = + { + (char) IAC, + (char) WONT, + (char) TELOPT_ECHO, + (char) TELOPT_NAOFFD, + (char) TELOPT_NAOCRD, + (char) 0, + }; + + netFconn_write(conn, off_string, sizeof(off_string)); +} + +static void cmdFecho_off(netTconn *conn) +{ + char off_string[] = + { + (char) IAC, + (char) WILL, + (char) TELOPT_ECHO, + (char) TELOPT_NAOFFD, + (char) TELOPT_NAOCRD, + (char) 0, + }; + + netFconn_write(conn, off_string, sizeof(off_string)); +} + +static cmdTstate *cmdFstate_init(void) { + cmdTstate *s; + + s=(cmdTstate *)malloc(sizeof(cmdTstate)); + assert(s!=NULL); + + memFclear(s,sizeof(cmdTstate)); + + return s; +} + +static int cmdFgather(netTconn *conn, cmdTstate *state) +{ + char c; + ssize_t ret; + size_t ignore=0; + + while(1) { + ret=read(conn->sd,&c,1); + if(ret==0) { + return -1; + } + + if(ret!=1) { + return -1; + } + + if(ignore>0) { + ignore--; + continue; + } + + switch(c) { + case '\r': + continue; + case '\n': + state->cmd[state->len]=0; + logFmsg(3,"cmd: %s", state->cmd); + state->len=0; + return 0; + case (char)IAC: + ignore+=2; + continue; + } + + // logFmsg(3,"read char: %c %u", c, c); + + state->cmd[state->len]=c; + state->len++; + } +} + +static int cmdFuser_auth(const char *un, const char *pw) { + assert(un!=NULL); + assert(pw!=NULL); + + char *goodpw=lstFset_get(cmdGusers,un); + + if(goodpw==NULL) return 0; + + logFmsg(3,"%s/%s", goodpw, pw); + + if(strcmp(goodpw,pw)!=0) return 0; + + return 1; +} + +cmdTop *cmdFmatch(const char *cmd, cmdTop *ops) { + int partials=0; + cmdTop *partial_op, *op; + + assert(cmd!=NULL); + assert(ops!=NULL); + + // logFmsg(3,"searching for cmd: ->%s<-", cmd); + + size_t clen=strlen(cmd); + + for(op=ops->sub_ops;op!=NULL;op=op->next) { + + // logFmsg(3,"searching for %s: eval %s", cmd, op->op_name); + + if(strcmp(cmd,op->op_name)==0) { + return op; + } + + if(strncmp(cmd,op->op_name,clen)==0) { + partials++; + partial_op=op; + } + } + + if(partials==0) { + /* Command not found */ + return NULL; + } else { + if(partials==1) { + return partial_op; + } + } + + /* Ambiguous expansion */ + return NULL; +} + +static void cmdFdo_help(netTconn *conn, cmdTop *op) { + + netFconn_writef(conn,"\r\nHelp\r\n----\r\n"); + + for(;op!=NULL;op=op->next) { + netFconn_writef(conn, "%s\t%s\r\n", op->op_name, op->helpmsg); + } +} + +static void cmdFloop(netTconn *conn, cmdTstate *state) +{ + char *stack[32]; + const cmdTop *op; + int argc; + + while(1) { + netFconn_writef(conn,"%s -> ", cmdGhostname); + + if(cmdFgather(conn,state)==-1) { + return; + } + + argc=strFsplit(state->cmd, stack, 32, ' ', '"'); + + cmdTop *p; + + p=cmdGops; + + for(int i=0;i%s<-", stack[i]); + + if(strcmp(stack[i],"?")==0) { + cmdFdo_help(conn,p->sub_ops); + continue; + } + + op=cmdFmatch(stack[i],p); + + if(op!=NULL) { + if(op->sub_ops!=NULL) { + p=op; + continue; + } + + if(op->op_func(conn,argc-i,&stack[i])==STATUS_EXIT) { + return; + } else { + break; + } + } else { + netFconn_writef(conn,"Invalid command.\r\n"); + break; + } + } + } +} + + +void cmdFhandler(netTconn *conn) +{ + cmdTstate *state=cmdFstate_init(); + char username[16]; + + assert(conn!=NULL); + assert(state!=NULL); + + while(1) { + netFconn_writef(conn,"\r\nlogin: "); + + if(cmdFgather(conn,state)==-1) { + break; + } + + strncpy(username,state->cmd,16); + + cmdFecho_off(conn); + netFconn_writef(conn,"Password: "); + + if(cmdFgather(conn,state)==-1) { + break; + } + + cmdFecho_on(conn); + + if(cmdFuser_auth(username,state->cmd)==0) { + netFconn_writef(conn,"login denied.\r\n"); + continue; + } + + logFmsg(3,"logged in."); + netFconn_writef(conn,"\r\nLogin accepted.\r\n"); + netFconn_writef(conn,"\r\n%s\r\n", BUILD_STRING); + + cmdFloop(conn,state); + break; + } + + logFmsg(3,"Shutting down connection."); + + netFconn_close(conn); +} + +static int cmdFop_quit(netTconn *conn, int argc, char **argv) +{ + netFconn_writef(conn,"Goodbye.\r\n"); + + return STATUS_EXIT; +} + +static int cmdFop_show_version(netTconn *conn, int argc, char **argv) { + netFconn_writef(conn,"\r\nVersion\r\n-------\r\n"); + op_show_version(conn); + return STATUS_OK; +} + +static int cmdFop_reload(netTconn *conn, int argc, char **argv) { + if(argc<2) { + netFconn_writef(conn,"Usage: RELOAD YES\r\n"); + return STATUS_OK; + } + + if(strcasecmp(argv[1],"yes")!=0) { + netFconn_writef(conn,"Usage: RELOAD YES\r\n"); + return STATUS_OK; + } + + netFconn_writef(conn,"Reloading instance...\r\n"); + + exit(0); +} + +static int cmdFop_halt(netTconn *conn, int argc, char **argv) { + if(argc<2) { + netFconn_writef(conn,"Usage: HALT YES\r\n"); + return STATUS_OK; + } + + if(strcasecmp(argv[1],"yes")!=0) { + netFconn_writef(conn,"Usage: HALT YES\r\n"); + return STATUS_OK; + } + + netFconn_writef(conn,"Halting instance...\r\n"); + + /* Instruct cdog to die if we are running under it */ + exit(5); +} + +static int cmdFop_show_time(netTconn *conn, int argc, char **argv) { + netFconn_writef(conn,"%s\r\n", utlFcommonlog_time()); + return STATUS_OK; +} + +static int cmdFop_show_uptime(netTconn *conn, int argc, char **argv) { + netFconn_writef(conn,"Uptime\r\n------\r\n"); + return STATUS_OK; +} + +int cmdFadd_user(void *p, lstTset *opt) { + const char *un, *pw; + + un=lstFset_get(opt,"user"); + pw=lstFset_get(opt,"password"); + + if(un!=NULL && pw!=NULL) { + lstFset_add(cmdGusers,un,pw); + } else { + logFmsg(2,"Failed."); + exit(5); + } + + return STATUS_OK; +} diff --git a/lc-continuity/mk4/modcommand/cmd.h b/lc-continuity/mk4/modcommand/cmd.h new file mode 100644 index 0000000000000000000000000000000000000000..f8770fc823abe0c1f1c87ec357ecdc894573b428 --- /dev/null +++ b/lc-continuity/mk4/modcommand/cmd.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 1994, 2001 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Use, disclosure, copying, distribution, or transmission of this code without + * express permission is prohibited. + */ + +#ifndef _CMD_H +#define _CMD_H + +#include +#include + +typedef struct cmdSop cmdTop; + +void cmdFbind_stub(cmdTop *parent,const char *cmd, const char *helpmsg); +void cmdFbind_command(cmdTop *parent, + const char *cmd, + int(*op_func)(netTconn *conn, int argc, char **argv), + const char *helpmsg); +cmdTop *cmdFroot(void); +cmdTop *cmdFmatch(const char *cmd, cmdTop *ops); +int cmdFadd_user(void *p, lstTset *opt); +#endif + diff --git a/lc-continuity/mk4/modcommand/cmd.xml b/lc-continuity/mk4/modcommand/cmd.xml new file mode 100644 index 0000000000000000000000000000000000000000..8efa1377015435b701f71fd7c2d2b49135fb552f --- /dev/null +++ b/lc-continuity/mk4/modcommand/cmd.xml @@ -0,0 +1,4 @@ + + cmd + cmdFinit + diff --git a/lc-continuity/mk4/moddb/CVS/Entries b/lc-continuity/mk4/moddb/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..153c97613917de8f4d65e6a87354ccdec0df54be --- /dev/null +++ b/lc-continuity/mk4/moddb/CVS/Entries @@ -0,0 +1,5 @@ +/Makefile.in/1.3/Wed May 12 13:57:25 2004//Tmk4_mod6_rc2 +/db.c/1.6/Fri May 14 06:20:33 2004//Tmk4_mod6_rc2 +/db.h/1.5/Fri May 14 06:20:33 2004//Tmk4_mod6_rc2 +/db.xml/1.1/Wed May 12 13:58:08 2004//Tmk4_mod6_rc2 +D diff --git a/lc-continuity/mk4/moddb/CVS/Repository b/lc-continuity/mk4/moddb/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..7204c42cbf66d24f2b260b8b0bca44638657bfed --- /dev/null +++ b/lc-continuity/mk4/moddb/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/moddb diff --git a/lc-continuity/mk4/moddb/CVS/Root b/lc-continuity/mk4/moddb/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/moddb/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/moddb/CVS/Tag b/lc-continuity/mk4/moddb/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/moddb/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/moddb/Makefile.in b/lc-continuity/mk4/moddb/Makefile.in new file mode 100644 index 0000000000000000000000000000000000000000..2bc5c2535e5406088a2a6ee1cab17097dd21151a --- /dev/null +++ b/lc-continuity/mk4/moddb/Makefile.in @@ -0,0 +1,24 @@ +# $Header: /san01/cvs/ashpool/csrc/moddb/Attic/Makefile.in,v 1.3 2004/05/12 13:57:25 aleigh Exp $ + +include ../continuity/lib/env.mk + +SRCS=db.c +OBJS=db.o + +CFLAGS=-I../continuity/include $(CONT_FLAGS) + +world: install + +db.so: $(OBJS) + $(LD_SHARECMD) -o db.so $(OBJS) +clean: + $(RM) $(OBJS) *~ db.so + +install: db.so db.h + (rm -f ../continuity/lib/db.so ; cp db.so ../continuity/lib) + cp db.h ../continuity/include + cp db.xml ../continuity/lib + + +depend: + $(MAKEDEPEND) $(DEPFLAGS) -I ../continuity/include $(SRCS) diff --git a/lc-continuity/mk4/moddb/db.c b/lc-continuity/mk4/moddb/db.c new file mode 100644 index 0000000000000000000000000000000000000000..05778da95224e813b0027b874f6d64187667a16a --- /dev/null +++ b/lc-continuity/mk4/moddb/db.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 1994, 2001 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Disclosure, copying, distribution, or transmission of this code without + * express permission is prohibited. + */ + +#include +#include "db.h" + +static dbTvector *vector = NULL; + +void dbFvector_register(dbTvector * vec) +{ + vector = vec; +} + +void *dbFopen(const char *user, const char *password, const char *service) +{ + return (*vector->open_fn) (user, password, service); +} + +int dbFclose(void *conn) +{ + return (*vector->close_fn) (conn); +} + +lstTset *dbFselect(void *conn, const char *sql) +{ + return (*vector->select_fn) (conn, sql); +} + +void dbFinit(void) +{ + (*vector->init_fn) (); +} + +int dbFgetrow(void *conn, lstTset * row) +{ + return (*vector->getrow_fn) (conn, row); +} + +int dbFdml(void *conn, const char *sql) +{ + return (*vector->dml_fn) (conn, sql); +} diff --git a/lc-continuity/mk4/moddb/db.h b/lc-continuity/mk4/moddb/db.h new file mode 100644 index 0000000000000000000000000000000000000000..344770e4df2f978a0716724b0a21f85458bdb876 --- /dev/null +++ b/lc-continuity/mk4/moddb/db.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 1994, 2001 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Disclosure, copying, distribution, or transmission of this code without + * express permission is prohibited. + */ + +#ifndef _DB_H +#define _DB_H + +struct dbSvector { + void (*init_fn)(void); + void *(*open_fn)(const char *user, const char *password, const char *service); + int (*close_fn)(void *conn); + + lstTset *(*select_fn)(void *conn, const char *sql); + int (*getrow_fn)(void *conn, lstTset *row); + + int (*dml_fn)(void *conn, const char *sql); +}; +typedef struct dbSvector dbTvector; + +void dbFvector_register(dbTvector *vec); +void *dbFopen(const char *user, const char *password, const char *service); +int dbFclose(void *conn); +void dbFinit(void); +lstTset *dbFselect(void *conn, const char *sql); +int dbFgetrow(void *conn, lstTset *row); +int dbFdml(void *conn, const char *sql); + +#endif + diff --git a/lc-continuity/mk4/moddb/db.xml b/lc-continuity/mk4/moddb/db.xml new file mode 100644 index 0000000000000000000000000000000000000000..fe21915a20f3d51c437a6ac8b4596f1ff2896de2 --- /dev/null +++ b/lc-continuity/mk4/moddb/db.xml @@ -0,0 +1,3 @@ + + db + diff --git a/lc-continuity/mk4/moddynamo/CMLDRP.c b/lc-continuity/mk4/moddynamo/CMLDRP.c new file mode 100644 index 0000000000000000000000000000000000000000..80d24fb1854892ed24d0dbf3be84e436ec4a360e --- /dev/null +++ b/lc-continuity/mk4/moddynamo/CMLDRP.c @@ -0,0 +1,1485 @@ +/* + * Copyright (C) 1997 Art Technology Group, Inc. + * All Rights Reserved. No use, copying or distribution of this + * work may be made except in accordance with a valid license + * agreement from Art Technology Group. This notice must be + * included on all copies, modifications and derivatives of this + * work. + * + * Art Technology Group (ATG) MAKES NO REPRESENTATIONS OR WARRANTIES + * ABOUT THE SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. ATG SHALL NOT BE + * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, + * MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. + * + * "Dynamo" is a trademark of Art Technology Group, Inc. + */ + +/* + CMLDRP.c - routines for CMLDRP subsystem + ("Connection-Module Load-Distribution Request Protocol", or something) + */ + +#ifndef WIN32 +/* NT */ +#include +#include +#include +#include +#include +#endif + +/* #define DEBUG */ + +#include /* for sprintf */ +#include + +#include + +#include "DRPClient.h" +#include "CMLDRP.h" + +#ifdef _DRP_MTHREAD +#include "threadabstr.h" +#endif + +#define kSilentCMLDRPLogInterval 150 /* seconds */ + + + +/* static prototypes */ +static int generateCMLDRPIdentifier(CMLDRP_Block * pBlock, + unsigned short iHTTPPort); +static int dispatchResponseMetaData(CMLDRP_Block * pBlock, + int iBytesReceived); +static int dispatchResponseData(CMLDRP_Block * pBlock, int iBytesReceived); +static int cmldrpUpdate(CMLDRP_Block * pBlock); +static int selectNextCMLDRPServer(CMLDRP_Block * pBlock); +static int internalizeCMLDRPServerInfo(CMLDRP_Block * pBlock, + int iNumServers, + const CMLDRP_ServerInfo * iServers); +static int openUDPSocket(CMLDRP_Block * pBlock, const char *iBindAddress); + +/* NOTE: Currently not used so not declared. - Frank Kim, 12/28/99 (lmd 3/24/00) */ +#if 0 +static int compareDRPServerRecords_ipPort(const void *iRec1, + const void *iRec2); +#endif + +#ifdef _DRP_MTHREAD +static int connectToNextCMLDRPServer(CMLDRP_Block * pBlock); +static void closeCMLDRPConnection(CMLDRP_Block * pBlock); +static int startCMLDRPThread(CMLDRP_Block * pBlock); +static kThread_returnType cmldrpThreadFunction(kThread_argType iArg); + +static Thread_t gCMLDRPThread = kThread_InvalidThread; +RWLock gLoadDataLock; + +#define kDefaultMaxHandlers 100 /* a maximum of 100 handler threads */ +#define kDefaultHandlersTimeout 30000 /* wait at most 30 seconds to acquire mutex */ +#define kDefaultBackoffInterval 5 +/* wait at most 5 seconds once limit has exceeded before testing next time */ +RWLock gHandlerCountLock; +int gEnforceMaxHandlers = 0; /* By default do not enforce the max handlers */ +int gMaxHandlers = kDefaultMaxHandlers; +int gHandlerCount = 0; +int gExceededLimit = 0; +time_t gBackoffInterval = kDefaultBackoffInterval; /* in seconds */ +time_t gLastTimeThreadLimitReported = 0; +time_t gLastTimeExceededLimitReached = 0; +#endif + +/* global variables */ + +CMLDRP_Block gCMLDRPBlock; + +drpServerRecord gDrpServers[kMaxDRPRecords]; +drpServerRecord *gDrpServerPtrs[kMaxDRPRecords]; +int gNumDrpServers; + +DebugInfo gDebugInfo = { 0, /* numRequestThreads */ + 0, /* numActiveRequests */ + 0, /* numWaitingOnReadLock */ + 0, /* numWaitingOnPool */ + 0, /* numWaitingToConnect */ + 0, /* numSendingRequest */ + 0 +}; /* numWaitingForResponse */ + +unsigned short gCMLDRP_Shutdown; +unsigned int gCMLDRP_InfoVersion; +unsigned short gCMLDRP_UpdateNow; +unsigned short gCMLDRP_ManagerRotationEnabled = 1; + +#ifdef _DRP_MTHREAD +unsigned short gCMLDRP_UseTcp = 0; +int gCMLDRP_TcpTimeout = kCMLDRP_DefaultTcpTimeout; +unsigned short gCMLDRP_ThreadIsRunning = 0; +#endif + +#ifdef _CPOOL +extern int gCP_Enabled; +#endif + +/** + * cmldrpInitialize + * Initializes the CMLDRP subsystem and initiates the first attempt to + * obtain DRP server information from a CMLDRP server (in the multiprocess + * case) or starts the CMLDRP thread (in the multithreaded case). + * iNumServers: number of CMLDRP server info blocks in iServers + * iServers: array of CMLDRP_ServerInfo objects + * iBindAddress: address to which CMLDRP subsystem should bind its socket + * (NULL: bind to any appropriate local address) + * iHTTPPort: main service port of the host HTTP server (for purposes of + * identifying this CMLDRP client to the CMLDRP server). + * iLogFunction: http-server-API-specific logging routine + * iLogShellData: opaque shellData object to be passed to iLogFunction + * return: 0 == success; !0 == failure + */ +int +cmldrpInitialize(int iNumServers, CMLDRP_ServerInfo * iServers, + const char *iBindAddress, unsigned short iHTTPPort, + LogMessage_fn iLogFunction, void *iLogShellData) +{ + int returnValue = 0; + + memset(&gCMLDRPBlock, 0, sizeof(gCMLDRPBlock)); + + gCMLDRPBlock.logFunction = iLogFunction; + gCMLDRPBlock.logShellData = iLogShellData; + + gCMLDRPBlock.nextServerToContact = NULL; + gCMLDRPBlock.lastTimeSilenceReported = 0; + gCMLDRPBlock.sock = kInvalidSocket; + +#ifdef _DRP_MTHREAD + gCMLDRPBlock.inputStream = NULL; + gCMLDRPBlock.outputStream = NULL; +#endif + + gCMLDRPBlock.timeout.tv_sec = kCMLDRP_DefaultTimeoutSec; + gCMLDRPBlock.timeout.tv_usec = kCMLDRP_DefaultTimeoutUsec; + + gCMLDRPBlock.nextUpdateTime = time(NULL); + +#ifdef _DRP_MTHREAD + if (0 == gCMLDRP_UseTcp) { + returnValue = openUDPSocket(&gCMLDRPBlock, iBindAddress); + if (returnValue) + goto CMLDRP_INIT_EXIT; + } +#else + returnValue = openUDPSocket(&gCMLDRPBlock, iBindAddress); + if (returnValue) + goto CMLDRP_INIT_EXIT; +#endif + + + gCMLDRPBlock.httpPort = iHTTPPort; + + returnValue = generateCMLDRPIdentifier(&gCMLDRPBlock, iHTTPPort); + if (returnValue) + goto CMLDRP_INIT_EXIT; + + returnValue = internalizeCMLDRPServerInfo(&gCMLDRPBlock, iNumServers, + iServers); + if (returnValue) + goto CMLDRP_INIT_EXIT; + + gCMLDRPBlock.nextServerToContactIdx = 0; + + gNumDrpServers = 0; + + gCMLDRPBlock.cmldrpVersion = kCMLDRP_RequestVersion; + + gCMLDRP_Shutdown = 0; + gCMLDRP_UpdateNow = 0; + gCMLDRP_InfoVersion = 0; + +#ifdef _DRP_MTHREAD + if (initializeRWLock(&gLoadDataLock)) { + gCMLDRPBlock.logFunction(gCMLDRPBlock.logShellData, kLog_Error, + kLogMessage_CannotCreateRWLock, NULL, + NULL); + returnValue = -1; + goto CMLDRP_INIT_EXIT; + } + if (initializeRWLock(&gHandlerCountLock)) { + gCMLDRPBlock.logFunction(gCMLDRPBlock.logShellData, kLog_Error, + kLogMessage_CannotCreateRWLock, NULL, + NULL); + returnValue = -1; + goto CMLDRP_INIT_EXIT; + } + returnValue = startCMLDRPThread(&gCMLDRPBlock); +#else + cmldrpUpdate(&gCMLDRPBlock); /* discard return value */ +#endif + + CMLDRP_INIT_EXIT: + + return returnValue; +} + +void cmldrpSetDebug(int flag) +{ + gCMLDRPBlock.debugEnabled = flag; +} + +void cmldrpSetManagerRotationEnabled(int flag) +{ + gCMLDRP_ManagerRotationEnabled = flag; +} + +#ifdef _DRP_MTHREAD +/** + * startCMLDRPThread + * starts up the CMLDRP client thread that will periodically refresh + * DRP server info for the entire DRP Client in the current process. + * return: 0 == success; !0 == failure + */ +static int startCMLDRPThread(CMLDRP_Block * pBlock) +{ + int returnValue = 0; + + gCMLDRPThread = + thread_startNewThread(kThread_defaultStackSize, + cmldrpThreadFunction, + (kThread_argType) pBlock); + if (gCMLDRPThread == kThread_InvalidThread) { + gCMLDRPBlock.logFunction(gCMLDRPBlock.logShellData, kLog_Error, + kLogMessage_CannotStartCMLDRPThread, NULL, + NULL); + returnValue = -1; + } + + return returnValue; +} + + +/** + * cmldrpThreadFunction + * the routine run by the CMDLRP client thread. + * iArg: pointer to a cmldrpBlock object (already initialized). + */ +static kThread_returnType cmldrpThreadFunction(kThread_argType iArg) +{ + CMLDRP_Block *cmldrpBlock = (CMLDRP_Block *) iArg; + int result; + short sleepy = 0; + + +#ifdef _DRP_MTHREAD + gCMLDRP_ThreadIsRunning = 1; +#endif + while (!gCMLDRP_Shutdown) { + result = cmldrpUpdate(cmldrpBlock); + if (result == 0) + gCMLDRP_UpdateNow = 0; /* clear force-update flag */ + else { + /* update() failed; set next polltime to minimum polltime + and update next manager to contact */ + cmldrpBlock->nextUpdateTime = + time(NULL) + kCMLDRP_MinimumPollInterval; + selectNextCMLDRPServer(cmldrpBlock); + } + + sleepy = 1; + while (sleepy) { + thread_sleep(kCMLDRP_Sleeptime); + if ((time(NULL) >= cmldrpBlock->nextUpdateTime) + || gCMLDRP_UpdateNow || gCMLDRP_Shutdown) + sleepy = 0; /* i.e. terminate while (sleepy) loop, + return to top of while (! shutdown) loop */ + } + } + +#ifdef _DRP_MTHREAD + gCMLDRP_ThreadIsRunning = 0; +#endif + + thread_return(0); +} +#else /* i.e. ndef _DRP_MTHREAD */ + +/** + * cmldrpUpdate_MP (_MP: multi-process) + * If appropriate, forces CMLDRP subsystem to refresh DRP server information + * from the CMLDRP server. for use in multi-process CMs. + * return: 0 == success; !0 == failure + */ +int cmldrpUpdate_MP(CMLDRP_Block * pBlock) +{ + int returnValue = 0; + int i = 0; + + /* Loop until we find an CMLDRP Server that is available. */ + while (((time(NULL) >= pBlock->nextUpdateTime) || gCMLDRP_UpdateNow) + && (i < pBlock->numCMLDRPServers)) { + returnValue = cmldrpUpdate(pBlock); + if (returnValue == 0) { + /* Success. */ + gCMLDRP_UpdateNow = 0; + return 0; + } else { + /* Current CMLDRP Server is available. Select next one. */ + pBlock->nextUpdateTime = + time(NULL) + kCMLDRP_MinimumPollInterval; + selectNextCMLDRPServer(pBlock); + i++; + } + } + + return returnValue; +} +#endif + + +/** + * internalizeCMLDRPServerInfo + * Stores contact information for CMLDRP servers in a CMLDRP_Block object + * (for use during the initialization phase). + * return: 0 == success; !0 == failure + */ +static int +internalizeCMLDRPServerInfo(CMLDRP_Block * pBlock, int iNumServers, + const CMLDRP_ServerInfo * iServers) +{ + int returnValue = 0; + int s; + + for (s = 0, pBlock->numCMLDRPServers = 0; s < iNumServers; s++) { + pBlock->cmldrpServers[pBlock->numCMLDRPServers].sin_family = + AF_INET; + pBlock->cmldrpServers[pBlock->numCMLDRPServers].sin_port = + htons(iServers[s].port); + pBlock->cmldrpServers[pBlock->numCMLDRPServers].sin_addr.s_addr = + hostToInetAddr(iServers[s].host); + + if (pBlock->cmldrpServers[pBlock->numCMLDRPServers].sin_addr. + s_addr != INADDR_NONE) + pBlock->numCMLDRPServers++; + else { + pBlock->logFunction(pBlock->logShellData, kLog_Error, + kLogMessage_CantResolveCMLDRPHost, + iServers[s].host, NULL); + } + } + + pBlock->nextServerToContact = + &(pBlock->cmldrpServers[pBlock->nextServerToContactIdx]); + + if (pBlock->numCMLDRPServers < 1) { + pBlock->logFunction(pBlock->logShellData, kLog_Error, + kLogMessage_NoGoodCMLDRPServers, NULL, NULL); + returnValue = -1; + } + + return returnValue; +} + + +/** + * generateCMLDRPIdentifier + * Construct an identification string that will uniquely identify this + * CMLDRP client entity + * CMLDRP identifier has the form: + * ::: + * where and reflect the IP and port describing the host HTTP + * server; is the id of the execution context + * of the CMLDRP client entity; serves to uniquely identify + * CMLDRP entities across time. + */ +static int +generateCMLDRPIdentifier(CMLDRP_Block * pBlock, unsigned short iHTTPPort) +{ + int returnValue = 0; + char hostname[MAXHOSTNAMELEN]; + struct hostent *hostinfo; + struct in_addr inAddr; + + if (gethostname(hostname, MAXHOSTNAMELEN)) { + returnValue = -1; + goto GENERATE_CMLDRP_ID_EXIT; + } + + hostinfo = gethostbyname(hostname); + if (hostinfo) { + memcpy(&inAddr, (void *) hostinfo->h_addr, hostinfo->h_length); + pBlock->identifierLength = (char) +#if defined(SOLARIS2) && !defined(_LP64) && !defined(_I32LPx) + sprintf(pBlock->identifier, "%s:%u:%ld:%ld", +#else + sprintf(pBlock->identifier, "%s:%u:%d:%ld", +#endif + inet_ntoa(inAddr), iHTTPPort, getpid(), time(NULL)); + } else { + returnValue = -1; + goto GENERATE_CMLDRP_ID_EXIT; + } + + GENERATE_CMLDRP_ID_EXIT: + + return returnValue; +} + +/** + * outputLength + * The number of bytes waiting to be sent in the io buffer + */ +static int outputLength(CMLDRP_Block * pBlock) +{ + return (sizeof(pBlock->cmldrpVersion) + + sizeof(pBlock->sequenceNumber) + 1 + pBlock->identifierLength); +} + + +/** + * sendCmldrpRequest_Udp + * Send a CMLDRP request via UDP + * return: 0 == success; !0 == failure + */ +int sendCmldrpRequestUdp(CMLDRP_Block * pBlock) +{ + + /* send request buffer */ + if (sendto(pBlock->sock, pBlock->ioBuffer, + outputLength(pBlock), + 0, + (struct sockaddr *) pBlock->nextServerToContact, + sizeof(*(pBlock->nextServerToContact))) + == SOCKET_ERROR) { + return -1; + } + return 0; +} + +#ifdef _DRP_MTHREAD +/** + * sendCmldrpRequest_Tcp + * Send a CMLDRP request via TCP + * return: 0 == success; !0 == failure + */ +int sendCmldrpRequestTcp(CMLDRP_Block * pBlock) +{ + IOStatus status; + int returnValue = 0; + + status = writeToOutputStream(pBlock->outputStream, + pBlock->ioBuffer, outputLength(pBlock)); + if (status == IOStatusOk) + status = flushOutputStream(pBlock->outputStream); + + if (IOStatusOk != status) { + char buf[180]; + const char *ioStatusString; + struct in_addr *inAddr; + struct sockaddr_in *addr; + + addr = pBlock->nextServerToContact; + inAddr = (struct in_addr *) &addr->sin_addr.s_addr; + + ioStatusString = getIOStatusString(status); + + sprintf(buf, + "CMLDRP(TCP) Error writing to Load Manager=%s:%d, io status=%s", + inet_ntoa(*inAddr), ntohs(addr->sin_port), ioStatusString); + + gCMLDRPBlock.logFunction(gCMLDRPBlock.logShellData, kLog_Error, + kLogMessage_OneString, buf, NULL); + + returnValue = -1; + } + return returnValue; +} +#endif + +/** + * checkResponseType + * Check that the response type for this was set + * return: 0 == success; !0 == failure + */ +static int checkResponseType(CMLDRP_Block * pBlock) +{ + unsigned short responseType; + struct sockaddr_in *contactServer = pBlock->nextServerToContact; + + /* make sure the response has the response indicator set */ + memcpy(&responseType, &pBlock->ioBuffer[kCMLDRP_ResponseTypeOffset], + sizeof(responseType)); + if (ntohs(responseType) != kCMLDRP_ResponseType) { + char portNumber[8]; + struct in_addr *inAddr; + + sprintf(portNumber, "%d", ntohs(contactServer->sin_port)); + inAddr = (struct in_addr *) &contactServer->sin_addr.s_addr; + gCMLDRPBlock.logFunction(gCMLDRPBlock.logShellData, kLog_Warn, + kLogMessage_BadCMLDRPResponseType, + inet_ntoa(*inAddr), portNumber); + return -1; + } + return 0; +} + + +/** + * receiveCmldrpResponseUdp + * Receive a CMLDRP response via UDP + * return: 0 == success; !0 == failure + */ +int receiveCmldrpResponseUdp(CMLDRP_Block * pBlock) +{ + int returnValue = 0; + fd_set readSet; + int nfds; + unsigned short requestSequence = pBlock->sequenceNumber; + unsigned short responseSequence = !requestSequence; + /*unsigned short requestType = kCMLDRP_RequestType; */ + struct sockaddr_in *contactServer = pBlock->nextServerToContact; + + do { + /* receive into response buffer */ + FD_ZERO(&readSet); + FD_SET(pBlock->sock, &readSet); + nfds = (int) pBlock->sock + 1; + if (select(nfds, &readSet, NULL, NULL, &pBlock->timeout) > 0) { + /* ready to read */ + size_t serverAddrSize = sizeof(*(pBlock->nextServerToContact)); + int bytesReceived = + recvfrom(pBlock->sock, pBlock->ioBuffer, + kCMLDRP_IOBufferSize, 0, + (struct sockaddr *) pBlock->nextServerToContact, + &serverAddrSize); + if ((bytesReceived == SOCKET_ERROR) || (bytesReceived <= 0)) { + returnValue = -1; + goto CMLDRP_RESPONSE_EXIT; + } + + returnValue = checkResponseType(pBlock); + + if (returnValue) + goto CMLDRP_RESPONSE_EXIT; + + /* check sequence number - if it's a match, use the response data, + otherwise discard and see if another packet arrived from the + CMLDRP server */ + memcpy(&responseSequence, + &pBlock->ioBuffer[kCMLDRP_ResponseSequenceOffset], + sizeof(responseSequence)); + responseSequence = ntohs(responseSequence); + if (responseSequence == requestSequence) { + /* dispatchRepsonseMetaData: will internalize CMLDRP flags, next + CMLDRP server to contact, etc; returns !0 if OK to dispatch + remaining response data (i.e. DRP server contact info) */ + if (dispatchResponseMetaData(pBlock, bytesReceived)) { + returnValue = + dispatchResponseData(pBlock, bytesReceived); + if (returnValue == 0) + /* increment info version so service threads can see there's new + load data available */ + gCMLDRP_InfoVersion++; + } + } + } else { + /* not ready to read */ + char portNumber[8]; + struct in_addr *inAddr; + + if (time(NULL) > + pBlock->lastTimeSilenceReported + + kSilentCMLDRPLogInterval) { + /* we've been trying to contact this CMLDRP server for more than + k..Interval seconds (or this is the first failure) */ + sprintf(portNumber, "%d", ntohs(contactServer->sin_port)); + inAddr = + (struct in_addr *) &contactServer->sin_addr.s_addr; + if (pBlock->lastTimeSilenceReported > 0) + gCMLDRPBlock.logFunction(gCMLDRPBlock.logShellData, + kLog_Warn, + kLogMessage_NoCMLDRPResponsePeriod, + inet_ntoa(*inAddr), + portNumber); + else + gCMLDRPBlock.logFunction(gCMLDRPBlock.logShellData, + kLog_Warn, + kLogMessage_NoCMLDRPResponseFirst, + inet_ntoa(*inAddr), + portNumber); + pBlock->lastTimeSilenceReported = time(NULL); + } + returnValue = -1; + goto CMLDRP_RESPONSE_EXIT; + } + } while (responseSequence != requestSequence); + + CMLDRP_RESPONSE_EXIT: + + return returnValue; +} + +#ifdef _DRP_MTHREAD +/** + * receiveCmldrpResponseTcp + * Send a CMLDRP response via TCP + * return: 0 == success; !0 == failure + */ +int receiveCmldrpResponseTcp(CMLDRP_Block * pBlock) +{ + int returnValue = 0; + IOStatus status; + int read; + int bytesReceived = 0; + + status = readFromInputStream(pBlock->inputStream, + pBlock->ioBuffer, + kCMLDRP_BaseResponseSize, &read); + + if (IOStatusOk == status) { + unsigned short numRecords; + int recordsLength; + + bytesReceived = kCMLDRP_BaseResponseSize; + + /* Calculate the number of Dynamo records expected */ + memcpy(&numRecords, + &pBlock->ioBuffer[kCMLDRP_ResponseNumRecsOffset], + sizeof(numRecords)); + numRecords = ntohs(numRecords); + recordsLength = numRecords * kCMLDRP_LoadRecordSize; + + /* Read the Dynamo records */ + status = readFromInputStream(pBlock->inputStream, + &pBlock-> + ioBuffer + [kCMLDRP_ResponseRecordOffset], + recordsLength, &read); + if (IOStatusOk == status) + bytesReceived += recordsLength; + } + + if (IOStatusOk != status) { + char buf[180]; + const char *ioStatusString = getIOStatusString(status); + struct in_addr *inAddr; + struct sockaddr_in *addr; + + addr = pBlock->nextServerToContact; + inAddr = (struct in_addr *) &addr->sin_addr.s_addr; + + sprintf(buf, + "CMLDRP(TCP) Error reading from Load Manager=%s:%d, io status=%s", + inet_ntoa(*inAddr), ntohs(addr->sin_port), ioStatusString); + + gCMLDRPBlock.logFunction(gCMLDRPBlock.logShellData, kLog_Error, + kLogMessage_OneString, buf, NULL); + + returnValue = -1; + } + + if (0 == returnValue) + returnValue = checkResponseType(pBlock); + + if (0 == returnValue) { + +#ifdef DEBUG + { + char buf[20]; + int i; + + for (i = 0; i < bytesReceived; i++) { + sprintf(buf, "byte[%d] == %u", i, pBlock->ioBuffer[i]); + gCMLDRPBlock.logFunction(gCMLDRPBlock.logShellData, + kLog_Warn, kLogMessage_OneString, + buf, NULL); + } + } +#endif + + if (dispatchResponseMetaData(pBlock, bytesReceived)) { + returnValue = dispatchResponseData(pBlock, bytesReceived); + if (returnValue == 0) + /* increment info version so service threads can see there's new + load data available */ + gCMLDRP_InfoVersion++; + } + } + + return returnValue;; +} +#endif + +/** + * cmldrpUpdate + * Attempt to update locally held DRP server load information by + * contacting a CMLDRP server + * return: 0 == success; !0 == failure + */ +int cmldrpUpdate(CMLDRP_Block * pBlock) +{ + int returnValue = 0; + unsigned short requestSequence = pBlock->sequenceNumber; + unsigned short requestType = kCMLDRP_RequestType; + +#ifdef _DRP_MTHREAD + if (gCMLDRP_UseTcp) { + if (connectToNextCMLDRPServer(pBlock)) { + returnValue = -1; + goto CMLDRP_UPDATE_EXIT; + } + } +#endif + + /* set up request buffer */ + *((unsigned short *) &pBlock->ioBuffer[kCMLDRP_RequestVersionOffset]) = + htons(pBlock->cmldrpVersion); + *((unsigned short *) &pBlock->ioBuffer[kCMLDRP_RequestTypeOffset]) = + htons(requestType); + *((unsigned short *) &pBlock-> + ioBuffer[kCMLDRP_RequestSequenceOffset]) = htons(requestSequence); + *((unsigned short *) &pBlock-> + ioBuffer[kCMLDRP_RequestIDLengthOffset]) = +htons(pBlock->identifierLength); + strncpy(&(pBlock->ioBuffer[kCMLDRP_RequestIDOffset]), + pBlock->identifier, pBlock->identifierLength); + +#ifdef _DRP_MTHREAD + if ((gCMLDRP_UseTcp == 0) ? + sendCmldrpRequestUdp(pBlock) : sendCmldrpRequestTcp(pBlock)) +#else + if (sendCmldrpRequestUdp(pBlock)) +#endif + { + returnValue = -1; + goto CMLDRP_UPDATE_EXIT; + } +#ifdef _DRP_MTHREAD + if (0 == gCMLDRP_UseTcp) + returnValue = receiveCmldrpResponseUdp(pBlock); + else + returnValue = receiveCmldrpResponseTcp(pBlock); +#else + returnValue = receiveCmldrpResponseUdp(pBlock); +#endif + + CMLDRP_UPDATE_EXIT: + +#ifdef _DRP_MTHREAD + if (gCMLDRP_UseTcp) + closeCMLDRPConnection(pBlock); +#endif + + pBlock->sequenceNumber++; + + return returnValue; +} + + +/** + * dispatchResponseMetaData + * parse general information from the CMLDRP server's response (i.e. only + * information not pertaining to DRP servers). + * return: 0 == do NOT dispatch remaining response data; + * >0 == do dispatch remaining response data; + * <0 == error + */ +static int +dispatchResponseMetaData(CMLDRP_Block * pBlock, int iBytesReceived) +{ + int returnValue = 0; + unsigned short cmldrpFlags; + unsigned long nextManagerHost; + unsigned short nextManagerPort; + unsigned short numRecords; + + if (iBytesReceived < kCMLDRP_BaseResponseSize) { + returnValue = -1; + +#ifdef DEBUG + gCMLDRPBlock.logFunction(gCMLDRPBlock.logShellData, kLog_Info, + kLogMessage_OneString, + "dispatchResponseMetaData received to view bytes", + NULL); +#endif + goto DISPATCH_META_DATA_EXIT; + } + + /* extract cmldrp flags from response */ + memcpy(&cmldrpFlags, &pBlock->ioBuffer[kCMLDRP_ResponseFlagsOffset], + sizeof(cmldrpFlags)); + cmldrpFlags = ntohs(cmldrpFlags); + + /* extract next-manager-to-contact info from response */ + memcpy(&nextManagerHost, + &pBlock->ioBuffer[kCMLDRP_ResponseNextHostOffset], + sizeof(nextManagerHost)); + memcpy(&nextManagerPort, + &pBlock->ioBuffer[kCMLDRP_ResponseNextPortOffset], + sizeof(nextManagerPort)); + nextManagerPort = ntohs(nextManagerPort); + + /* extract number of DRP records and check against bytes received */ + memcpy(&numRecords, &pBlock->ioBuffer[kCMLDRP_ResponseNumRecsOffset], + sizeof(numRecords)); + numRecords = ntohs(numRecords); + + if ((numRecords * kCMLDRP_LoadRecordSize + kCMLDRP_BaseResponseSize != + iBytesReceived) || (numRecords > kMaxDRPRecords)) { + returnValue = -1; + +#ifdef DEBUG + gCMLDRPBlock.logFunction(gCMLDRPBlock.logShellData, kLog_Info, + kLogMessage_OneString, + "dispatchResponseMetaData bad load record size", + NULL); +#endif + goto DISPATCH_META_DATA_EXIT; + } + + /* set some local fields w/ response data */ + pBlock->cmldrpFlags = cmldrpFlags; + + /* + * This is an option put in for kodak, but it might be useful generally. + * If this option is set to false, we ignore the load manager that the + * current LM wants us to poll and just keep on using our own heuristics. + * This feature is there so that if we have more than one load manager, we + * can revert back to using the original primary after it comes back up. + * + * Kodak, though, has a proxy server so the IP address that the LM thinks + * it is, is not the right one. + */ + if (gCMLDRP_ManagerRotationEnabled) { + /* set next CMLDRP server to contact */ + pBlock->tempCMLDRPServer.sin_family = AF_INET; + pBlock->tempCMLDRPServer.sin_port = ntohs(nextManagerPort); + pBlock->tempCMLDRPServer.sin_addr.s_addr = nextManagerHost; + if (memcmp(pBlock->nextServerToContact, &pBlock->tempCMLDRPServer, + sizeof(pBlock->tempCMLDRPServer))) { + /* only reset lastTimeSilenceReported if nextServerToContact changes */ + pBlock->lastTimeSilenceReported = 0; + } + pBlock->nextServerToContact = &pBlock->tempCMLDRPServer; + } + + /* if CMLDRP server indicates it is finished w/ initialization, return + >0, to force internalization of DRP server response data */ + if (cmldrpFlags & kCMLDRPFlags_Initialized) + returnValue = 1; + else { + /* CMLDRP server still initializing; set next polltime to minimum + polltime */ + pBlock->nextUpdateTime = time(NULL) + kCMLDRP_MinimumPollInterval; + +#ifdef DEBUG + gCMLDRPBlock.logFunction(gCMLDRPBlock.logShellData, kLog_Info, + kLogMessage_OneString, + "setting nextUpdateTime - not initialized", + NULL); +#endif + } + + DISPATCH_META_DATA_EXIT: + + return returnValue; +} + + + +/** + * dispatchResponseData + * Copy data from a CMLDRP server's response into local structures + * return: 0 == success; !0 == failure + */ +static int dispatchResponseData(CMLDRP_Block * pBlock, int iBytesReceived) +{ + int returnValue = 0; + unsigned short cmldrpVersion; + unsigned short pollInterval; + unsigned short numRecords; + int l; + int recordOffset; + int r; + + if (iBytesReceived < kCMLDRP_BaseResponseSize) { + returnValue = -1; + goto DISPATCH_RESP_DATA_EXIT; + } + + memcpy(&cmldrpVersion, + &pBlock->ioBuffer[kCMLDRP_ResponseVersionOffset], + sizeof(cmldrpVersion)); + cmldrpVersion = ntohs(cmldrpVersion); + + memcpy(&pollInterval, + &pBlock->ioBuffer[kCMLDRP_ResponseIntervalOffset], + sizeof(pollInterval)); + pollInterval = ntohs(pollInterval); + + memcpy(&numRecords, &pBlock->ioBuffer[kCMLDRP_ResponseNumRecsOffset], + sizeof(numRecords)); + numRecords = ntohs(numRecords); + + pBlock->pollInterval = pollInterval; + pBlock->nextUpdateTime = time(NULL) + pollInterval; + +#ifdef _DRP_MTHREAD + { + int result; + do { + result = + getWriteLock(&gLoadDataLock, kRWL_DefaultWriteTimeout); + } while (result != 0 && !gCMLDRP_Shutdown); + if (gCMLDRP_Shutdown) + return 0; + } +#endif + + /* at this point we've decided the data packet is legit */ + /* mark all known servers inactive; after we've absorbed all the + per-drp-server data (below), all servers marked as active will have + data from the CMLDRP server, and any servers not mentioned by + CMLDRP server will be marked inactive */ + for (r = 0; r < gNumDrpServers; r++) { + gDrpServers[r].flags &= ~kDrpServerFlags_Active; + } + + for (l = 0, recordOffset = kCMLDRP_ResponseRecordOffset; + l < numRecords; l++, recordOffset += kCMLDRP_LoadRecordSize) { + drpServerRecord record; + drpServerRecord *recordPtr; + drpServerRecord **match; + + memset(&record, 0, sizeof(record)); + + memcpy(&record.inetaddr, + &pBlock->ioBuffer[recordOffset + kCMLDRP_RecordHostOffset], + sizeof(record.inetaddr)); + memcpy(&record.port, + &pBlock->ioBuffer[recordOffset + kCMLDRP_RecordPortOffset], + sizeof(record.port)); + record.port = ntohs(record.port); + memcpy(&record.probability, + &pBlock->ioBuffer[recordOffset + kCMLDRP_RecordProbOffset], + sizeof(record.probability)); + record.probability = ntohs(record.probability); + memcpy(&record.flags, + &pBlock->ioBuffer[recordOffset + kCMLDRP_RecordFlagsOffset], + sizeof(record.flags)); + record.flags = ntohs(record.flags); + /* + * Mark this server as active. We don't have + */ + record.flags |= kDrpServerFlags_Active; + + /* look up record in list of record ptrs */ + recordPtr = &record; + match = bsearch(&recordPtr, gDrpServerPtrs, gNumDrpServers, + sizeof(recordPtr), compareDRPServerRecPtrs_ipPort); + if (match) { + (*match)->probability = record.probability; + (*match)->flags = record.flags; + } else { + drpServerRecord *newServer = &(gDrpServers[gNumDrpServers]); + newServer->probability = record.probability; + newServer->flags = record.flags; + newServer->inetaddr = record.inetaddr; + newServer->port = record.port; + newServer->sock = kInvalidSocket; + + gDrpServerPtrs[gNumDrpServers] = newServer; + + gNumDrpServers++; + + /* must now sort new record into the list of pointers */ + qsort(gDrpServerPtrs, gNumDrpServers, sizeof(recordPtr), + compareDRPServerRecPtrs_ipPort); + +#ifdef _CPOOL + /* initialize the connection pool for this server */ + if (gCP_Enabled) { + newServer->pool = malloc(sizeof(connectionPool)); + initializeCP(newServer->pool); + } +#endif + } + } + +#ifdef _DRP_MTHREAD + releaseWriteLock(&gLoadDataLock); +#endif + + if (gCMLDRPBlock.debugEnabled) { + char buf[1024]; + int i; + + if (pBlock->nextServerToContact != NULL) { + struct in_addr *inAddr = + (struct in_addr *) &pBlock->nextServerToContact->sin_addr. + s_addr; + sprintf(buf, + "updating %d servers - next lm=%s:%d%s - num request threads=%d", + gNumDrpServers, inet_ntoa(*inAddr), + ntohs(pBlock->nextServerToContact->sin_port), + (gCMLDRP_ManagerRotationEnabled == + 0) ? " (load manager rotation disabled)" : "", + gDebugInfo.numRequestThreads); + } else + sprintf(buf, + "updating %d servers - next lm=null - num request threads=%d", + gNumDrpServers, gDebugInfo.numRequestThreads); + gCMLDRPBlock.logFunction(gCMLDRPBlock.logShellData, kLog_Info, + kLogMessage_OneString, buf, NULL); + + sprintf(buf, + "num active requests=%d - num waiting on lock=%d - num waiting on pool=%d - num waiting to connect=%d - num sending request=%d, num waiting for response=%d", + gDebugInfo.numActiveRequests, + gDebugInfo.numWaitingOnReadLock, + gDebugInfo.numWaitingOnPool, + gDebugInfo.numWaitingToConnect, + gDebugInfo.numSendingRequest, + gDebugInfo.numWaitingForResponse); + gCMLDRPBlock.logFunction(gCMLDRPBlock.logShellData, kLog_Info, + kLogMessage_OneString, buf, NULL); + + for (i = 0; i < gNumDrpServers; i++) { + sprintf(buf, "server %ld.%ld.%ld.%ld port=%d prob=%d flags=%d", + gDrpServerPtrs[i]->inetaddr & 0xff, + (gDrpServerPtrs[i]->inetaddr >> 8) & 0xff, + (gDrpServerPtrs[i]->inetaddr >> 16) & 0xff, + (gDrpServerPtrs[i]->inetaddr >> 24) & 0xff, + gDrpServerPtrs[i]->port, + gDrpServerPtrs[i]->probability, + gDrpServerPtrs[i]->flags); + gCMLDRPBlock.logFunction(gCMLDRPBlock.logShellData, kLog_Info, + kLogMessage_OneString, buf, NULL); + } + } + + DISPATCH_RESP_DATA_EXIT: + + return returnValue; +} + + +/** + * compareDRPServerRecords_ipPort + * (for use with qsort, bsearch) + * compares two drpServerRecord objects first by IP address, then by port. + * return: <0 : iRec1 < iRec2 + * 0 : iRec1 == iRec2 + * >0 : iRec1 > iRec2 + */ +/* NOTE: Currently not used so not defined. - Frank Kim, 12/28/99 (lmd 3/24/00)*/ +#if 0 +int compareDRPServerRecords_ipPort(const void *iRec1, const void *iRec2) +{ + drpServerRecord *rec1 = (drpServerRecord *) iRec1; + drpServerRecord *rec2 = (drpServerRecord *) iRec2; + + if (rec1->inetaddr < rec2->inetaddr) + return -1; + if (rec1->inetaddr > rec2->inetaddr) + return 1; + + if (rec1->port < rec2->port) + return -1; + if (rec1->port > rec2->port) + return 1; + + return 0; +} +#endif + +/** + * compareDRPServerRecPtrs_ipPort + * (for use with qsort, bsearch) + * compares two _pointers to_ drpServerRecord objects first by IP address, + * then by port. + * return: <0 : *iRec1 < *iRec2 + * 0 : *iRec1 == *iRec2 + * >0 : *iRec1 > *iRec2 + */ +int compareDRPServerRecPtrs_ipPort(const void *iPtr1, const void *iPtr2) +{ + drpServerRecord **ptr1 = (drpServerRecord **) iPtr1; + drpServerRecord **ptr2 = (drpServerRecord **) iPtr2; + + if ((*ptr1)->inetaddr < (*ptr2)->inetaddr) + return -1; + if ((*ptr1)->inetaddr > (*ptr2)->inetaddr) + return 1; + + if ((*ptr1)->port < (*ptr2)->port) + return -1; + if ((*ptr1)->port > (*ptr2)->port) + return 1; + + return 0; +} + + +/** + * openUDPSocket + * Establish a UDP datagram socket for use in obtaining load information + * from CMLDRP server(s). + * pBlock: CMLDRP information block + * iBindAddress: if present, bind the datagram socket to the address + * indicated; if NULL, bind to any appropriate network interface + * return: 0 == success; !0 == failure + */ +static int openUDPSocket(CMLDRP_Block * pBlock, const char *iBindAddress) +{ + int returnValue = 0; + struct sockaddr_in clientAddr; /* host of current process */ + + if ((pBlock->sock = socket(AF_INET, SOCK_DGRAM, 0)) == kInvalidSocket) { + returnValue = -1; + goto OPEN_UDP_EXIT; + } + + memset(&clientAddr, 0, sizeof(clientAddr)); + clientAddr.sin_family = AF_INET; + clientAddr.sin_port = htons(0); + if (iBindAddress) { + /* Parse out the potential "name:port" value */ + char tmpAddress[256]; + char *port; + strcpy(tmpAddress, iBindAddress); + port = strchr(tmpAddress, ':'); + if (port != NULL) { + *port = '\0'; + port++; + clientAddr.sin_port = (short) atoi(port); + clientAddr.sin_port = htons(clientAddr.sin_port); + } + /* bind to specific address (for multi-homed hosts) */ + clientAddr.sin_addr.s_addr = hostToInetAddr(tmpAddress); + + { + char buf[256]; + sprintf(buf, "Binding to specified local address: %s:%d", + tmpAddress, (int) ntohs(clientAddr.sin_port)); + pBlock->logFunction(pBlock->logShellData, kLog_Info, + kLogMessage_OneString, buf, NULL); + } + } else { + /* bind to any local address (for single-homed hosts, or if user d/n + care which network interface is used) */ + clientAddr.sin_addr.s_addr = htonl(INADDR_ANY); + } + + if (bind(pBlock->sock, (struct sockaddr *) &clientAddr, + sizeof(clientAddr))) { + returnValue = -1; + goto OPEN_UDP_EXIT; + } + + OPEN_UDP_EXIT: + + return returnValue; +} + +#ifdef _DRP_MTHREAD +/** + * connectToNextCMLDRPServer + * Connect to a CMLDRP server using TCP + * pBlock: CMLDRP information block + * return: 0 == success; !0 == failure + */ +int connectToNextCMLDRPServer(CMLDRP_Block * pBlock) +{ + struct sockaddr_in *addr = pBlock->nextServerToContact; + IOStatus status; + int returnValue = 0; + +#ifdef WIN32 + status = createSocketIOStreamsFromAddressWithTimeout((*addr), + gCMLDRP_TcpTimeout, + &(pBlock-> + inputStream), + &(pBlock-> + outputStream)); +#else + status = createSocketIOStreamsFromAddressWithBlocking((*addr), + &(pBlock-> + inputStream), + &(pBlock-> + outputStream)); +#endif + + if (IOStatusOk != status || + pBlock->inputStream == NULL || pBlock->outputStream == NULL) { + + if (time(NULL) > + pBlock->lastTimeSilenceReported + kSilentCMLDRPLogInterval) { + char buf[180]; + const char *ioStatusString = getIOStatusString(status); + struct in_addr *inAddr; + + inAddr = (struct in_addr *) &addr->sin_addr.s_addr; + + sprintf(buf, + "CMLDRP(TCP) Failure to connect via TCP to Load Manager=%s:%d, io status=%s", + inet_ntoa(*inAddr), + ntohs(addr->sin_port), ioStatusString); + + gCMLDRPBlock.logFunction(gCMLDRPBlock.logShellData, kLog_Error, + kLogMessage_OneString, buf, NULL); + pBlock->lastTimeSilenceReported = time(NULL); + } + returnValue = -1; + } + + return returnValue; +} + +/** + * closeCMLDRPConnection + * Close a TCP connection to a CMLDRP server + * pBlock: CMLDRP information block + */ +void closeCMLDRPConnection(CMLDRP_Block * pBlock) +{ + + if (pBlock->inputStream) + destroyInputStream(pBlock->inputStream); + + if (pBlock->outputStream) + destroyOutputStream(pBlock->outputStream); + return; +} +#endif + +/** + * selectNextCMLDRPServer + * Determines which known CMLDRP server should be next to contact; to be + * invoked in case of lack of response from the current CMLDRP server. + * return: 0 == success; !0 == failure + */ +int selectNextCMLDRPServer(CMLDRP_Block * pBlock) +{ + int returnValue = 0; + +#ifdef DEBUG + char dbgBuf[64]; + sprintf(dbgBuf, "num of CMLDRPServers: %d", pBlock->numCMLDRPServers); + pBlock->logFunction(pBlock->logShellData, kLog_Info, + kLogMessage_OneString, dbgBuf, NULL); + sprintf(dbgBuf, "next Server to Contact index: %d", + pBlock->nextServerToContactIdx); + pBlock->logFunction(pBlock->logShellData, kLog_Info, + kLogMessage_OneString, dbgBuf, NULL); +#endif + + pBlock->nextServerToContactIdx = + (pBlock->nextServerToContactIdx + 1) % pBlock->numCMLDRPServers; + if (pBlock->numCMLDRPServers > 1) + pBlock->lastTimeSilenceReported = 0; + + pBlock->nextServerToContact = + &(pBlock->cmldrpServers[pBlock->nextServerToContactIdx]); + + return returnValue; +} + + +/** + * getDrpServerRecord + * Given a list of DRP server records and an address-port combination, + * finds the server record (if any) in the list with that addr-port. + * return: NULL if no matching record found + */ +drpServerRecord **getDrpServerRecord(const drpServerRecord ** iServerPtrs, + int iNumServers, unsigned long iAddr, + unsigned short iPort) +{ + drpServerRecord record; + drpServerRecord *recordPtr = &record; + + memset(&record, 0, sizeof(record)); + record.inetaddr = iAddr; + record.port = iPort; + + return bsearch(&recordPtr, iServerPtrs, iNumServers, sizeof(recordPtr), + compareDRPServerRecPtrs_ipPort); +} + + +/** + * parseDynamoManagers + * Given list of Dynamo Managers (i.e. CMDLRP servers), builds and returns + * a list of CMLDRP_ServerInfo objects containing contact information for + * the CMLDRP servers specified. + * iDynamoManagers: expected format is: + * {host}:{port},{host}:{port},... + * oNumServers: on exit, contains the number of server records in the + * list returned. + * + * NB: modifies iDynamoManagers in place + * NB: allocates data + */ +CMLDRP_ServerInfo *parseDynamoManagers(char *iDynamoManagers, + int *oNumServers) +{ + int numCommas; + char *tempPtr; + char *nextPtr; + char *portPtr; + CMLDRP_ServerInfo *serverData = NULL; + + /* first: get max number of servers in list by counting commas */ + for (tempPtr = iDynamoManagers, numCommas = 0; tempPtr;) { + tempPtr = strchr(tempPtr, kChar_Comma); + if (tempPtr) { + tempPtr++; + numCommas++; + } + } + + serverData = (CMLDRP_ServerInfo *) + malloc(sizeof(CMLDRP_ServerInfo) * (numCommas + 1)); + + /* second: populate the server records */ + + tempPtr = iDynamoManagers; + *oNumServers = 0; + + while (tempPtr && (*tempPtr != kChar_Null)) { + nextPtr = strchr(tempPtr, kChar_Comma); + if (nextPtr) + *nextPtr++ = kChar_Null; /* terminate this host[:port] entry */ + + portPtr = strchr(tempPtr, kChar_Colon); + if (portPtr) + *portPtr++ = kChar_Null; /* terminate this host entry */ + + serverData[*oNumServers].host = (char *) + malloc(sizeof(char) * (strlen(tempPtr) + 1)); + strcpy(serverData[*oNumServers].host, tempPtr); + serverData[*oNumServers].port = + (portPtr ? atoi(portPtr) : kCMLDRP_DefaultCMLDRPPort); + + (*oNumServers)++; + + tempPtr = nextPtr; + } + + return serverData; +} + + +/** + * cmldrpShutdown() + * Cause the CMLDRP thread, if active, to stop + * + * On ISAPI, the inetinfo process would die during shutdown sometimes + * without the loop and the IsRunning flag. This seems to fix this problem. + */ +void cmldrpShutdown(void) +{ + gCMLDRP_Shutdown = 1; + +#ifdef _DRP_MTHREAD + do { + thread_sleep(kCMLDRP_Sleeptime * 2); + } while (gCMLDRP_ThreadIsRunning); +#endif +} + +#ifdef _DRP_MTHREAD +void setEnforceMaxHandlers(int flag) +{ + gEnforceMaxHandlers = flag; +} + +void setMaxHandlers(int count) +{ + gMaxHandlers = count; +} + +void setBackoffInterval(time_t interval) +{ + gBackoffInterval = interval; +} + +/** + * Returns 0 if this thread can be a handler, otherwize + * it can return non-zero + */ +int acquireHandler() +{ + int returnValue = -1; + + if (!gEnforceMaxHandlers) { + return 0; + } else { + if (0 == getWriteLock(&gHandlerCountLock, kDefaultHandlersTimeout)) { + + if (gExceededLimit) { + time_t now = time(NULL); + + /* Log an error at intervals */ + if (now > + gLastTimeThreadLimitReported + + kSilentCMLDRPLogInterval) { + char threadLimitReached[80]; + + sprintf(threadLimitReached, + "Dymamo handler limit reached = %d, backoff interval = %d seconds", + gMaxHandlers, gBackoffInterval); + gCMLDRPBlock.logFunction(gCMLDRPBlock.logShellData, + kLog_Error, + kLogMessage_OneString, + threadLimitReached, NULL); + gLastTimeThreadLimitReported = now; + } + + /* At intervals check to re-test the exceeded limit */ + /* Log an error at intervals */ + if (now > + (gLastTimeExceededLimitReached + gBackoffInterval)) { + if (gLastTimeExceededLimitReached > 0) { + char limitOver[80]; + sprintf(limitOver, + "Dymamo backoff interval over. limit = %d, backoff interval = %d seconds", + gMaxHandlers, gBackoffInterval); + gCMLDRPBlock.logFunction(gCMLDRPBlock.logShellData, + kLog_Info, + kLogMessage_OneString, + limitOver, NULL); + gExceededLimit = 0; + } + } + } + + if (!gExceededLimit) { + if (gHandlerCount < gMaxHandlers) { + gHandlerCount++; + returnValue = 0; + } else { + gLastTimeExceededLimitReached = time(NULL); + gExceededLimit = 1; + } + } + + releaseWriteLock(&gHandlerCountLock); + } + } + return returnValue; +} + +/** + * Release a handler. + */ +void releaseHandler() +{ + if (gEnforceMaxHandlers != 0) { + if (0 == getWriteLock(&gHandlerCountLock, kDefaultHandlersTimeout)) { + gHandlerCount--; + releaseWriteLock(&gHandlerCountLock); + } + } +} + +#endif diff --git a/lc-continuity/mk4/moddynamo/CMLDRP.h b/lc-continuity/mk4/moddynamo/CMLDRP.h new file mode 100644 index 0000000000000000000000000000000000000000..bf623540f8ef054c9730f9823ae36ff9ea9bbffd --- /dev/null +++ b/lc-continuity/mk4/moddynamo/CMLDRP.h @@ -0,0 +1,279 @@ +/* + * Copyright (C) 1997 Art Technology Group, Inc. + * All Rights Reserved. No use, copying or distribution of this + * work may be made except in accordance with a valid license + * agreement from Art Technology Group. This notice must be + * included on all copies, modifications and derivatives of this + * work. + * + * Art Technology Group (ATG) MAKES NO REPRESENTATIONS OR WARRANTIES + * ABOUT THE SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. ATG SHALL NOT BE + * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, + * MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. + * + * "Dynamo" is a trademark of Art Technology Group, Inc. + */ + +/* + CMLDRP.h - interface for CMLDRP subsystem + ("Connection-Module Load-Distribution Request Protocol", or something) + */ + + +#ifndef _CMLDRP_H_ +#define _CMLDRP_H_ + +#include + +#ifdef WIN32 +/* NT */ +#include +#else +/* UNIXen */ +#include +#include +#include +#include +#include +#ifdef _IRIX +#include +#endif +#ifdef SOLARIS2_6 +#include +#endif +#endif + +#include "DRPTypes.h" +#include "DRPClient.h" + +#ifdef _DRP_MTHREAD +#include "rwLocks.h" + +extern RWLock gLoadDataLock; /* defined in CMLDRP.c */ +void setEnforceMaxHandlers(int flag); +void setMaxHandlers(int count); +void setBackoffInterval(time_t interval); +int acquireHandler(); +void releaseHandler(); + +#include "io.h" /* libw3 io.h */ +#define kCMLDRP_DefaultTcpTimeout 10000 /* milliseconds */ +#endif + + +#define kCMLDRP_DefaultTimeoutSec 3 +#define kCMLDRP_DefaultTimeoutUsec 0 + + +/* + * These intervals used to be 1 second for the minimum poll interval and + * 250 msec for the SleepTime. I believe that this is because of the + * forceUpdateCM stuff in DRPClient.c which does not work anyway. + * + * Instead, I think we should sleep slightly longer than the min poll + * interval so that we end up waking up, polling, sleeping, waking up polling + * etc. + */ +#define kCMLDRP_MinimumPollInterval 2 /* seconds */ + +#define kCMLDRP_Sleeptime 2500 /* milliseconds */ + +#define kCMLDRP_MaxIdentifierLength 48 /* includes some extra */ +#define kCMLDRP_MaxHttpHostLength 18 + + +#define kCMLDRP_IOBufferSize 1064 /* 1018 is large enough for 100 records */ +#define kCMLDRP_MaxCMLDRPRecords kMaxDRPRecords +#define kCMLDRP_BaseResponseSize 18 +#define kCMLDRP_LoadRecordSize 10 + + +#define kCMLDRP_RequestVersion 1 + + +/* offsets into request buffer */ +#define kCMLDRP_RequestVersionOffset 0 +#define kCMLDRP_RequestTypeOffset 2 +#define kCMLDRP_RequestSequenceOffset 4 +#define kCMLDRP_RequestIDLengthOffset 6 +#define kCMLDRP_RequestIDOffset 8 + +/* offsets into response buffer */ +#define kCMLDRP_ResponseVersionOffset 0 +#define kCMLDRP_ResponseTypeOffset 2 +#define kCMLDRP_ResponseSequenceOffset 4 +#define kCMLDRP_ResponseFlagsOffset 6 +#define kCMLDRP_ResponseNextHostOffset 8 +#define kCMLDRP_ResponseNextPortOffset 12 +#define kCMLDRP_ResponseIntervalOffset 14 +#define kCMLDRP_ResponseNumRecsOffset 16 +#define kCMLDRP_ResponseRecordOffset 18 + +/* offsets into load records in a buffer */ +#define kCMLDRP_RecordHostOffset 0 +#define kCMLDRP_RecordPortOffset 4 +#define kCMLDRP_RecordProbOffset 6 +#define kCMLDRP_RecordFlagsOffset 8 + + +#define kCMLDRP_RequestType 0xDABA +#define kCMLDRP_ResponseType 0xABBA + + +#define kCMLDRP_DefaultCMLDRPPort 8890 + + +#define kDrpServerFlags_Active 0x0002 +#define kDrpServerFlags_AcceptingNewSessions 0x0001 +#define kDrpServerFlags_Overloaded 0x0004 +#define kDrpServerFlags_SeemsDown 0x0008 + +#define kCMLDRPFlags_Initialized 0x0001 + + +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 256 +#endif + +#ifndef SOCKET_ERROR +#define SOCKET_ERROR -1 +#endif + +/* +** The standard C library function getpid() returns the current +** process id. In the WIN32 API the equivalent function is _getpid(). +*/ + +#ifdef WIN32 +#ifndef getpid +#define getpid _getpid +#endif +#endif + +typedef struct _CMLDRP_ServerInfo CMLDRP_ServerInfo; +typedef struct _CMLDRP_Block CMLDRP_Block; + +/* CMLDRP_ServerInfo: associates the host name with a port for a single + CMLDRP server */ +struct _CMLDRP_ServerInfo { + char * host; + unsigned short port; +}; + + +/* CMLDRP_Block: block of data maintained by the CMLDRP subsystem; in the + multithreaded case, an instance of this block will be associated with + the CMLDRP thread via thread-local-storage (see threadabstr.h) */ +struct _CMLDRP_Block { + socket_t sock; /* used for UDP port */ + +#ifdef _DRP_MTHREAD + InputStream *inputStream; /* used for TCP input stream */ + OutputStream *outputStream; /* used for TCP output stream */ +#endif + + /* numCMDLRPServers is number of records in cmldrpServers field; + cmldrpServers is the ordered collection of CMDLRP server info passed + in at init time + nextServerToContactIdx is index into cmldrpServers indicating next + CMLDRP server to contact for load info; a value of -1 indicates + that the 1st (0th) server should be used next + tempCMLDRPServer is a temporary storage place to hold CMLDRP server + contact info received from a CMLDRP server that is not already + present in the cmldrpServers field + nextServerToContact points to the sockaddr_in describing the next + CMLDRP server to contact for load information; could be pointing + at tempCMLDRPServer or into cmldrpServers + lastTimeSilenceReported indicates the time (in seconds since the epoch) + at which the CMLDRP system last logged the unavailability of the + server indicated by nextServerToContact or nextServerToContactIdx; + NB: this value MUST be reset to zero whenever nextServerToContact[Idx] + is updated. + */ + struct sockaddr_in cmldrpServers[kCMLDRP_MaxCMLDRPRecords]; + int numCMLDRPServers; + int nextServerToContactIdx; + struct sockaddr_in tempCMLDRPServer; + struct sockaddr_in * nextServerToContact; + time_t lastTimeSilenceReported; + + struct timeval timeout; + + char identifier[kCMLDRP_MaxIdentifierLength]; + unsigned short identifierLength; + + char httpHost[kCMLDRP_MaxHttpHostLength]; + unsigned short httpPort; + + unsigned short pollInterval; + + time_t nextUpdateTime; + + unsigned char ioBuffer[kCMLDRP_IOBufferSize]; + + unsigned short cmldrpVersion; + unsigned short cmldrpFlags; + + unsigned short sequenceNumber; + + LogMessage_fn logFunction; + void * logShellData; + + char debugEnabled; +}; + +extern CMLDRP_Block gCMLDRPBlock; +extern drpServerRecord gDrpServers[]; /* NB: not sorted */ +extern drpServerRecord * gDrpServerPtrs[]; /* NB: sorted by IP:addr */ +extern int gNumDrpServers; + +int cmldrpInitialize(int iNumServers, CMLDRP_ServerInfo * iServers, + const char * iBindAddress, unsigned short iHTTPPort, + LogMessage_fn iLogFunction, void * iLogShellData); +void cmldrpShutdown(); + +void cmldrpSetDebug(int pFlag); + +void cmldrpSetManagerRotationEnabled(int flag); + +/* signals shutdown to the CMLDRP thread (MT only) */ +extern unsigned short gCMLDRP_Shutdown; + +/* current version of DRP server load info */ +extern unsigned int gCMLDRP_InfoVersion; + +/* signals forced-update to CMLDRP thread (MT only) */ +extern unsigned short gCMLDRP_UpdateNow; + + +drpServerRecord ** getDrpServerRecord(const drpServerRecord ** iServerPtrs, + int iNumServers, unsigned long iAddr, + unsigned short iPort); +int compareDRPServerRecPtrs_ipPort(const void * iPtr1, const void * iPtr2); + +CMLDRP_ServerInfo * parseDynamoManagers(char * iDynamoManagers, + int * oNumServers); + +#ifndef _DRP_MTHREAD +int cmldrpUpdate_MP(CMLDRP_Block * pBlock); +#endif + + + +typedef struct _DebugInfo DebugInfo; + +/* _DebugInfo: information useful during debugging */ +struct _DebugInfo { + int numRequestThreads; + int numActiveRequests; + int numWaitingOnReadLock; + int numWaitingOnPool; + int numWaitingToConnect; + int numSendingRequest; + int numWaitingForResponse; +}; + +#endif + diff --git a/lc-continuity/mk4/moddynamo/CVS/Entries b/lc-continuity/mk4/moddynamo/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..2008d039d3798f18be87e83c182237ff94889053 --- /dev/null +++ b/lc-continuity/mk4/moddynamo/CVS/Entries @@ -0,0 +1,23 @@ +/CMLDRP.c/1.2/Thu Mar 18 15:04:15 2004//Tmk4_mod6_rc2 +/CMLDRP.h/1.1/Fri Dec 12 15:08:04 2003//Tmk4_mod6_rc2 +/DRPClient.c/1.2/Thu Mar 18 15:04:15 2004//Tmk4_mod6_rc2 +/DRPClient.h/1.1/Fri Dec 12 15:08:04 2003//Tmk4_mod6_rc2 +/DRPServerIO.c/1.2/Thu Mar 18 15:04:15 2004//Tmk4_mod6_rc2 +/DRPServerIO.h/1.1/Fri Dec 12 15:08:04 2003//Tmk4_mod6_rc2 +/DRPTypes.h/1.1/Fri Dec 12 15:08:04 2003//Tmk4_mod6_rc2 +/DynSock.c/1.2/Thu Mar 18 15:04:15 2004//Tmk4_mod6_rc2 +/DynSock.h/1.1/Fri Dec 12 15:08:04 2003//Tmk4_mod6_rc2 +/Makefile/1.4/Tue Jun 22 14:36:14 2004//Tmk4_mod6_rc2 +/cmVersion.h/1.1/Fri Dec 12 15:08:04 2003//Tmk4_mod6_rc2 +/hook.c/1.12/Thu Mar 18 15:04:15 2004//Tmk4_mod6_rc2 +/io.c/1.2/Thu Mar 18 15:04:15 2004//Tmk4_mod6_rc2 +/io.h/1.1/Fri Dec 12 15:08:04 2003//Tmk4_mod6_rc2 +/pageroute.c/1.2/Thu Mar 18 15:04:15 2004//Tmk4_mod6_rc2 +/pageroute.h/1.1/Fri Dec 12 15:08:04 2003//Tmk4_mod6_rc2 +/rwLocks.h/1.1/Fri Dec 12 15:08:04 2003//Tmk4_mod6_rc2 +/sockerrs.c/1.2/Thu Mar 18 15:04:15 2004//Tmk4_mod6_rc2 +/sockerrs.h/1.1/Fri Dec 12 15:08:04 2003//Tmk4_mod6_rc2 +/system.h/1.1/Fri Dec 12 15:08:04 2003//Tmk4_mod6_rc2 +/threadabstr.c/1.2/Thu Mar 18 15:04:15 2004//Tmk4_mod6_rc2 +/threadabstr.h/1.1/Fri Dec 12 15:08:04 2003//Tmk4_mod6_rc2 +D diff --git a/lc-continuity/mk4/moddynamo/CVS/Repository b/lc-continuity/mk4/moddynamo/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..837e5b094793ac4a8a57913819241d123455e282 --- /dev/null +++ b/lc-continuity/mk4/moddynamo/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/moddynamo diff --git a/lc-continuity/mk4/moddynamo/CVS/Root b/lc-continuity/mk4/moddynamo/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/moddynamo/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/moddynamo/CVS/Tag b/lc-continuity/mk4/moddynamo/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/moddynamo/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/moddynamo/DRPClient.c b/lc-continuity/mk4/moddynamo/DRPClient.c new file mode 100644 index 0000000000000000000000000000000000000000..1345da322499dc7fc847c49090d19d02cdbf2a81 --- /dev/null +++ b/lc-continuity/mk4/moddynamo/DRPClient.c @@ -0,0 +1,3050 @@ +/* + * Copyright (C) 1997 Art Technology Group, Inc. + * All Rights Reserved. No use, copying or distribution of this + * work may be made except in accordance with a valid license + * agreement from Art Technology Group. This notice must be + * included on all copies, modifications and derivatives of this + * work. + * + * Art Technology Group (ATG) MAKES NO REPRESENTATIONS OR WARRANTIES + * ABOUT THE SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. ATG SHALL NOT BE + * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, + * MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. + * + * "Dynamo" is a trademark of Art Technology Group, Inc. + */ + +/* + DRPClient.c - DRP client functionality + */ + +/* #define DEBUG */ + + +#ifdef WIN32 +/* NT */ +#include + +#define EINTR WSAEINTR +#define ETIMEDOUT WSAETIMEDOUT + +#else +/* UNIXen */ +#include +#include +#include +#include +#include +#include + +#ifndef _DRP_MTHREAD +# include +#endif + +#define closesocket(s) close(s) /* to match NT closesocket() routine */ +#endif + + +#include +#include +#include +#include + + +#include "DRPClient.h" +#include "DRPServerIO.h" + +#include "CMLDRP.h" + +#include "pageroute.h" + +#include "rwLocks.h" + +extern int errno; +extern DebugInfo gDebugInfo; + +#ifdef _CPOOL +extern unsigned short gCP_Enabled; +#endif + +/* The number of seconds that singly threaded web servers wait to poll the CM */ +#define kSingleThreadPollSeconds 60 + +static time_t gLastUpdateTime = 0; + +int gRetryServerAfterFailure = 0; + +/* static globals */ + +#define kDefaultSessionCookieName "sessionid" + +/** + * This is the name used for both cookies and query arguments + */ +static char *gSessionCookieName = kDefaultSessionCookieName; +static int gSessionCookieNameLength = 9; + +/* Name and port number of the server to redirect requests to in the case + * of total dynamo failure. + */ +static char *gFailoverServer = NULL; + +/** + * Used for URL arguments + */ +#define kDefaultSessionParamName "$sessionid$" + +#define kDynServerName "dyn_server" +#define kDynServerLength 10 + +static char *gSessionParamName = kDefaultSessionParamName; +static int gSessionParamNameLength = 11; + +#define kCookieHeaderName "cookie" + + +/* 0 == no info known re: DRP servers; + !0 == info has been obtained from DM */ +/* drpContextBlock * a */ +#define serverInfoAvailable(a) (gCMLDRP_InfoVersion != 0) + + +/* r: drpServerRecord * + evaluates to: 0 == server not known to be active; !0 == server active */ +#define serverActive(r) \ + ((r) && ((r)->flags & kDrpServerFlags_Active)) + +/* r: drpServerRecord * + evaluates to: 0 == server not accepting new sessions */ +#define serverAcceptingNewSessions(r) \ + ((r) && ((r)->flags & kDrpServerFlags_AcceptingNewSessions)) + +/* r: drpServerRecord * + evaluates to: 1 == server is known to be overloaded */ +#define serverOverloaded(r) \ + ((r) && ((r)->flags & kDrpServerFlags_Overloaded)) + +/* r: drpServerRecord * + evaluates to: 1 == server seems to be down */ +#define serverSeemsDown(r) \ + ((r) && ((r)->flags & kDrpServerFlags_SeemsDown)) + +/* clear DRP server's active flag + r: drpServerRecord * + */ +#define markServerInactive(r) \ + ((r)->flags &= ~kDrpServerFlags_Active) + + +/* Set the DRP servers seems down flag + r: drpServerRecord * + */ +#define markServerSeemsDown(r) \ + ((r)->flags |= kDrpServerFlags_SeemsDown) + + +/* 0: parameter p requires a single response object; + !0: parameter p requires a list (indexed) of responses (e.g. headers) */ +#define paramDemandsListResponse(p) \ + ((p.name.type == kDefined) && ((p.name.value.defined == kParameters) || \ + (p.name.value.defined == kHeaders))) + +/* 0: parameter p requires a DRP 4-byte Integer response; + !0: parameter p requires a string-type response */ +#define paramDemandsIntResponse(p) \ + ((p.name.type == kDefined) && ((p.name.value.defined == kContentLength) || \ + (p.name.value.defined == kServerPort))) + +/* establish the DRP server record pointed to by recPtr as the "current + server" for context-block pCB */ +#define setCurrentServer(pCB,recPtr) \ + (pCB)->currentServer = (recPtr) + + +/* static function prototypes */ +static DrpServiceStatus forceUpdateFromDM(drpContextBlock * pCB); + +static DrpServiceStatus drpService_sid(drpContextBlock * pCB); +static DrpServiceStatus drpService_load(drpContextBlock * pCB); +static DrpServiceStatus drpService_route(drpContextBlock * pCB); +static int isStaticallyRoutedRequest(drpContextBlock * pCB); +static int getDrpServerInfoFromSid(drpContextBlock * pCB, + unsigned long *oAddr, + unsigned short *oPort); +static DrpServiceStatus tryServer(drpContextBlock * pCB, + drpServerRecord * drpServer); +static DrpServiceStatus drpService_server(drpContextBlock * pCB); +#ifdef _CPOOL +static int pooledConnectToCurrentServer(drpContextBlock * pCB); +#endif +static int connectedToCurrentServer(drpContextBlock * pCB); +static int connectToCurrentServer(drpContextBlock * pCB); +static DrpServiceStatus sendBeginRequest(drpContextBlock * pCB); +static DrpServiceStatus handleDrpServerRequest(drpContextBlock * pCB); + +static DrpServiceStatus handleGetParameters(drpContextBlock * pCB); +static DrpServiceStatus handleReadData(drpContextBlock * pCB); +static DrpServiceStatus handleWriteData(drpContextBlock * pCB); +static DrpServiceStatus handleFlush(drpContextBlock * pCB); +static DrpServiceStatus handleClose(drpContextBlock * pCB); +static DrpServiceStatus handleHeader(drpContextBlock * pCB); +static DrpServiceStatus handleReplyPacket(drpContextBlock * pCB); + +static DrpServiceStatus doSendHeader(drpContextBlock * pCB); + +static DrpServiceStatus handleGetAllHeaders(drpContextBlock * pCB); + +static int getSessionID(drpContextBlock * pCB); + +static DrpServiceStatus batchHeaders(drpContextBlock * pCB); +static DrpServiceStatus dispatchHeaders(drpContextBlock * pCB); + +static DrpServiceStatus sendParameter(drpContextBlock * pCB, + drpByte iDefinedParam, + drpIdentifier * iIdentParam); + +static int copyGlobalDrpServerInfo(drpContextBlock * pCB); + +#if 0 +/* obsoleted - see end of file */ +static DrpServiceStatus handleGetAllParameters(drpContextBlock * pCB); +static void getNextQueryArg(char *pBuffer, int namePtr, int *oValPtr, + int *oNextPtr); +#endif + +#if 0 +/* useful for debugging */ +void debugPrint(const char *message) +{ + FILE *debugOut = fopen("d:\\debug.log", "a"); + if (debugOut != NULL) { + fputs(message, debugOut); + fclose(debugOut); + } +} +#endif + +/** + * drpInitialize + * initialize the DRP2 subsystem for a connection module instance. should + * be invoked once for each process (not thread) containing a CM instance, + * before any DRP2 service is performed. + */ +void drpInitialize(void) +{ + +#ifdef _DRP_MTHREAD + srand((unsigned) time(NULL)); + +#else + + /* need a better seed for multiple processes otherwise each process + will start with the same seed or a similar seed. */ + +#ifdef WIN32 + /* use the millisecond part of the time as the seed. */ + struct _SYSTEMTIME tp; + GetSystemTime(&tp); + srand(tp.wMilliseconds); + +#else + /* use the microsecond part of the time as the seed. */ + unsigned int seed = 0; + struct timeval tp; + int ret = gettimeofday(&tp, 0); + if (!ret) { + seed = (unsigned int) tp.tv_usec; + } else { + /* this should never happen. use ftime instead. */ + struct timeb tb; + ret = ftime(&tb); + if (!ret) { + seed = (unsigned int) tb.millitm; + } else { + /* we should REALLY never get here. */ + seed = (unsigned int) time(0); + } + } + srand(seed); + +#endif /* ifdef WIN32 */ + +#endif /* ifdef _DRP_MTHREAD */ +} + + +/** + * drpReset + * Reset a DRP Context Block between service requests + * pCB: context block to reset + * note: the context block object should be byte-cleared to 0 when created + * by the shell + */ +void drpReset(drpContextBlock * pCB) +{ + pCB->serviceStatus = kIdle; + + /* Was this request targeted with dyn_server=... */ + pCB->isTargetedRequest = 0; + + /* reset request logging to off */ + pCB->isLoggedRequest = 0; + + /* reset debugging to off */ + pCB->debugEnabled = 0; + + /* create or reset internal buffers */ + if (!pCB->ioBuffer.buffer) + createGrowBuffer(&(pCB->ioBuffer), kMainBufferSize); + else + clearGrowBuffer_m((&pCB->ioBuffer)); + + if (!pCB->ioBuffer2.buffer) + createGrowBuffer(&(pCB->ioBuffer2), kMinorBufferSize); + else + clearGrowBuffer_m((&pCB->ioBuffer2)); + + if (!pCB->headers.buffer) + createGrowBuffer(&(pCB->headers), kMinorBufferSize); + else + clearGrowBuffer_m((&pCB->headers)); + + if (!pCB->headers2.buffer) + createGrowBuffer(&(pCB->headers2), kMinorBufferSize); + else + clearGrowBuffer_m((&pCB->headers2)); + + if (!pCB->statusBuffer.buffer) + createGrowBuffer(&(pCB->statusBuffer), kMinorBufferSize); + else + clearGrowBuffer_m((&pCB->statusBuffer)); + + /* create or reset socket IO buffers */ + if (!pCB->recvBuf.data) { + pCB->recvBuf.capacity = kSockBufSize; + pCB->recvBuf.data = (char *) malloc(pCB->recvBuf.capacity); + } else { + pCB->recvBuf.curPtr = 0; + pCB->recvBuf.used = 0; + } + + if (!pCB->sendBuf.data) { + pCB->sendBuf.capacity = kSockBufSize; + pCB->sendBuf.data = (char *) malloc(pCB->sendBuf.capacity); + } else { + pCB->sendBuf.curPtr = 0; + pCB->sendBuf.used = 0; + } + + pCB->statusSetByServer = 0; + pCB->statusSentToAgent = 0; + pCB->statusCode = 0; + pCB->statusMesg.type = kNull; + pCB->sessionID[0] = '\0'; +} + +/** + * drpSetFailoverServer + * Set the hostname and port number of the server to redirect requests to + * in the event of a total application failure. + */ +void drpSetFailoverServer(const char *newServer) +{ + if (gFailoverServer != NULL) + free(gFailoverServer); + if (newServer == NULL) + gFailoverServer = NULL; + else + gFailoverServer = (char *) strdup(newServer); +} + +/** + * drpSetSessionCookieName + * Set the session cookie name used by this server. + */ +void drpSetSessionCookieName(const char *pCookieName) +{ + if (pCookieName) { + gSessionCookieName = (char *) strdup(pCookieName); + gSessionCookieNameLength = strlen(pCookieName); + } +} + +/** + * drpService + * Service the current request + * return: 0 == success; !0 == failure (details in pCB->serviceStatus) + */ +int drpService(drpContextBlock * pCB) +{ + int returnValue = kDrpServiceOk; + +#ifdef _DRP_MTHREAD + int acquiredHandler = 1; + /* first: check to see if we are not exceeding our handler limit */ + if (acquireHandler() != 0) { + returnValue = kDrpServiceFailover; + acquiredHandler = 0; + goto DRP_SVC_EXIT; + } +#endif + +#ifndef _DRP_MTHREAD + /* + * In non-multi-threaded servers, we need to poll the load manager + * periodically to update the server table. + */ + if (time(NULL) > gLastUpdateTime + kSingleThreadPollSeconds) { + forceUpdateFromDM(pCB); + } +#endif + + /* next: check to see if we should update local copy of drp-server + info from the CMLDRP system */ + if ((pCB->drpServerInfoVersion != gCMLDRP_InfoVersion) || + (!serverInfoAvailable(pCB))) { + int status = copyGlobalDrpServerInfo(pCB); + if (status != 0 && pCB->debugEnabled) + pCB->logMessage(pCB->shellData, kLog_Info, + kLogMessage_OneString, + "can't global global server info", NULL); + } + + pCB->serviceStatus = kConnectingToServer; + + if (!serverInfoAvailable(pCB)) { + if (pCB->debugEnabled) + pCB->logMessage(pCB->shellData, kLog_Info, + kLogMessage_OneString, + "no serverInfo available", NULL); + /* copyGlobalServerInfo will have attempted to force a data update + if no server info available, so don't do so here */ + + /* if no server info is available, probably the load manager is down + * or some other catastrophic failure. try to fail over to a different + * server. + */ + getSessionID(pCB); /* extract session ID information, if any */ + returnValue = kDrpServiceFailover; + + pCB->logMessage(pCB->shellData, kLog_Error, + kLogMessage_NoDRPServerAvailable, NULL, NULL); + goto DRP_SVC_EXIT; + } + + /* if there is a session ID cookie, route to the server that it came + * from. + */ + if (getSessionID(pCB)) { + returnValue = drpService_sid(pCB); + /* errors will be logged by drpService_sid() */ + if (returnValue != kDrpServiceOk && pCB->isTargetedRequest) { + if (pCB->debugEnabled) + pCB->logMessage(pCB->shellData, kLog_Error, + kLogMessage_OneString, + "aborting failed to deliver request to specic dyn_server", + NULL); + goto DRP_SVC_EXIT; + } + if (returnValue != kDrpServiceOk && pCB->debugEnabled) { + char buf[256]; + sprintf(buf, + "failed sending request to session server with sessionId=%s", + pCB->sessionID); + pCB->logMessage(pCB->shellData, kLog_Error, + kLogMessage_OneString, buf, NULL); + } + } + + /* there is no session ID cookie; if this is one of the URLs that + * must be hashed to a particular server, do it. + */ + else if (isStaticallyRoutedRequest(pCB)) { + returnValue = drpService_route(pCB); + /* errors will be logged by drpService_load() */ + } + + /* if the request wasn't serviced by either SID redirection or static + * routing then service it by load. + */ + if (pCB->serviceStatus < kServicingRequest) { + returnValue = drpService_load(pCB); + /* errors will be logged by drpService_load() */ + } + + DRP_SVC_EXIT: + + /* If a total application failover has occurred, try to redirect the + * request to a different application server. + */ + if ((gFailoverServer != NULL) && (returnValue == kDrpServiceFailover)) { + drpIdentifier paramName; + growBuffer requestUrl; + growBuffer failoverUrl; + growBuffer name; + growBuffer value; + + /* we should verify that this is a redirectable method (ie, not POST) + * here + */ + + createGrowBuffer(&requestUrl, kMinorBufferSize); + createGrowBuffer(&failoverUrl, kMinorBufferSize); + createGrowBuffer(&name, kMinorBufferSize); + createGrowBuffer(&value, kMinorBufferSize); + + /* extract the request URL information + */ + paramName.name.type = kDefined; + paramName.name.value.defined = kPathInfo; + paramName.hasIndex = 0; + pCB->getParameter(pCB->shellData, ¶mName, &requestUrl); + + concatenate(&failoverUrl, "http://"); + concatenate(&failoverUrl, gFailoverServer); + if (requestUrl.buffer[0] != '/') + concatenate(&failoverUrl, "/"); + concatenate(&failoverUrl, requestUrl.buffer); + + /* if there's no session ID information already in the URL, try to add + * it. + */ + if (!strstr(requestUrl.buffer, "$sessionid$") && + (strlen(pCB->sessionID) > 0)) { + concatenate(&failoverUrl, ";$sessionid$"); + concatenate(&failoverUrl, pCB->sessionID); + } + + /* assemble the HTTP header and send it on its way + */ + pCB->statusCode = kFailoverStatusCode; /* Moved Temporarily */ + pCB->statusSetByServer = 1; + /*pCB->statusMesg = kFailoverStatusMessage; -- gotta convert this */ + setGrowBuffer(&name, "Location"); + pCB->setResponseHeader(pCB->shellData, &name, &failoverUrl); + setGrowBuffer(&name, "Content-Type"); + setGrowBuffer(&value, "text/html"); + pCB->setResponseHeader(pCB->shellData, &name, &value); + returnValue = doSendHeader(pCB); + + /* Emit a reasonable error page. + */ + if (returnValue == kDrpServiceOk) { + setGrowBuffer(&value, "\n"); + concatenate(&value, "Application Error\n"); + concatenate(&value, "

Application Error

\n"); + concatenate(&value, + "A recoverable application error has occurred. If you would like to continue, please use "); + concatenate(&value, ""); + concatenate(&value, failoverUrl.buffer); + concatenate(&value, ".\n"); + concatenate(&value, "\n"); + concatenate(&value, "\n"); + returnValue = + pCB->writeToAgent(pCB->shellData, &value, value.used); + } + + /* emit redirection page HTML here */ + if (returnValue != kDrpServiceOk) + returnValue = handleFlush(pCB); + handleClose(pCB); + + destroyGrowBuffer(&requestUrl); + destroyGrowBuffer(&failoverUrl); + destroyGrowBuffer(&name); + destroyGrowBuffer(&value); + } +#ifdef _DRP_MTHREAD + if (acquiredHandler) { + releaseHandler(); + } +#endif + + return returnValue; +} + + +#ifdef _DRP_MTHREAD +#define kSleepTime_WaitingForUpdate 250 /* msec */ +#define kWaitTime_WaitingForUpdate 1 /* sec */ +#else +#define kSleepTime_WaitingForUpdate 1 /* sec */ +#define kWaitTime_WaitingForUpdate 1 /* sec */ +#endif + + + +/** + * noteDrpServerSeemsDown + * Update the global flags for a Drp server to note + * that it seems to be down + * return: 0 == success; !0 == failure + */ +static int noteDrpServerSeemsDown(drpContextBlock * pCB) +{ + /* NB: must obtain write lock on global drp server info in order + to update a global flag for this server. This is an expensive + operation only to be undertaken in extreme cases where the + drp server seems to be down + */ + if (!getWriteLock(&gLoadDataLock, kRWL_DefaultReadTimeout)) { + drpServerRecord *drpServer = pCB->currentServer; + drpServerRecord **globalRecord; + + /* Find and update the location in the global server list */ + globalRecord = + getDrpServerRecord((const drpServerRecord **) gDrpServerPtrs, + gNumDrpServers, drpServer->inetaddr, + drpServer->port); + + if (globalRecord != NULL) { + markServerSeemsDown((*globalRecord)); + (*globalRecord)->probability = 0; + /* Update the info version so that all the handler threads will now + * pick up this information + */ + gCMLDRP_InfoVersion++; + } +#ifdef _DRP_MTHREAD + releaseWriteLock(&gLoadDataLock); +#endif + return 0; + } + return -1; +} + + +/** + * copyGlobalDrpServerInfo + * Copy drp server information from the CMLDRP system's global vars. + * return: 0 == success; !0 == failure + */ +static int copyGlobalDrpServerInfo(drpContextBlock * pCB) +{ + int returnValue = 0; + + if (gCMLDRP_InfoVersion == 0) { + /* no DRP server info available yet */ + forceUpdateFromDM(pCB); + + /* did the data get updated? */ + if (gCMLDRP_InfoVersion == 0) { + if (pCB->debugEnabled) { + pCB->logMessage(pCB->shellData, kLog_Info, + kLogMessage_OneString, + "No drp servers in the global list", NULL); + } + goto COPY_GLOBAL_INFO_EXIT; + } + } + + /* NB: must obtain read lock on global drp server info! */ + if (!getReadLock(&gLoadDataLock, kRWL_DefaultReadTimeout)) { + int s; + short newServers = 0; + + /* + * Only set the probability to 0 once we've gotten the read lock. If + * we fail to get the read lock, at least we can go on and use the old + * cached version of the hosts + */ + pCB->totalProb = 0; + + /* update information for all drp servers known to the local thread */ + for (s = 0; s < pCB->numDrpServers; s++) { + pCB->drpServers[s].probability = gDrpServers[s].probability; + pCB->drpServers[s].flags = gDrpServers[s].flags; + if (pCB->drpServers[s].flags & kDrpServerFlags_Active) + pCB->totalProb += pCB->drpServers[s].probability; + } + + /* establish new information for all drp servers not yet known to + local thread (i.e. newly obtained by the CMLDRP thread since last + update from local thread) */ + while (gNumDrpServers > pCB->numDrpServers) { + int idx = pCB->numDrpServers; + + newServers++; + + pCB->drpServers[idx].inetaddr = gDrpServers[idx].inetaddr; + pCB->drpServers[idx].port = gDrpServers[idx].port; + pCB->drpServers[idx].probability = + gDrpServers[idx].probability; + pCB->drpServers[idx].flags = gDrpServers[idx].flags; + pCB->drpServers[idx].sock = kInvalidSocket; + + pCB->drpServerPtrs[idx] = &pCB->drpServers[idx]; + + if (pCB->drpServers[idx].flags & kDrpServerFlags_Active) + pCB->totalProb += pCB->drpServers[idx].probability; + +#ifdef _CPOOL + pCB->drpServers[idx].pool = gDrpServers[idx].pool; +#endif + + pCB->numDrpServers++; + } + + /* update local drp server information version */ + pCB->drpServerInfoVersion = gCMLDRP_InfoVersion; + +#ifdef _DRP_MTHREAD + releaseReadLock(&gLoadDataLock); +#endif + + /* sort locally stored servers by IP:port */ + if (newServers) { + qsort(pCB->drpServerPtrs, pCB->numDrpServers, + sizeof(drpServerRecord *), + compareDRPServerRecPtrs_ipPort); + } + } else { + if (pCB->debugEnabled) { + pCB->logMessage(pCB->shellData, kLog_Info, + kLogMessage_OneString, + "Failed to copy server info - using stale server info", + NULL); + } + returnValue = -1; + } + + COPY_GLOBAL_INFO_EXIT: + + return returnValue; +} + + +/** + * forceUpdateFromDM + * (DM == "Dynamo Manager", i.e. CMLDRP server) + * force communication w/ a DM to update DRP server information; + * wait for DRP server info to be updated before returning + * return: 0 == success; !0 == failure (update did not occur) + */ +static DrpServiceStatus forceUpdateFromDM(drpContextBlock * pCB) +{ + int returnValue = kDrpServiceError; + time_t waketime; + unsigned int infoVersion = gCMLDRP_InfoVersion; + + /* setting this flag forces CMLDRP system to attempt to update its + globally-held drp server information */ + gCMLDRP_UpdateNow = 1; + + gLastUpdateTime = time(NULL); + + waketime = gLastUpdateTime + kWaitTime_WaitingForUpdate; + do { +#ifdef _DRP_MTHREAD + /* multithreaded case: wait for the CMLDRP thread to get its data */ + thread_sleep(kSleepTime_WaitingForUpdate); +#else + /* multiprocess case: invoke CMLDRP communication directly */ + returnValue = cmldrpUpdate_MP(&gCMLDRPBlock); +#endif + if (gCMLDRP_InfoVersion != infoVersion) { + returnValue = kDrpServiceOk; + break; /* out of do/while loop */ + } + } while (time(NULL) < waketime); + + return returnValue; +} + + +/** + * getSessionID + * Obtain a session ID from the current request, if one is available. + * + * Note: this routine also looks for the dyn_server=IPADDR:PORT option. + * If it exists, it sets pCB->isTargetedRequest and stores the targeted + * IP address and IP port in the request. + * return: 0 == no session ID found; !0 == session ID placed in pCB + */ +static int getSessionID(drpContextBlock * pCB) +{ + int returnValue = 0; /* assume no session ID */ + drpIdentifier cookieHeaderName; + drpIdentifier pathInfoParamName; + drpIdentifier queryParamName; + int result; + + pCB->isTargetedRequest = 0; + + /* first check in Dynamo URI args */ + pathInfoParamName.name.type = kDefined; + pathInfoParamName.name.value.defined = kPathInfo; + pathInfoParamName.hasIndex = 0; + + result = pCB->getParameter(pCB->shellData, &pathInfoParamName, + &pCB->ioBuffer); + if (result == 0) { + /* got some URL params */ + char *sidStart; + char *searchStart = pCB->ioBuffer.buffer; + + pCB->ioBuffer.buffer[pCB->ioBuffer.used] = kChar_Null; + + /* + * The URL parameter string is of the form: + * + * ;$name1$value1;$name2$value2 + */ + do { + sidStart = strchr(searchStart, kChar_Semicolon); + if (sidStart) { + sidStart++; /* Skip the semicolon */ + if (!strncmp + (sidStart, gSessionParamName, + gSessionParamNameLength)) { + char *sidEnd; + int sidLen; + sidStart += gSessionParamNameLength; + /* find the ending semicolon, if any */ + sidEnd = strchr(sidStart, kChar_Semicolon); + if (sidEnd == NULL) + sidEnd = &sidStart[strlen(sidStart)]; + sidLen = sidEnd - sidStart; + if (sidLen < kMaxSessionIDLength) { + strncpy(pCB->sessionID, sidStart, sidLen); + pCB->sessionID[sidLen] = '\0'; + returnValue = 1; + break; + } + } + searchStart = sidStart + 1; + } + } while (sidStart != NULL); + } + + /* now check the dynamo query arguments for dyn_sid and dyn_server */ + queryParamName.name.type = kDefined; + queryParamName.name.value.defined = kQueryString; + queryParamName.hasIndex = 0; + + result = pCB->getParameter(pCB->shellData, &queryParamName, + &pCB->ioBuffer); + if (result == 0) { + /* got some Query params */ + char *sidStart; + char *searchStart = pCB->ioBuffer.buffer; + + pCB->ioBuffer.buffer[pCB->ioBuffer.used] = kChar_Null; + + sidStart = searchStart; + /* + * The Query parameter string is of the form: + * + * name1=value1&name2=value2 + */ + do { + if (!strncmp + (sidStart, gSessionCookieName, gSessionCookieNameLength)) { + char *sidEnd; + int sidLen; + sidStart += gSessionCookieNameLength + 1; + sidEnd = strchr(sidStart, kChar_Ampersand); + if (sidEnd == NULL) + sidEnd = &sidStart[strlen(sidStart)]; + sidLen = sidEnd - sidStart; + if (sidLen < kMaxSessionIDLength) { + strncpy(pCB->sessionID, sidStart, sidLen); + pCB->sessionID[sidLen] = '\0'; + returnValue = 1; + } + } else + if (!strncmp(sidStart, kDynServerName, kDynServerLength)) { + unsigned long serverAddr = 0; + char *sep; + int i; + + sidStart += kDynServerLength + 1; + + pCB->isTargetedRequest = 1; + + for (i = 0; i < 4; i++) { + char tmpbuf[128]; + char searchChar; + if (i == 3) + searchChar = kChar_Colon; + else + searchChar = kChar_Dot; + sep = strchr(sidStart, searchChar); + if (sep != NULL) { + serverAddr <<= 8; + strncpy(tmpbuf, sidStart, sep - sidStart); + tmpbuf[sep - sidStart] = '\0'; + serverAddr |= atoi(tmpbuf); + sidStart = sep + 1; + } + /* + * Bad IP address format + */ + else { + pCB->isTargetedRequest = 0; + break; + } + } + if (pCB->isTargetedRequest) { + pCB->targetedServerPort = atoi(sidStart); + if (pCB->targetedServerPort == 0) { + pCB->isTargetedRequest = 0; + } else { + /* + * Convert this from host to network byte order + */ + pCB->targetedServerAddr = htonl(serverAddr); + returnValue = 1; + if (pCB->debugEnabled) { + char buf[128]; + sprintf(buf, + "specific dyn_server=%lu.%lu.%lu.%lu:%hu", + pCB->targetedServerAddr & 0xff, + (pCB->targetedServerAddr >> 8) & 0xff, + (pCB->targetedServerAddr >> 16) & 0xff, + (pCB->targetedServerAddr >> 24) & 0xff, + pCB->targetedServerPort); + pCB->logMessage(pCB->shellData, kLog_Info, + kLogMessage_OneString, buf, + NULL); + } + } + } + } + searchStart = strchr(sidStart, kChar_Ampersand); + /* + * Skip the ampersand + */ + sidStart = searchStart + 1; + } while (searchStart != NULL); + } + + if (returnValue == 0) { + /* SID not found in dynamo url args; try cookie header */ + cookieHeaderName.hasIndex = 0; + cookieHeaderName.name.type = kAscii; + cookieHeaderName.name.numChars = strlen(kCookieHeaderName) + 1; + cookieHeaderName.name.value.ascii = kCookieHeaderName; + + result = pCB->getParameter(pCB->shellData, &cookieHeaderName, + &pCB->ioBuffer); + if (result == 0) { + /* there is something in the cookie header */ + char *sidStart; + + pCB->ioBuffer.buffer[pCB->ioBuffer.used] = kChar_Null; + sidStart = strstr(pCB->ioBuffer.buffer, gSessionCookieName); + if (sidStart) { + sidStart += gSessionCookieNameLength; + if (*sidStart == kChar_Equals) { + char *sidEnd; + int sidLen; + sidStart++; /* now sidStart points at 1st char in sid */ + /* This is a special char that represents an invalid session id */ + if (*sidStart != '-') { + sidEnd = strchr(sidStart, kChar_Semicolon); + if (sidEnd == NULL) + sidEnd = &sidStart[strlen(sidStart)]; + sidLen = sidEnd - sidStart; + if (sidLen < kMaxSessionIDLength) { + strncpy(pCB->sessionID, sidStart, sidLen); + pCB->sessionID[sidLen] = '\0'; + returnValue = 1; + } + } + } + } + } + } + + return returnValue; +} + +/** + * getShellParameter + * Helper function used to extract a shell parameter into a growBuffer. + * return: 0 on success, !0 on failure. + */ +int getShellParameter(drpContextBlock * pCB, int whichParam, + growBuffer * retBuf) +{ + drpIdentifier paramName; + int retValue; + + paramName.name.type = kDefined; + paramName.name.value.defined = whichParam; + paramName.hasIndex = 0; + retValue = pCB->getParameter(pCB->shellData, ¶mName, retBuf); + if (retValue == 0) { + if (retBuf->buffer[0] == '\0') /* failed if buffer is empty */ + retValue = -1; + } + return retValue; +} + +/** + * isStaticallyRoutedRequest + * See if the URI of the incoming request exists in the statically routed + * page table. + * returns 1 (true) if so, 0 (false) if not. + */ +int isStaticallyRoutedRequest(drpContextBlock * pCB) +{ + growBuffer buf; + int returnValue; + + if (createGrowBuffer(&buf, 1024) == NULL) + return 0; /* fails due to lack of memory */ + if (getShellParameter(pCB, kRequestURI, &buf) == 0) + returnValue = isStaticallyRoutedPage(buf.buffer); + else + returnValue = 0; /* no URI found */ + destroyGrowBuffer(&buf); + return returnValue; +} + +/** + * drpService_sid + * Use the session-ID from the current request to determine the DRP server + * with which to communicate; contact that server and use it to service + * the request + * return: 0 == success; !0 == failure + */ +static DrpServiceStatus drpService_sid(drpContextBlock * pCB) +{ + int returnValue = kDrpServiceOk; + unsigned long serverAddr; + unsigned short serverPort; + int result; + + /* get IP:port of requested DRP server from session id (SID stored + in context block) */ + if (pCB->isTargetedRequest) { + result = 0; + serverAddr = pCB->targetedServerAddr; + serverPort = pCB->targetedServerPort; + } else { + result = getDrpServerInfoFromSid(pCB, &serverAddr, &serverPort); + } + if (result == 0) { + drpServerRecord **serverRecord; + serverRecord = + getDrpServerRecord((const drpServerRecord **) pCB-> + drpServerPtrs, pCB->numDrpServers, + serverAddr, serverPort); + if (!serverRecord) { + if (pCB->debugEnabled) { + char buf[1024]; + sprintf(buf, + "Unable to find dynamo server with addr=%lu.%lu.%lu.%lu port=%hu", + serverAddr & 0xff, (serverAddr >> 8) & 0xff, + (serverAddr >> 16) & 0xff, + (serverAddr >> 24) & 0xff, serverPort); + pCB->logMessage(pCB->shellData, kLog_Error, + kLogMessage_OneString, buf, NULL); + } + /* most likely case: this session was started by another context + with more current info about avail drp servers, which this + context does not yet have; obtain that info */ + returnValue = forceUpdateFromDM(pCB); + serverRecord = + getDrpServerRecord((const drpServerRecord **) pCB-> + drpServerPtrs, pCB->numDrpServers, + serverAddr, serverPort); + } + + /* now, if server still not active, we can't use it */ + if ((!serverRecord) || (!serverActive((*serverRecord)))) + returnValue = kDrpServiceNoServer; + else + returnValue = tryServer(pCB, *serverRecord); + } + + return returnValue; +} + +/** + * drpService_load + * Use load-balancing to determine the DRP server with which to communicate + * to service the current request; contact that server and use it to + * complete service + * return: 0 == success; !0 == failure + */ +static DrpServiceStatus drpService_load(drpContextBlock * pCB) +{ + int returnValue = -1; + unsigned int randNum; + int s; + drpServerRecord *drpServer; + + if (pCB->debugEnabled && pCB->totalProb <= 0) { + char buf[256]; + sprintf(buf, "total probability is: %d numServers=%d", + pCB->totalProb, pCB->numDrpServers); + pCB->logMessage(pCB->shellData, kLog_Info, kLogMessage_OneString, + buf, NULL); + for (s = 0; s < pCB->numDrpServers; s++) { + + sprintf(buf, + "probability for server: %lu.%lu.%lu.%lu " + "port=%hu flags=%hu is: %hu", + pCB->drpServers[s].inetaddr & 0xff, + (pCB->drpServers[s].inetaddr >> 8) & 0xff, + (pCB->drpServers[s].inetaddr >> 16) & 0xff, + (pCB->drpServers[s].inetaddr >> 24) & 0xff, + pCB->drpServers[s].port, + pCB->drpServers[s].flags, + pCB->drpServers[s].probability); + pCB->logMessage(pCB->shellData, kLog_Info, + kLogMessage_OneString, buf, NULL); + } + } + + while (pCB->totalProb > 0) { + /* get a random number from 1 to totalProb (sum of all active DRP server + weights); walk through the list of DRP servers to find the + drp server record corresponding to the random number by weight */ + + drpServer = NULL; + randNum = (rand() % pCB->totalProb) + 1; /* 1..totalProb */ + + for (s = 0; (s < pCB->numDrpServers) && (randNum > 0); s++) { + if (serverActive(&pCB->drpServers[s])) { + if (serverAcceptingNewSessions(&pCB->drpServers[s]) && + !serverOverloaded(&pCB->drpServers[s]) && + !serverSeemsDown(&pCB->drpServers[s]) && + randNum <= pCB->drpServers[s].probability) { + drpServer = &pCB->drpServers[s]; + break; /* out of "for (s = 0..." loop */ + } + /* + * Only subtract the probablity if this server is in the list + */ + randNum -= MIN(pCB->drpServers[s].probability, randNum); + } + } + + if (drpServer) { + returnValue = tryServer(pCB, drpServer); + if (returnValue == 0) + break; /* out of "while pCb->totalProb > 0" */ + else if (gRetryServerAfterFailure) + break; + } else { + pCB->logMessage(pCB->shellData, kLog_Error, + kLogMessage_NoDRPServerAvailable, NULL, NULL); + + /* all servers failed; tell the HTTP server to try to fail over + * to a different dynamo cluster. + */ + returnValue = kDrpServiceFailover; + break; + } + } + + /* + * This is a last ditch effort to find a server to try. If the load + * manager mistakenly polled a dynamo and saw that it was down, it + * would get removed from the list. If we have no dynamos in the list, + * then and this "retry mode" is turned on, we go through the list + * and retry each server until we find one that works. + */ + if (returnValue != kDrpServiceOk && pCB->totalProb == 0) { + if (pCB->debugEnabled) + pCB->logMessage(pCB->shellData, kLog_Info, + kLogMessage_OneString, + "total prob is 0 retrying server list", NULL); + for (s = 0; s < pCB->numDrpServers; s++) { + /* + * Unless the server has been explicitly marked as inactive, overloaded + * or down. + */ + if (serverActive(&pCB->drpServers[s]) && + serverAcceptingNewSessions(&pCB->drpServers[s]) && + !serverOverloaded(&pCB->drpServers[s]) && + !serverSeemsDown(&pCB->drpServers[s])) { + drpServer = &pCB->drpServers[s]; + + returnValue = tryServer(pCB, drpServer); + if (returnValue == kDrpServiceOk) { + if (pCB->debugEnabled) + pCB->logMessage(pCB->shellData, kLog_Info, + kLogMessage_OneString, + "successfully retried server", + NULL); + break; + } + } + } + + /* we didn't find any dynamos that work; tell the HTTP server + * to fail over, if possible. + */ + if (returnValue != kDrpServiceOk) + returnValue = kDrpServiceFailover; + } + + + return returnValue; +} + +/** + * drpService_route + * Use a deterministic algorithm to route to determine the DRP server with + * which to communicate to service the current request; contact that + * server and use it to complete service. + * + * The selection algorithm uses a string hash value plus the two high-order + * octets in the client IP address. The latter adjustment is done as + * a way to better distribute the load amongst the servers. Only the + * high-order octets are used because AOL (and possibly other) clients can + * shift IP addresses between requests, but it is extremely unlikely that + * they will shift between B-class networks. + * + * In case of server failure the next working server in the server table + * is used instead. This fallback has a window where two requests that + * should go to the same server will go to different servers if the + * selected server should fail or return to service between requests. + * For Ad Station's use this is felt to be acceptable. + * + * return: 0 == success; !0 == failure + */ +static DrpServiceStatus drpService_route(drpContextBlock * pCB) +{ + int hashValue; + int firstServerNum; + int serverNum; + growBuffer buf; + int returnValue = -1; + int octetValue = 0; + int ipValue = 0; + int dotCount = 0; + + /* no servers, no routing. + */ + if (pCB->numDrpServers == 0) { + pCB->logMessage(pCB->shellData, kLog_Error, + kLogMessage_NoDRPServerAvailable, NULL, NULL); + return kDrpServiceNoServer; + } + + if (createGrowBuffer(&buf, 1024) == NULL) + return kDrpServiceNoMemory; /* memory allocation failure */ + + /* calculate a hash value for the User-Agent field, if known + */ + if (getShellParameter(pCB, kUserAgent, &buf) != 0) + hashValue = 0; + else + hashValue = getStringHashValue(buf.buffer); + + /* adjust the hash value using the 2 high-order bytes of the IP address + * for better load balancing. + */ + if (getShellParameter(pCB, kRemoteAddr, &buf) == 0) { + char *p = &buf.buffer[0]; + + /* parse the first two octets of the dotted IP address into a value. + */ + while (*p != '\0') { + if ((*p >= '0') && (*p <= '9')) + octetValue = (octetValue * 10) + (*p - '0'); + else if (*p == '.') { + ipValue = (ipValue << 8) + octetValue; + if (++dotCount == 2) /* only first two octets */ + break; + octetValue = 0; + } + p++; + } + + hashValue += ipValue; + } + + /* use the hash to determine the first server to try. + */ + serverNum = firstServerNum = hashValue % pCB->numDrpServers; + + for (;;) { + + /* if the server is thought to be responding, try it. + */ + if (pCB->drpServers[serverNum].probability != 0) { + returnValue = tryServer(pCB, &pCB->drpServers[serverNum]); + if (returnValue == 0) /* request went through */ + goto cleanup; + } + + /* try the next server in the table + */ + serverNum = (serverNum + 1) % pCB->numDrpServers; + + /* if we've tried all servers in the table, we're SOL. + */ + if (serverNum == firstServerNum) { + pCB->logMessage(pCB->shellData, kLog_Error, + kLogMessage_NoDRPServerAvailable, NULL, NULL); + goto cleanup; + } + } + + cleanup: + destroyGrowBuffer(&buf); + return returnValue; +} + +/** + * tryServer + * Attempts to service the request with the given server, adjusting + * the server probabilities if the request fails. + * return: 0 == success; !0 == failure + */ +static DrpServiceStatus tryServer(drpContextBlock * pCB, + drpServerRecord * drpServer) +{ + int returnValue; + + setCurrentServer(pCB, drpServer); + + /* drpService_server actually attempts the service */ + returnValue = drpService_server(pCB); + + /* if the attempt failed, log it and return. + */ + if (returnValue != 0) { + char portString[8]; + struct in_addr *inAddr; + + sprintf(portString, "%d", drpServer->port); + inAddr = (struct in_addr *) &drpServer->inetaddr; + pCB->logMessage(pCB->shellData, kLog_Warn, + kLogMessage_DRPServerUnavailable, + inet_ntoa(*inAddr), portString); + /* + * mark server as unavailable, restart loop and + * factor this server's unavailability into random number range + */ + if (!gRetryServerAfterFailure) { + /* + * Don't do this twice - some of the error conditions already do this + * apparently. + */ + if (serverActive(drpServer)) { + markServerInactive(drpServer); + pCB->totalProb -= drpServer->probability; + } + } + returnValue = kDrpServiceError; + } + + return returnValue; +} + +/** + * drpService_server + * Use the current server to service the current request + * return: 0 == success; !0 == failure (details in pCB->serviceStatus) + */ +static DrpServiceStatus drpService_server(drpContextBlock * pCB) +{ + int returnValue = kDrpServiceOk; + +#ifdef _CPOOL + connectionPool *pool; +#endif + + /* If we think this server is down we will return a failure */ + if (serverSeemsDown(pCB->currentServer)) { + return kDrpServiceFailover; + } + + if (!connectedToCurrentServer(pCB)) { + +#ifdef _CPOOL + /* Hold on to the pool pointer in case we fail to connect + to this server compeletely in which case + pCB->currentServer will be set to NULL. + */ + pool = pCB->currentServer->pool; + returnValue = pooledConnectToCurrentServer(pCB); +#else + returnValue = connectToCurrentServer(pCB); +#endif + + if (returnValue) { + /* NB: don't log error; connectToCurrentServer will have done so */ + goto DRP_SVC_SERVER_EXIT; + } + } + + returnValue = sendBeginRequest(pCB); + + if (!pCB->isLoggedRequest) { + while ((pCB->serviceStatus < kServiceComplete) + && (returnValue == 0)) { + returnValue = handleDrpServerRequest(pCB); + } + } + /* + * We don't get any replies here + */ + else + pCB->serviceStatus = kServiceComplete; + + DRP_SVC_SERVER_EXIT: + +#ifdef _CPOOL + + /* Unless the Connection Pool is disabled, or the checkout + operation timed out, a connection has to be checked back + into the connection pool. + */ + if (gCP_Enabled && (returnValue != kCP_OperationTimedOut)) { + int result; + + if (pCB->currentServer) + result = checkinCP(pCB->currentServer->pool, + pCB->currentServer->sock); + /* Case where the current server has been set to + NULL + */ + else + result = checkinCP(pool, kInvalidSocket); + + switch (result) { + case kCP_CheckedIn:{ + if (pCB->currentServer) + pCB->currentServer->sock = kInvalidSocket; +/* + if (pCB->debugEnabled) { + char buf[100]; + sprintf(buf, "Checked In: pool %x : Available in pool = %d", + pool, + getAvailableCP(pool)); + pCB->logMessage(pCB->shellData, + kLog_Info, + kLogMessage_OneString, + buf, + NULL); + } +*/ + break; + } + case kCP_OperationTimedOut:{ +/* + if (pCB->debugEnabled) { + char buf[100]; + sprintf(buf, "Check In timed out: pool %x", pool); + pCB->logMessage(pCB->shellData, + kLog_Info, + kLogMessage_OneString, + buf, + NULL); + } +*/ + break; + } + case kCP_Full:{ +/* + if (pCB->debugEnabled) { + char buf[100]; + sprintf(buf, "Connection pool full: %x", pool); + pCB->logMessage(pCB->shellData, kLog_Info, + kLogMessage_OneString, + buf, + NULL); + } +*/ + break; + } + } + } +#endif + + return returnValue; +} + + +/** + * connectedToCurrentServer + * Determine whether this execution context has an active socket + * connection to the context block's current DRP server + * return: 0 == NOT connected; !0 == connected + */ +static int connectedToCurrentServer(drpContextBlock * pCB) +{ + int returnValue = 0; /* assume not */ + + if (pCB->currentServer && (pCB->currentServer->sock != kInvalidSocket)) { + fd_set checkSet; + int nfds; + struct timeval timeout; + + nfds = ((int) pCB->currentServer->sock) + 1; + + timeout.tv_sec = 0; + timeout.tv_usec = 0; + + FD_ZERO(&checkSet); + FD_SET(pCB->currentServer->sock, &checkSet); + if (select(nfds, &checkSet, NULL, NULL, &timeout)) { + /* socket has data ready to read; this is bad -- either we're out + of synch with server on the DRP protocol, or the conn has been + dropped by the server -- in either case, we should close it */ + closesocket(pCB->currentServer->sock); + pCB->currentServer->sock = kInvalidSocket; +/* + if (pCB->debugEnabled) { + char buf[256]; + sprintf(buf,"Closed bad connection to: %d.%d.%d.%d sock=%d", + pCB->currentServer->inetaddr & 0xff, + (pCB->currentServer->inetaddr >> 8) & 0xff, + (pCB->currentServer->inetaddr >> 16) & 0xff, + (pCB->currentServer->inetaddr >> 24) & 0xff, + pCB->currentServer->sock); + pCB->logMessage(pCB->shellData, kLog_Info, + kLogMessage_OneString, buf, NULL); + } +*/ + } else { + returnValue = 1; + } + } + + return returnValue; +} + + +#ifdef _CPOOL +/** + * pooledConnectToCurrentServer + * Establish a socket connection to the context block's current DRP server, + * or retrieve an existing socket connection from the connection pool. + * Note that this can block if the number of sockets managed by the + * connection pool exceeds + * return: 0 == success; !0 == failure + */ +static int pooledConnectToCurrentServer(drpContextBlock * pCB) +{ + int checkOutResult; + + /* If the connection pool is enabled first try to check + out a socket from the pool. + */ + if (gCP_Enabled) { + + gDebugInfo.numWaitingOnPool++; + checkOutResult = checkoutCP(pCB->currentServer->pool, + &(pCB->currentServer->sock)); + gDebugInfo.numWaitingOnPool--; + + switch (checkOutResult) { + case kCP_CheckedOut:{ + if (connectedToCurrentServer(pCB)) { +/* + if (pCB->debugEnabled) { + char buf[100]; + sprintf(buf, "Checked Out: pool %x : Available in pool = %d", + pCB->currentServer->pool, + getAvailableCP(pCB->currentServer->pool)); + pCB->logMessage(pCB->shellData, + kLog_Info, + kLogMessage_OneString, + buf, + NULL); + } +*/ + return 0; + } else { + /* We either got an invalid socket, or one that no + longer applies to this server. + */ + pCB->currentServer->sock = kInvalidSocket; + break; + } + } + case kCP_OperationTimedOut:{ + /* An attempt to get a socket from the connection pool was + timed out so we want to note that this is a sign that the + server seems to be down. + */ + + if (pCB->debugEnabled) { + char buf[100]; + sprintf(buf, "Check Out timed out: pool %x", + pCB->currentServer->pool); + pCB->logMessage(pCB->shellData, kLog_Info, + kLogMessage_OneString, buf, NULL); + } + noteDrpServerSeemsDown(pCB); + return kCP_OperationTimedOut; + } + } + } + /* + Where we actually attempt to connect. + */ + return connectToCurrentServer(pCB); +} +#endif + +/** + * connectToCurrentServer + * Establish a socket connection to the context block's current DRP server + * return: 0 == success; !0 == failure + */ +static int connectToCurrentServer(drpContextBlock * pCB) +{ + int returnValue = 0; + int onFlag = 1; + struct sockaddr_in addr; + time_t timeBefore = 0; + +#ifdef DEBUG + { + char buf[64]; + sprintf(buf, "max connect timeout is %d", pCB->maxConnectTimeout); + pCB->logMessage(pCB->shellData, kLog_Info, kLogMessage_OneString, + buf, NULL); + } +#endif + + timeBefore = time(NULL); + + gDebugInfo.numWaitingToConnect++; + + trysocketagain: + pCB->currentServer->sock = socket(AF_INET, SOCK_STREAM, 0); + if (pCB->currentServer->sock == kInvalidSocket) { + char errorNumber[12]; + + /* couldn't create a socket */ + sprintf(errorNumber, "%d", net_error()); + pCB->logMessage(pCB->shellData, kLog_Error, + kLogMessage_CannotCreateSocket, errorNumber, NULL); + returnValue = -1; + goto CONNECT_CURRENT_EXIT; + } else { + /* turn on keep-alive; ignore result */ + setsockopt(pCB->currentServer->sock, SOL_SOCKET, SO_KEEPALIVE, + (char *) &onFlag, sizeof(onFlag)); + /* turn off the nagle-algorithm, so that the system will send + teeny-weeny packets without farting around */ + setsockopt(pCB->currentServer->sock, IPPROTO_TCP, TCP_NODELAY, + (char *) &onFlag, sizeof(onFlag)); + + addr.sin_family = AF_INET; + addr.sin_port = htons(pCB->currentServer->port); + addr.sin_addr.s_addr = pCB->currentServer->inetaddr; + + tryagain: + returnValue = connect(pCB->currentServer->sock, + (struct sockaddr *) &addr, + sizeof(struct sockaddr)); + if (returnValue) { + char errorNumber[12]; + + int errorNum = net_error(); + if (errorNum == EINTR) + goto tryagain; + + if (errorNum == ETIMEDOUT) { + closesocket(pCB->currentServer->sock); + pCB->currentServer->sock = kInvalidSocket; + + if (pCB->debugEnabled) { + char buf[256]; + sprintf(buf, + "got ETIMEDOUT on connect to server: %lu.%lu.%lu.%lu sock=%d", + pCB->currentServer->inetaddr & 0xff, + (pCB->currentServer->inetaddr >> 8) & 0xff, + (pCB->currentServer->inetaddr >> 16) & 0xff, + (pCB->currentServer->inetaddr >> 24) & 0xff, + pCB->currentServer->sock); + pCB->logMessage(pCB->shellData, kLog_Info, + kLogMessage_OneString, buf, NULL); + } + if ((timeBefore > 0) && + (time(NULL) > (timeBefore + pCB->maxConnectTimeout))) { + noteDrpServerSeemsDown(pCB); + return kDrpServiceFailover; + } + goto trysocketagain; + } + + /* couldn't connect to current DRP server */ + sprintf(errorNumber, "%d", net_error()); + + if (!gRetryServerAfterFailure) { + /* Be sure not to do this twice for the same server! */ + if (serverActive(pCB->currentServer)) { + markServerInactive(pCB->currentServer); + pCB->totalProb -= pCB->currentServer->probability; + } + } + + /* + * Need to nuke this socket or else we'll wrongly think we are still + * connected! + */ + closesocket(pCB->currentServer->sock); + pCB->currentServer->sock = kInvalidSocket; + + pCB->logMessage(pCB->shellData, kLog_Error, + kLogMessage_CannotConnect, errorNumber, NULL); + pCB->currentServer = NULL; + goto CONNECT_CURRENT_EXIT; + } +/* + else if (pCB->debugEnabled) { + char buf[256]; + sprintf(buf,"Created new connection to: %d.%d.%d.%d sock=%d", + pCB->currentServer->inetaddr & 0xff, + (pCB->currentServer->inetaddr >> 8) & 0xff, + (pCB->currentServer->inetaddr >> 16) & 0xff, + (pCB->currentServer->inetaddr >> 24) & 0xff, + pCB->currentServer->sock); + pCB->logMessage(pCB->shellData, kLog_Info, + kLogMessage_OneString, buf, NULL); + } +*/ + } + + CONNECT_CURRENT_EXIT: + + gDebugInfo.numWaitingToConnect--; + + return returnValue; +} + + +/** + * sendBeginRequest + * Send BeginRequest packet to DRP server to start DRP service cycle + * return: 0 == success; !0 == failure + */ +static DrpServiceStatus sendBeginRequest(drpContextBlock * pCB) +{ + int returnValue = kDrpServiceOk; + drpByte beginType; + drpByte _0 = 0; + + gDebugInfo.numSendingRequest++; + + /* + * Use a different header byte if we are logging, not servicing + * this request + */ + if (pCB->isLoggedRequest) + beginType = kBeginLogRequest; + else + beginType = kBeginRequest; + + returnValue = sendByte(pCB, pCB->currentServer->sock, &beginType); + + /* also send: Method, PathInfo, ContentLength, PathTranslated, + Querystring, RequestURI, ServletPath, and all Headers */ + + /* method */ + if (returnValue == kDrpServiceOk) + returnValue = sendParameter(pCB, kMethod, NULL); + + /* path-info */ + if (returnValue == kDrpServiceOk) + returnValue = sendParameter(pCB, kPathInfo, NULL); + + /* content-length */ + if (returnValue == kDrpServiceOk) + returnValue = sendParameter(pCB, kContentLength, NULL); + + /* content-type */ + if (returnValue == kDrpServiceOk) + returnValue = sendParameter(pCB, kContentType, NULL); + + /* path-translated */ + if (returnValue == kDrpServiceOk) + returnValue = sendParameter(pCB, kPathTranslated, NULL); + + /* query-string */ + if (returnValue == kDrpServiceOk) + returnValue = sendParameter(pCB, kQueryString, NULL); + + /* request-uri */ + if (returnValue == kDrpServiceOk) + returnValue = sendParameter(pCB, kRequestURI, NULL); + + /* servlet-path */ + if (returnValue == kDrpServiceOk) + returnValue = sendParameter(pCB, kServletPath, NULL); + + /* + * In 3.0, we only send these values for logged requests. Turns out + * to be pretty common to want them and fairly slow to make the drp + * server come back to get them. Just send them all then.. + */ + if (returnValue == kDrpServiceOk) + returnValue = sendParameter(pCB, kScheme, NULL); + if (returnValue == kDrpServiceOk) + returnValue = sendParameter(pCB, kRemoteAddr, NULL); + if (returnValue == kDrpServiceOk) + returnValue = sendParameter(pCB, kServerName, NULL); + if (returnValue == kDrpServiceOk) + returnValue = sendParameter(pCB, kServerPort, NULL); + + /* + * In D4.0, I'm sending this as well. Now all of the headers should + * be there to avoid unnecessary GET_PARAMETERS calls + */ + if (returnValue == kDrpServiceOk) + returnValue = sendParameter(pCB, kProtocol, NULL); + + /* all headers */ + if (returnValue == kDrpServiceOk) + returnValue = handleGetAllHeaders(pCB); + + /* terminate NV-pair list */ + if (returnValue == kDrpServiceOk) + returnValue = sendByte(pCB, pCB->currentServer->sock, &_0); + + /* also send: block of data from agent (browser), if available */ + if (returnValue == kDrpServiceOk && !pCB->isLoggedRequest) { + int result; + + result = + pCB->readFromAgent(pCB->shellData, &pCB->ioBuffer, + pCB->ioBuffer.avail); + if (result == 0) { + returnValue = sendLong(pCB, pCB->currentServer->sock, + (drpInt *) & pCB->ioBuffer.used); + if (returnValue == kDrpServiceOk) + returnValue = sendBuffer(pCB, pCB->currentServer->sock, + &pCB->ioBuffer); + } else { + drpInt _0L = (drpInt) 0; + returnValue = sendLong(pCB, pCB->currentServer->sock, &_0L); + } + } + + if (returnValue == 0) { + returnValue = send_flush(pCB, pCB->currentServer->sock, 0); + } + + gDebugInfo.numSendingRequest--; + + return returnValue; +} + + +/** + * sendParameter + * find the value for a requested parameter and send the response to + * DRP server. (name-value pair is sent to DRP server, so this routine + * can be invoked several times to construct a DRP name-value pair list + * which must be terminated by the caller.) + * iParameter: if (0 < iParameter < kDefinedPlaceholder), the parameter + * sought is defined string iParameter; otherwise, iIdentParam + * iIdentParam: used as lookup paramete if iParameter does not correspond + * to a known defined string value + * return: 0 == success; !0 == failure + */ +static DrpServiceStatus +sendParameter(drpContextBlock * pCB, drpByte iDefinedParam, + drpIdentifier * iIdentParam) +{ + int returnValue = 0; + drpIdentifier paramName; + drpIdentifier *paramPtr = NULL; + drpByte _1 = 1; + + if ((iDefinedParam > 0) && (iDefinedParam < kDefinedPlaceholder)) { + /* we're looking up a defined-string parameter, iDefinedParam */ + + paramName.hasIndex = 0; + paramName.name.type = kDefined; + paramName.name.value.defined = iDefinedParam; + paramPtr = ¶mName; + } else if (iIdentParam) { + /* we're looking up a string parameter, iIdentParam */ + paramPtr = iIdentParam; + } else { + /* no good lookup parameter passed to us */ + returnValue = -1; + } + + returnValue = + pCB->getParameter(pCB->shellData, paramPtr, &pCB->ioBuffer2); + if (returnValue == 0) { + /* send "1" (indicating parameter pair follows) */ + returnValue = sendByte(pCB, pCB->currentServer->sock, &_1); + /* send the defined-string parameter name */ + if (returnValue == 0) + returnValue = + sendIdentifier(pCB, pCB->currentServer->sock, paramPtr); + /* send the parameter value */ + if (returnValue == 0) { + if (paramDemandsIntResponse((*paramPtr))) { + pCB->ioBuffer2.buffer[pCB->ioBuffer2.used] = kChar_Null; + returnValue = + sendIntTLiteral(pCB, pCB->currentServer->sock, + atol(pCB->ioBuffer2.buffer)); + } else { + returnValue = + sendAsciiTLiteral(pCB, pCB->currentServer->sock, + &pCB->ioBuffer2); + } + } + } + + return returnValue; +} + + +/** + * handleDrpServerRequest + * Receive and handle (i.e. respond appropriately to) one DRP packet + * from the current DRP server + * return: 0 == success; !0 == failure + * also: pCB->serviceStatus may change to reflect checkpoints in + * DRP cycle + */ +static DrpServiceStatus handleDrpServerRequest(drpContextBlock * pCB) +{ + int returnValue = kDrpServiceOk; + drpByte packetType; + + gDebugInfo.numWaitingForResponse++; + returnValue = recvByte(pCB, pCB->currentServer->sock, &packetType); + + if (returnValue == 0) { + switch (packetType) { + case kReply: + returnValue = handleReplyPacket(pCB); + break; + case kGetParameters: + returnValue = handleGetParameters(pCB); + break; + case kReadDataStream: + returnValue = handleReadData(pCB); + break; + + default: + /* unknown/unexpected packet type */ + returnValue = kDrpServiceProtocolError; + { + char packetTypeNumber[128]; + sprintf(packetTypeNumber, "value=%d status=%d", packetType, + pCB->serviceStatus); + pCB->logMessage(pCB->shellData, kLog_Error, + kLogMessage_InternalProtoError, + packetTypeNumber, NULL); + } + break; + } + } + gDebugInfo.numWaitingForResponse--; + return returnValue; +} + + +/** + * handleReplyPacket + * Receive and handle reply packet information (may include HTTP status + * information, reply headers, response data, etc); reply with success + * status to DRP server if requested by server. + * return: 0 == success; !0 == failure + */ +static DrpServiceStatus handleReplyPacket(drpContextBlock * pCB) +{ + /* This is error code for reads from dynamo */ + int returnValue = kDrpServiceOk; + drpByte sendHeader = 0; + drpByte flushData = 0; + drpByte closeData = 0; + drpByte endRequest = 0; + drpByte replyExpected = 0; + /* This has the return value of writes to the client */ + int result = 0; + drpByte _0 = 0; + drpByte _1 = 1; + + /* receive reply flags - should we flush, close, etc */ + returnValue = recvByte(pCB, pCB->currentServer->sock, &sendHeader); + if (returnValue == kDrpServiceOk) + returnValue = recvByte(pCB, pCB->currentServer->sock, &flushData); + if (returnValue == kDrpServiceOk) + returnValue = recvByte(pCB, pCB->currentServer->sock, &closeData); + if (returnValue == kDrpServiceOk) + returnValue = recvByte(pCB, pCB->currentServer->sock, &endRequest); + if (returnValue == kDrpServiceOk) + returnValue = + recvByte(pCB, pCB->currentServer->sock, &replyExpected); + + if ((sendHeader) && (returnValue == kDrpServiceOk)) { + /* also receive and handle header info */ + result = handleHeader(pCB); + } + + if (returnValue == kDrpServiceOk) { + /* also receive and send output data block */ + if (result == 0) { + returnValue = handleWriteData(pCB); + if (returnValue != kDrpServiceOk) { + result = -1; + /* + * Don't let this error cause the server to think that the request + * failed. + */ + returnValue = kDrpServiceOk; + /* + * We had to close the socket so the protocol is done. + */ + if (pCB->currentServer->sock == kInvalidSocket) { + pCB->serviceStatus = kServiceComplete; + return returnValue; + } + } + } + } + + /* handle miscellaneous reply flags */ + if (result == 0 && flushData) + result = handleFlush(pCB); + if (result == 0 && closeData) + result |= handleClose(pCB); + if (replyExpected) { + /* send 1 (success) or 0 (failure) in reply to DRP server */ + returnValue = sendByte(pCB, pCB->currentServer->sock, + ((result == 0) ? &_1 : &_0)); + if (returnValue == 0) + /* force the send */ + returnValue = send_flush(pCB, pCB->currentServer->sock, 0); + } + if (endRequest) { + + pCB->serviceStatus = kServiceComplete; + + if (endRequest == 2) { + closesocket(pCB->currentServer->sock); + pCB->currentServer->sock = kInvalidSocket; + } +#ifdef _CPOOL + if (gCP_Enabled) { + + if (endRequest == 2) { + /* + This is an incompatable configuration - we are pooling + connections on the CM side, but a DRPServer is closing + connections. + Therefore output an error message and disable pooling. + */ + if (pCB->debugEnabled) + pCB->logMessage(pCB->shellData, kLog_Info, + kLogMessage_OneString, + "DRPServer dropped connection when connection pool was enabled", + NULL); + gCP_Enabled = 0; + } + } +#endif /* _CPOOL */ + } + return returnValue; +} + + +/** + * handleGetParameters + * Satisfy a Get-Parameters DRP server request in progress. This routine + * (with subroutines) receives the DRP identifier-list from the drp server + * and responds with a full DRP name-value pair list (with terminator). + * return: 0 == success; !0 == failure + */ +static DrpServiceStatus handleGetParameters(drpContextBlock * pCB) +{ + int returnValue = kDrpServiceOk; + drpByte identDelim; + drpByte _0 = 0; + + if (pCB->serviceStatus < kExaminingRequest) + pCB->serviceStatus = kExaminingRequest; + /* as long as identDelim byte is 1, we've got more identifiers to + read from the list sent by the DRP server */ + returnValue = recvByte(pCB, pCB->currentServer->sock, &identDelim); + while ((identDelim == 1) && (returnValue == 0)) { + drpIdentifier paramName; + + returnValue = + recvIdentifier(pCB, pCB->currentServer->sock, ¶mName, + &pCB->ioBuffer); + if (returnValue == kDrpServiceOk) { + if (paramName.name.type == kDefined) { + /* special handling of defined-string requested parameters: + these parameters are divided into four groups; whenever a request + is made for a single element from any group, the values for + the entire group should be sent in response (the first group + is to be sent with the begin-request packet) */ + + switch (paramName.name.value.defined) { + case kMethod: + case kPathInfo: + case kContentLength: + case kPathTranslated: + case kQueryString: + case kRequestURI: + case kServletPath: + case kHeaders: + /* group 1 */ + returnValue = sendParameter(pCB, kMethod, NULL); + if (returnValue == kDrpServiceOk) + returnValue = sendParameter(pCB, kPathInfo, NULL); + if (returnValue == kDrpServiceOk) + returnValue = + sendParameter(pCB, kContentLength, NULL); + if (returnValue == kDrpServiceOk) + returnValue = + sendParameter(pCB, kPathTranslated, NULL); + if (returnValue == kDrpServiceOk) + returnValue = + sendParameter(pCB, kQueryString, NULL); + if (returnValue == kDrpServiceOk) + returnValue = + sendParameter(pCB, kRequestURI, NULL); + if (returnValue == kDrpServiceOk) + returnValue = + sendParameter(pCB, kServletPath, NULL); + if (returnValue == kDrpServiceOk) + returnValue = handleGetAllHeaders(pCB); + break; + + case kContentType: + case kAuthType: + /* group 2 */ + returnValue = sendParameter(pCB, kContentType, NULL); + if (returnValue == kDrpServiceOk) + returnValue = sendParameter(pCB, kAuthType, NULL); + break; + + case kRemoteAddr: + case kRemoteHost: + case kRemoteUser: + /* group 3 */ + returnValue = sendParameter(pCB, kRemoteAddr, NULL); + if (returnValue == kDrpServiceOk) + returnValue = + sendParameter(pCB, kRemoteHost, NULL); + if (returnValue == kDrpServiceOk) + returnValue = + sendParameter(pCB, kRemoteUser, NULL); + break; + + case kProtocol: + case kServerName: + case kServerPort: + case kScheme: + /* group 4 */ + returnValue = sendParameter(pCB, kProtocol, NULL); + if (returnValue == kDrpServiceOk) + returnValue = + sendParameter(pCB, kServerName, NULL); + if (returnValue == kDrpServiceOk) + returnValue = + sendParameter(pCB, kServerPort, NULL); + if (returnValue == kDrpServiceOk) + returnValue = sendParameter(pCB, kScheme, NULL); + break; + + case kParameters: + /* will never be requested by DRP 2.01 server */ + break; + + default: /* eh? what's that? */ + break; + } + } else { + /* sendParameter() takes care of sending result back to DRP server, + excluding final terminating 0 byte; passing kDefinedPlaceholder + (an invalid defined string) forces sendParameter to use paramName + as its lookup parameter */ + returnValue = + sendParameter(pCB, kDefinedPlaceholder, ¶mName); + } + } + + returnValue = recvByte(pCB, pCB->currentServer->sock, &identDelim); + } + + /* finish the NV-Pair response */ + if (returnValue == kDrpServiceOk) + returnValue = sendByte(pCB, pCB->currentServer->sock, &_0); + + if (returnValue == kDrpServiceOk) + /* force the send */ + returnValue = send_flush(pCB, pCB->currentServer->sock, 0); + + return returnValue; +} + + +/** + * handleGetAllHeaders + * Satisfy the DRP server's request for all Headers. this routine sends + * a single DRP2 name-value pair for each request header; it does _not_ + * send the terminator for the name-value pair list, so caller must. + * return: 0 == success; !0 == failure + */ +static DrpServiceStatus handleGetAllHeaders(drpContextBlock * pCB) +{ + int returnValue = kDrpServiceOk; + drpByte _1 = 1; + int headerNum = 0; + + do { + returnValue = + pCB->getNthHeader(pCB->shellData, headerNum, &pCB->ioBuffer, + &pCB->ioBuffer2); + if ((pCB->ioBuffer.used > 0) && (returnValue == 0)) { + /* send byte: NV-Pair follows */ + returnValue = sendByte(pCB, pCB->currentServer->sock, &_1); + if (returnValue == 0) { + /* send indexed NV pair: ("headername"[headernum], header-name) */ + returnValue = + sendIntIndexedPair(pCB, pCB->currentServer->sock, + kHeaderName, headerNum, + pCB->ioBuffer.buffer); + /* send byte: NV-Pair follows */ + returnValue = sendByte(pCB, pCB->currentServer->sock, &_1); + if (returnValue == kDrpServiceOk) + /* send indexed NV pair: ("headerval"[headernum], header-val) */ + returnValue = + sendIntIndexedPair(pCB, pCB->currentServer->sock, + kHeaderVal, headerNum, + pCB->ioBuffer2.buffer); + } + } + headerNum++; + } while ((pCB->ioBuffer.used > 0) && (returnValue == kDrpServiceOk)); + + /* do _not_ send 0x00 (NV-Pair terminating byte); caller will handle */ + + return returnValue; +} + + +/** + * handleReadData + * Satisfy a Read-Data DRP server request in progress. This routine + * receives the maximum requested bytes value (4 bytes) from the drp + * server, and sends the data packet with agent data (or failure indicator). + * return: 0 == success; !0 == failure + */ +static DrpServiceStatus handleReadData(drpContextBlock * pCB) +{ + int returnValue = kDrpServiceOk; + size_t length; + drpByte _1 = 1; + drpByte _0 = 0; + size_t bytesToPipe = 0; + + if (pCB->serviceStatus < kServicingRequest) + pCB->serviceStatus = kServicingRequest; + returnValue = + recvLong(pCB, pCB->currentServer->sock, (drpInt *) & length); + if ((length > 0) && (returnValue == kDrpServiceOk)) { + int result; + + /* NB: don't propagate a non-zero return from readFromAgent as an + error return from handleReadData (which will be interpreted as a + DRP-server related error) */ + + bytesToPipe = MIN(length, pCB->ioBuffer.avail); + pCB->ioBuffer.used = 0; + result = pCB->readFromAgent(pCB->shellData, &pCB->ioBuffer, + bytesToPipe); + if (result == 0) { + returnValue = sendByte(pCB, pCB->currentServer->sock, &_1); + if (returnValue == kDrpServiceOk) + returnValue = sendLong(pCB, pCB->currentServer->sock, + (drpInt *) & pCB->ioBuffer.used); + if (returnValue == kDrpServiceOk) + returnValue = sendBuffer(pCB, pCB->currentServer->sock, + &pCB->ioBuffer); + } else { + /* send failure byte */ + sendByte(pCB, pCB->currentServer->sock, &_0); + } + } else { + /* send failure byte */ + sendByte(pCB, pCB->currentServer->sock, &_0); + } + + if (returnValue == kDrpServiceOk) { + returnValue = send_flush(pCB, pCB->currentServer->sock, 0); + } + + return returnValue; +} + + +/** + * handleWriteData + * Satisfy a Write-Data DRP server request in progress. This routine + * receives the data packet (length and data) to be written to the agent + * from the DRP server, and attempts to write that data to the agent. + * return: 0 == success; !0 == failure + */ +static DrpServiceStatus handleWriteData(drpContextBlock * pCB) +{ + int returnValue = kDrpServiceOk; + size_t length; + drpByte success = 1; + size_t bytesPiped = 0; + size_t bytesToPipe = 0; + + if (pCB->serviceStatus < kServicingRequest) + pCB->serviceStatus = kServicingRequest; + returnValue = + recvLong(pCB, pCB->currentServer->sock, (drpInt *) & length); + if ((length > 0) && (returnValue == kDrpServiceOk)) { + if (pCB->statusSetByServer && (!pCB->statusSentToAgent)) { + returnValue = doSendHeader(pCB); + /* + * We must complete the request even if sending the headers fails + * In particular, we have to read the data from the client or else + * the protocol will get screwed up. + */ + if (returnValue != kDrpServiceOk) { + success = 0; + returnValue = kDrpServiceOk; + } + } + while ((bytesPiped < length) && (returnValue == kDrpServiceOk)) { + bytesToPipe = MIN(length - bytesPiped, pCB->ioBuffer.avail); + returnValue = recvBuffer(pCB, pCB->currentServer->sock, + &pCB->ioBuffer, bytesToPipe); + if (returnValue == kDrpServiceOk) { + /* NB: don't propagate a non-zero return from writeToAgent as an + error return from handleWriteData (which will be interpreted as + a DRP-server related error) */ + int result; + + result = pCB->writeToAgent(pCB->shellData, &pCB->ioBuffer, + bytesToPipe); + if (result != 0) { + success = 0; + /* + * Return an error so that this gets reported to dynamo + * after the request. + */ + returnValue = kDrpServiceError; + + /* + * Close the socket right here. This will give the immediate + * feedback to the DRP thread regardless of whether or not + * we are doing "dropConnectionAfterRequest". It also spares + * us from having to finish reading all of the data for this + * request (which has been aborted by the user). It does have + * the overhead that we'll need to create a new socket for + * the next request but that is not a big hit + */ + closesocket(pCB->currentServer->sock); + pCB->currentServer->sock = kInvalidSocket; + break; /* out of while loop */ + } + } else { + /* recv (from server) not successful */ + success = 0; + break; /* out of while loop */ + } + bytesPiped += bytesToPipe; + } + } else { + success = 0; + } + + return returnValue; +} + + +/** + * handleFlush + * Satisfy a Flush-Data-Stream DRP server request in progress. + * return: 0 == success; !0 == failure + */ +static DrpServiceStatus handleFlush(drpContextBlock * pCB) +{ + int returnValue = kDrpServiceOk; + drpByte success = 1; + int result; + + /* NB: don't propagate a non-zero return from flushData as an + error return from handleFlush (which will be interpreted as a + DRP-server related error) */ + + result = pCB->flushData(pCB->shellData); + if (result != 0) + success = 0; + + return returnValue; +} + + +/** + * handleClose + * Satisfy a Close-Data-Stream DRP server request in progress. + * return: 0 == success; !0 == failure + */ +static DrpServiceStatus handleClose(drpContextBlock * pCB) +{ + int returnValue = kDrpServiceOk; + drpByte success = 1; + int result; + + /* NB: don't propagate a non-zero return from closeData as an + error return from handleClose (which will be interpreted as a + DRP-server related error) */ + + result = pCB->closeData(pCB->shellData); + if (result != 0) + success = 0; + + return returnValue; +} + + +/** + * handleHeader + * Satisfy a Send-Header DRP server request in progress. This routine + * (with subroutines) receives status code and message and response + * headers, and distributes headers and status info to agent. + * return: 0 == success; !0 == failure + */ +static DrpServiceStatus handleHeader(drpContextBlock * pCB) +{ + int returnValue = kDrpServiceOk; + drpByte shouldSend = 0; + drpByte success = 1; + + returnValue = + recvLong(pCB, pCB->currentServer->sock, &pCB->statusCode); + if (returnValue == kDrpServiceOk) { + returnValue = recvTLiteral(pCB, pCB->currentServer->sock, + &pCB->statusMesg, &pCB->statusBuffer); + } + if (returnValue == kDrpServiceOk) + returnValue = recvByte(pCB, pCB->currentServer->sock, &shouldSend); + + if (pCB->shellExpectsHeaderPairs) { + returnValue = dispatchHeaders(pCB); + } else { + returnValue = batchHeaders(pCB); + } + + pCB->statusSetByServer = 1; + + if (shouldSend && (returnValue == kDrpServiceOk)) { + returnValue = doSendHeader(pCB); + } + + if (returnValue != kDrpServiceOk) + success = 0; + + return returnValue; +} + + +/** + * dispatchHeaders + * Retrieve header pairs from DRP server and dispatch them to shell (for + * those shells that expect headers to come one pair at a time) + * return: 0 == success; !0 == failure + */ +static DrpServiceStatus dispatchHeaders(drpContextBlock * pCB) +{ + int returnValue = kDrpServiceOk; + drpByte pairDelim; + + returnValue = recvByte(pCB, pCB->currentServer->sock, &pairDelim); + while ((pairDelim == 1) && (returnValue == 0)) { + drpIdentifier headerName; + drpTLiteral headerVal; + + pCB->ioBuffer.used = 0; /* "clear" ioBuffer */ + returnValue = + recvIdentifier(pCB, pCB->currentServer->sock, &headerName, + &pCB->ioBuffer); + if (returnValue == kDrpServiceOk) { + pCB->ioBuffer2.used = 0; /* "clear" ioBuffer2 */ + returnValue = + recvTLiteral(pCB, pCB->currentServer->sock, &headerVal, + &pCB->ioBuffer2); + if (returnValue == kDrpServiceOk) { + pCB->headers.used = 0; /* "clear" headers buffer */ + identToAscii(pCB->definedStringLength, + pCB->definedStringToAscii, pCB->shellData, + &headerName, &pCB->headers); + pCB->headers2.used = 0; /* "clear" headers2 buffer */ + tliteralToAscii(pCB->definedStringLength, + pCB->definedStringToAscii, pCB->shellData, + &headerVal, &pCB->headers2); + returnValue = + pCB->setResponseHeader(pCB->shellData, &pCB->headers, + &pCB->headers2); + } + } + if (returnValue == kDrpServiceOk) + returnValue = + recvByte(pCB, pCB->currentServer->sock, &pairDelim); + } + + return returnValue; +} + + +/** + * batchHeaders + * Dump headers from the DRP server into an ascii buffer (for those shells + * that expect headers to come in one big lump) + * return: 0 == success; !0 == failure + */ +static DrpServiceStatus batchHeaders(drpContextBlock * pCB) +{ + int returnValue = kDrpServiceOk; + drpByte pairDelim; + + returnValue = recvByte(pCB, pCB->currentServer->sock, &pairDelim); + while ((pairDelim == 1) && (returnValue == kDrpServiceOk)) { + drpIdentifier headerName; + drpTLiteral headerVal; + + pCB->ioBuffer.used = 0; /* "clear" ioBuffer */ + returnValue = + recvIdentifier(pCB, pCB->currentServer->sock, &headerName, + &pCB->ioBuffer); + if (returnValue == kDrpServiceOk) { + identToAscii(pCB->definedStringLength, + pCB->definedStringToAscii, pCB->shellData, + &headerName, &pCB->headers); + concatenate(&pCB->headers, kString_HeaderNVDelim); + pCB->ioBuffer.used = 0; /* "clear" ioBuffer */ + returnValue = + recvTLiteral(pCB, pCB->currentServer->sock, &headerVal, + &pCB->ioBuffer); + if (returnValue == kDrpServiceOk) { + tliteralToAscii(pCB->definedStringLength, + pCB->definedStringToAscii, pCB->shellData, + &headerVal, &pCB->headers); + concatenate(&pCB->headers, kString_Newline); + } + } + returnValue = recvByte(pCB, pCB->currentServer->sock, &pairDelim); + } + concatenate(&pCB->headers, kString_Newline); + + return returnValue; +} + + +/** + * identToAscii + * Copy an ascii representation of a DRP Identifier object onto the end + * of the supplied buffer. (Grows buffer as necessary.) + */ +void +identToAscii(DefinedLength_fn iDefinedLength, + DefinedAscii_fn iDefinedAscii, void *pShellData, + const drpIdentifier * iIdent, growBuffer * oBuffer) +{ + /* NB: ignoring index */ + tliteralToAscii(iDefinedLength, iDefinedAscii, pShellData, + &iIdent->name, oBuffer); +} + + +/** + * tliteralToAscii + * Copy an ascii representation of a DRP Typed Literal object onto the end + * of the supplied buffer. (Grows buffer as necessary.) + */ +void +tliteralToAscii(DefinedLength_fn iDefinedLength, + DefinedAscii_fn iDefinedAscii, void *pShellData, + const drpTLiteral * iTLiteral, growBuffer * oBuffer) +{ + size_t result; + size_t c; + + switch (iTLiteral->type) { + case kInteger: + ensureGrowBufferSize_m(oBuffer, (oBuffer->used + 16)); + result = sprintf(oBuffer->buffer + oBuffer->used, "%ld", + iTLiteral->value.integer); + oBuffer->used += result; + break; + case kDefined: + result = iDefinedLength(pShellData, iTLiteral->value.defined); + if (result > 0) { + ensureGrowBufferSize_m(oBuffer, (oBuffer->used + result)); + } + result = sprintf(oBuffer->buffer + oBuffer->used, "%s", + iDefinedAscii(pShellData, + iTLiteral->value.defined)); + oBuffer->used += result; + break; + case kAscii: + ensureGrowBufferSize_m(oBuffer, + (oBuffer->used + iTLiteral->numChars)); + memmove(oBuffer->buffer + oBuffer->used, iTLiteral->value.ascii, + iTLiteral->numChars); + oBuffer->used += iTLiteral->numChars; + oBuffer->buffer[oBuffer->used] = kChar_Null; + break; + case kUnicode: + ensureGrowBufferSize_m(oBuffer, + (oBuffer->used + iTLiteral->numChars)); + for (c = 0; c < iTLiteral->numChars; c++) { + oBuffer->buffer[oBuffer->used++] = + ((char *) iTLiteral->value.unicode)[2 * c + 1]; + } + oBuffer->buffer[oBuffer->used] = kChar_Null; + break; + case kNull: + /* intentional fall-through */ + default: + break; + } +} + + +/** + * doSendHeader + * Send HTTP header information to user agent + * return: 0 == success; !0 == failure + */ +static DrpServiceStatus doSendHeader(drpContextBlock * pCB) +{ + int returnValue = kDrpServiceOk; + + pCB->statusSentToAgent = 1; + + if (pCB->statusMesg.type > kNull) { + pCB->ioBuffer.used = 0; + tliteralToAscii(pCB->definedStringLength, + pCB->definedStringToAscii, pCB->shellData, + &pCB->statusMesg, &pCB->ioBuffer); + } else { + pCB->ioBuffer.buffer[0] = kChar_Null; + pCB->ioBuffer.used = 0; + } + + if (pCB->shellExpectsHeaderPairs) { + returnValue = + pCB->sendHeaderNoBatch(pCB->shellData, pCB->statusCode, + pCB->ioBuffer.buffer, + pCB->ioBuffer.used); + } else { + returnValue = pCB->sendHeaderBatch(pCB->shellData, pCB->statusCode, + pCB->ioBuffer.buffer, + pCB->ioBuffer.used, + pCB->headers.buffer, + pCB->headers.used); + } + + return returnValue; +} + + +/** + * bitcpy32 + * NB: macro, modifies d (destination) in place + * d: destination (4 bytes) + * db: destination offset, in bits + * s: source (4 bytes) + * sb: source offset, in bits + * "copies" up to 32 bits from s (offset sb) to d (offset db) + */ +#define bitcpy32(d,db,s,sb) \ + ((d) |= \ + ((db) > (sb) ? \ + (((long) (s)) << ((db) - (sb))) : \ + (((long) (s)) >> ((sb) - (db))))) + +/** + * bitcpy16 + * NB: macro, modifies d (destination) in place + * d: destination (2 bytes) + * db: destination offset, in bits + * s: source (2 bytes) + * sb: source offset, in bits + * "copies" up to 16 bits from s (offset sb) to d (offset db) + */ +#define bitcpy16(d,db,s,sb) \ + ((d) |= \ + ((db) > (sb) ? \ + (((short) (s)) << ((db) - (sb))) : \ + (((short) (s)) >> ((sb) - (db))))) + + +/** + * getDrpServerInfoFromSid + * From the session-ID stored in pCB, extract the the address and port + * of the DRP server that issued the SID. + * oAddr: will be filled in with address of DRP server (if return is 0) + * oPort: will be filled in with port of DRP server (if return is 0) + * return: 0 == success; !0 == failure + */ +static int +getDrpServerInfoFromSid(drpContextBlock * pCB, unsigned long *oAddr, + unsigned short *oPort) +{ + /* + adapted from Nate-o-rama's documentation of the d3 session id format + (atg.servlet.sessiontracking.SessionManager): + + The generated id's are based on a byte array with + the following format: + bytes 0-3: hash based on counter and start time + bytes 4-7: counter + bytes 8-11: host IP addr + The byte array is then converted to a String. The byte array is + broken down into groups of 5 bits, and each group's value (0-31) is + used to form a character from the character set 'A'-'Z', '0'-'5'. + */ + + int returnValue = kDrpServiceOk; + char addrInts[8]; + char portInts[4]; + int c; + char *id = pCB->sessionID; + + /* DRP server IP address: + convert relevant characters from session ID into array of byte integers */ + for (c = 0; c < 8; c++) { + if ((id[c + 12] >= 'A') && (id[c + 12] <= 'Z')) + addrInts[c] = id[c + 12] - 'A'; + else if ((id[c + 12] >= '0') && (id[c + 12] <= '5')) + addrInts[c] = id[c + 12] - '0' + 26; + else { + char badChar[2]; + char buf[128]; + badChar[0] = id[c + 12]; + badChar[1] = kChar_Null; + sprintf(buf, "(case 1) session id='%s', char='%s'(0x%x)", + pCB->sessionID, badChar, (int) id[c + 12]); + + pCB->logMessage(pCB->shellData, kLog_Warn, + kLogMessage_BadSIDCharacter, buf, NULL); + + if (pCB->debugEnabled) { + drpIdentifier cookieHeaderName; + int result; + cookieHeaderName.hasIndex = 0; + cookieHeaderName.name.type = kAscii; + cookieHeaderName.name.numChars = + strlen(kCookieHeaderName) + 1; + cookieHeaderName.name.value.ascii = kCookieHeaderName; + + result = + pCB->getParameter(pCB->shellData, &cookieHeaderName, + &pCB->ioBuffer); + if (result == 0) { + pCB->ioBuffer.buffer[pCB->ioBuffer.used] = kChar_Null; + sprintf(buf, "cookie header is='%s'", + pCB->ioBuffer.buffer); + pCB->logMessage(pCB->shellData, kLog_Info, + kLogMessage_OneString, buf, NULL); + } else { + pCB->logMessage(pCB->shellData, kLog_Info, + kLogMessage_OneString, + "no cookie header present", NULL); + } + } + returnValue = -1; + } + } + + /* DRP server port: + convert relevant characters from session ID into array of byte integers */ + if (returnValue == 0) + for (c = 0; c < 4; c++) { + if ((id[c + 19] >= 'A') && (id[c + 19] <= 'Z')) + portInts[c] = id[c + 19] - 'A'; + else if ((id[c + 19] >= '0') && (id[c + 19] <= '5')) + portInts[c] = id[c + 19] - '0' + 26; + else { + char badChar[2]; + char buf[128]; + + badChar[0] = id[c + 19]; + badChar[1] = kChar_Null; + sprintf(buf, "(case 2) session id='%s', char='%s'(0x%x)", + pCB->sessionID, badChar, (int) id[c + 12]); + + pCB->logMessage(pCB->shellData, kLog_Warn, + kLogMessage_BadSIDCharacter, badChar, + NULL); + if (pCB->debugEnabled) { + drpIdentifier cookieHeaderName; + int result; + cookieHeaderName.hasIndex = 0; + cookieHeaderName.name.type = kAscii; + cookieHeaderName.name.numChars = + strlen(kCookieHeaderName) + 1; + cookieHeaderName.name.value.ascii = kCookieHeaderName; + + result = + pCB->getParameter(pCB->shellData, + &cookieHeaderName, + &pCB->ioBuffer); + if (result == 0) { + pCB->ioBuffer.buffer[pCB->ioBuffer.used] = + kChar_Null; + sprintf(buf, "cookie header is='%s'", + pCB->ioBuffer.buffer); + pCB->logMessage(pCB->shellData, kLog_Info, + kLogMessage_OneString, buf, NULL); + } else { + pCB->logMessage(pCB->shellData, kLog_Info, + kLogMessage_OneString, + "no cookie header present", NULL); + } + } + returnValue = kDrpServiceBadSID; + } + } + + if (returnValue == kDrpServiceOk) { + /* DRP server IP address: + pack bits from drp server int array into *oAddr */ + *oAddr = 0; + bitcpy32(*oAddr, 31, addrInts[0], 0); + for (c = 0; c < 6; c++) + bitcpy32(*oAddr, 30 - c * 5, addrInts[c + 1], 4); + bitcpy32(*oAddr, 0, addrInts[7], 4); + /* NB: *oAddr is in host byte-order, because we reconstructed it by + value rather than receiving it in a specific order; but, it has + to be in network byte-order for the network calls. so munge it. */ + *oAddr = htonl(*oAddr); + + /* DRP server port: + pack bits from drp server int array into *oPort */ + *oPort = 0; + bitcpy16(*oPort, 15, portInts[0], 3); + bitcpy16(*oPort, 11, portInts[1], 4); + bitcpy16(*oPort, 6, portInts[2], 4); + bitcpy16(*oPort, 1, portInts[3], 4); + /* NB: *oPort is in host byte-order, because we recontsructed it by + value rather than receiving it in a specific byte order. + so leave it. */ + } + + return returnValue; +} + +/* Sets the value of a grow buffer. + * Return: 0 == success; !0 == failure + */ +int setGrowBuffer(growBuffer * b, const char *s) +{ + clearGrowBuffer_m(b); + return concatenate(b, s); +} + + +/** + * concatenate + * Concatenate a character string onto the end of pBuffer, growing + * pBuffer if necessary. + * return: 0 == success; !0 == failure + */ +int concatenate(growBuffer * pBuffer, const char *iString) +{ + int returnValue = kDrpServiceOk; + int stringLength = strlen(iString); + + ensureGrowBufferSize_m(pBuffer, (pBuffer->used + stringLength + 1)); + pBuffer->buffer[pBuffer->used] = kChar_Null; + strcat(pBuffer->buffer, iString); + pBuffer->used += stringLength; + + return returnValue; +} + + +/** + * createGrowBuffer + * creates a new growable buffer structure with at least iInitialSize bytes + * bytes allocated to the buffer field. + * returns: new growBuffer object + */ +growBuffer *createGrowBuffer(growBuffer * pBuffer, size_t iInitialSize) +{ + if (pBuffer != NULL) + pBuffer->allocated = 0; + else { + pBuffer = (growBuffer *) malloc(sizeof(growBuffer)); + if (pBuffer == NULL) + return NULL; + pBuffer->allocated = 1; + } + pBuffer->used = 0; + pBuffer->avail = iInitialSize + 1; + pBuffer->buffer = (char *) malloc(sizeof(char) * pBuffer->avail); + if (pBuffer->buffer == NULL) { + if (pBuffer->allocated) + free(pBuffer); + return NULL; + } + + return pBuffer; +} + + +/** + * growGrowBuffer + * increases the allocation of the buffer field of the indicated + * growable buffer object by at least iGrowSize bytes. + * return: 0 == success; !0 == failure (i.e. allocation failure) + */ +int growGrowBuffer(growBuffer * pBuffer, size_t iGrowSize) +{ + int returnValue = kDrpServiceOk; + + pBuffer->avail += iGrowSize; + pBuffer->buffer = realloc(pBuffer->buffer, pBuffer->avail); + if (!pBuffer->buffer) + returnValue = kDrpServiceNoMemory; + + return returnValue; +} + +/** + * destroyGrowBuffer + * frees up a growBuffer's resources. + */ +void destroyGrowBuffer(growBuffer * pBuffer) +{ + free(pBuffer->buffer); + if (pBuffer->allocated) + free(pBuffer); +} + +/** + * hostToInetAddr + * Given a host address string (either IP address or host name), return + * a corresponding internet address value. + * iHost: host address string (IP or host name). + * return: internet address value; INADDR_NONE (see DRPTypes.h) on failure. + */ +unsigned long hostToInetAddr(const char *iHost) +{ + unsigned long addr; + + /* first, try inet_addr to see if the host is in dotted-decimal form */ + addr = inet_addr(iHost); + if (addr == INADDR_NONE) { + /* second, try gethostbyname */ + struct hostent *he = gethostbyname(iHost); + struct sockaddr_in sa_in; + + if (he != NULL) { + memcpy(&sa_in.sin_addr, he->h_addr, he->h_length); + addr = (unsigned long) sa_in.sin_addr.s_addr; + } + } + + return addr; +} + +#if 0 +/* the following routines were obsoleted with the change from "DRP 2.0" + to "DRP 2.01" (my fake version numbers) */ + +/** + * handleGetAllParameters + * Satisfy the DRP server's request for all Parameters + * return: 0 == success; !0 == failure + */ +static DrpServiceStatus handleGetAllParameters(drpContextBlock * pCB) +{ + int returnValue = kDrpServiceOk; + drpIdentifier paramName; + int namePtr = 0; + int valPtr = 0; + int nextPtr = 0; + int queryLength = 0; + drpByte _1 = 1; + + paramName.name.type = kDefined; + paramName.name.value.defined = kQueryString; + paramName.hasIndex = 0; + + returnValue = + pCB->getParameter(pCB->shellData, ¶mName, &pCB->ioBuffer2); + + if ((pCB->ioBuffer2.used > 0) && (returnValue == kDrpServiceOk)) { + queryLength = strlen(pCB->ioBuffer2.buffer); + while ((nextPtr < queryLength) && (returnValue == kDrpServiceOk)) { + namePtr = nextPtr; + if (pCB->ioBuffer2.buffer[namePtr] == kChar_Null) + break; /* out of while loop */ + getNextQueryArg(pCB->ioBuffer2.buffer, namePtr, &valPtr, + &nextPtr); + /* send byte: NV-Pair follows */ + returnValue = sendByte(pCB, pCB->currentServer->sock, &_1); + if (returnValue == 0) + returnValue = + sendNameIndexedPair(pCB, pCB->currentServer->sock, + kParameter, + pCB->ioBuffer2.buffer + namePtr, + pCB->ioBuffer2.buffer + valPtr); + } + } + + /* do _not_ send 0x00 (NV-Pair terminating byte); caller will handle */ + + return returnValue; +} + + +/** + * getNextQueryArg + * obtain the next query argument from the query argument list + */ +static void +getNextQueryArg(char *pBuffer, int namePtr, int *oValPtr, int *oNextPtr) +{ + char *valCharPtr; + char *nextCharPtr; + + /* name known to start at namePtr */ + + /* first: find where this query argument ends and null-terminate it */ + nextCharPtr = strchr(pBuffer + namePtr, kChar_Ampersand); + if (!nextCharPtr) + nextCharPtr = strchr(pBuffer + namePtr, kChar_Null); + *nextCharPtr = kChar_Null; + + /* second: find next occurrence of '=' */ + valCharPtr = strchr(pBuffer + namePtr, kChar_Equals); + if (!valCharPtr) + valCharPtr = nextCharPtr; + else { + /* null-terminate the name, and move the val ptr ahead to 1st char of + value */ + *valCharPtr = kChar_Null; + valCharPtr++; + } + + /* now: namePtr indicates 1st char of name, which is null-terminated. + valCharPtr is either 1st char of value, or null if no value. + nextCharPtr is terminating char of value (or name, if no value). */ + + nextCharPtr++; /* move next ptr ahead to 1st char of next arg */ + + *oValPtr = valCharPtr - pBuffer; + *oNextPtr = nextCharPtr - pBuffer; +} +#endif diff --git a/lc-continuity/mk4/moddynamo/DRPClient.h b/lc-continuity/mk4/moddynamo/DRPClient.h new file mode 100644 index 0000000000000000000000000000000000000000..19cd9df93ecdeeb06a2f76a039d7b505296927cf --- /dev/null +++ b/lc-continuity/mk4/moddynamo/DRPClient.h @@ -0,0 +1,440 @@ +/* + * Copyright (C) 1997 Art Technology Group, Inc. + * All Rights Reserved. No use, copying or distribution of this + * work may be made except in accordance with a valid license + * agreement from Art Technology Group. This notice must be + * included on all copies, modifications and derivatives of this + * work. + * + * Art Technology Group (ATG) MAKES NO REPRESENTATIONS OR WARRANTIES + * ABOUT THE SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. ATG SHALL NOT BE + * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, + * MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. + * + * "Dynamo" is a trademark of Art Technology Group, Inc. + */ + +/* + DRPClient.h - public API for DRP client routines + */ + +#ifndef _DRP_CLIENT_H_ +#define _DRP_CLIENT_H_ + +#include "DRPTypes.h" + +#ifdef _CPOOL +#include "connectionPool.h" +#endif + +/* constants */ + +/* orig. size of main (per-context) buffers */ +#define kMainBufferSize 4096 + +/* orig. size of minor storage buffers */ +#define kMinorBufferSize 1024 + +/* max # of DRP servers for which the CM will keep information */ +#define kMaxDRPRecords 100 + +/* length of session ID */ +#define kMaxSessionIDLength 256 + +/* size of IO buffers used for buffered send/recv */ +#define kSockBufSize 4200 + +/* default total time to go around a loop calling connect() and + * getting a timeout + */ +#define kDRP_DefaultMaxConnectTimeout 30 /* seconds */ + +/* checkpoints in the service of a request */ +enum { + kIdle = 0, + + kConnectingToServer, + kExaminingRequest, + kNotificationInProgress, + kServicingRequest, + + kServiceComplete, + kNotificationComplete, + + kServiceError, + + kServiceStatusPlaceholder +}; + +/* status values returned from drpService */ +typedef enum DrpServiceStatus { + kDrpServiceOk = 0, /* service request succeeded */ + kDrpServiceError = -1, /* service request failed nonrecoverably */ + kDrpServiceNoServer = -2, /* service request failed because no server + * could satisfy it. */ + kDrpServiceFailover = -3, /* load-managed service request failed; failover + * should be attempted */ + kDrpServiceNoMemory = -4, /* service request failed due to lack of server + * memory */ + kDrpServiceProtocolError = -5, /* service request failed due to a protocol + * error */ + kDrpServiceBadSID = -6, /* service request failed due to bad SID */ +} DrpServiceStatus; + +/* HTTP response information for kDrpServiceFailover handling */ +#define kFailoverStatusCode 302 /* Moved Temporarily */ +#define kFailoverStatusMessage "Application failure, use alternate server" + +void drpSetFailoverServer(const char* newServer); + +void drpSetSessionCookieName(const char* cookieName); + +/* type definitions */ + +typedef struct _sockBuf sockBuf; + +/* SockBuf: IO buffer used for buffered send/recv */ +struct _sockBuf { + char * data; + size_t capacity; /* # bytes allocated to data field */ + size_t used; /* # bytes of data in data field */ + size_t curPtr; /* indicates next byte in buffer to "recv" */ +}; + + +typedef struct _drpContextBlock drpContextBlock; +typedef struct _drpServerRecord drpServerRecord; + + +/* DRPServerRecord: maintains information about a single DRP2 server */ +struct _drpServerRecord { + socket_t sock; /* socket connection to the DRP2 server */ + unsigned long inetaddr; /* IP address of DRP2 server */ + unsigned short port; /* port of DRP2 server */ + unsigned short probability; /* weight used to determine selection of + DRP2 server from list; see + DRPClient.c:drpService_load() */ + unsigned short flags; /* per-server flags, e.g. "active" */ +#ifdef _CPOOL + connectionPool *pool; /* per-server connection pool */ +#endif +}; + + +/** SHELL CALLBACK FUNCTION TYPE DEFINITIONS **/ +/* these prototypes indicate the callback interface used by the DRP2 client + to access functionality in the CM "shell" specific to each server API */ + +/** + * GetParameter_fn + * Retrieve the value (in ascii) for a request parameter (e.g. URI, + * server port, etc). + * pShellData: shell-specific (request-specific) data object + * iName: incdicates parameter to retrieve + * oVal: (growable) buffer in which to store parameter value (in ascii) + * (if no value found, return successfully with empty oVal buffer) + * return: 0 == success; !0 == failure (other than val not found) + */ +typedef int (* GetParameter_fn) + (void * pShellData , const drpIdentifier * iName, growBuffer * oVal); + +/** + * GetNthHeader_fn + * Retrieve the name and value (in ascii) of the nth request header. + * pShellData: shell-specific (request-specific) data object + * iHeaderNum: 0-based index of header to retrieve + * oName, oVal: (growable) buffers in which to store header name and value + * (in ascii) (if no header for iHeaderNum, return successfully + * with empty name and val buffers) + * return: 0 == success; !0 == failure (other than no such header) + */ +typedef int (* GetNthHeader_fn) + (void * pShellData, int iHeaderNum, growBuffer * oName, + growBuffer * oVal); + +/** + * ReadFromAgent_fn + * Read at most iMaxLength bytes from the user agent (browser). + * pShellData: shell-specific (request-specific) data object + * oBuffer: buffer in which to store data read from browser; this callback + * should not increase the size available in oBuffer + * iMaxLength: maximum number of bytes to read from agent; actual number of + * bytes read is indicated via oBuffer->used. guaranteed to be + * <= bytes available in oBuffer. + * return: 0 == success (including EOF); !0 == failure (other than EOF) + * note: if the data stream to the agent has been closed (physically or + * logically), return failure. + */ +typedef int (* ReadFromAgent_fn) + (void * pShellData, growBuffer * oBuffer, size_t iMaxLength); + +/** + * WriteToAgent_fn + * Write iLength bytes to the user agent (browser). + * pShellData: shell-specific (request-specific) data object + * iBuffer: contains data to write to agent + * iLength: number of bytes to write to agent. + * return: 0 == success (all bytes were written); !0 == failure + * note: if the data stream to the agent has been closed (physically or + * logically), return failure. + */ +typedef int (* WriteToAgent_fn) + (void * pShellData, const growBuffer * iBuffer, size_t iLength); + +/** + * FlushData_fn + * Flush the data stream to the user agent (browser), if possible. + * pShellData: shell-specific (request-specific) data object + * note: if the data stream to the agent has been closed (physically or + * logically), return failure. + */ +typedef int (* FlushData_fn) + (void * pShellData); + +/** + * CloseData_fn + * Close the data stream to the user agent (browser), if possible. + * pShellData: shell-specific (request-specific) data object + * note: if it is not possible or advisable for the CM shell to close the + * data stream, it is permissible to mark it as closed for the + * purpose of responding to future callbacks as if the stream were + * closed. + */ +typedef int (* CloseData_fn) + (void * pShellData); + +/** + * SendHeaderBatch_fn + * Send HTTP response status and header(s) to user agent (browser); + * headers are provided in a preformatted block. + * pShellData: shell-specific (request-specific) data object + * iStatusCode: HTTP status code (e.g. 200) + * iStatusMesg: optional status message for HTTP status line + * iMesgLength: number of relevant bytes in iStatusMesg; test iMesgLength + * rather than iStatusMesg for presence of message + * iHeaders: preformatted block of header name-value pairs, including + * newlines (should need no parsing by shell) + * iHeadersLength: number of relevant bytes in iHeaders + * return: 0 == success; !0 == failure + * note: a CM shell implementation need implement only one of + * SendHeaderBatch or SendHeaderNoBatch; the shell's expectation is + * noted in the DRP Context Block passed to drpService. a shell + * that registers itself as expecting batched headers need not + * implement a SetResponseHeader callback. + */ +typedef int (* SendHeaderBatch_fn) + (void * pShellData, drpInt iStatusCode, const char * iStatusMesg, + size_t iMesgLength, const char * iHeaders, size_t iHeadersLength); + +/** + * SetResponseHeader_fn + * Set a single HTTP response header name-value pair, to be sent to the agent + * when SendHeaderNoBatch is invoked. + * pShellData: shell-specific (request-specific) data object + * iHeaderName: name of response header (ascii, null-terminated) + * iHeaderValue: value of response header (ascii, null-terminated) + * return: 0 == success; !0 == failure + * note: a shell that registers itself as expecting batched headers need not + * implement a SetResponseHeader callback. + */ +typedef int (* SetResponseHeader_fn) + (void * pShellData, const growBuffer * iHeaderName, + const growBuffer * iHeaderValue); + +/** + * SendHeaderNoBatch_fn + * Send HTTP response status and header(s) to user agent (browser); + * headers will have been provided already via SetResponseHeader callback, + * and must be sent with this callback. + * pShellData: shell-specific (request-specific) data object + * iStatusCode: HTTP status code (e.g. 200) + * iStatusMesg: optional status message for HTTP status line + * iMesgLength: number of relevant bytes in iStatusMesg; test iMesgLength + * rather than iStatusMesg for presence of message + * return: 0 == success; !0 == failure + * note: a CM shell implementation need implement only one of + * SendHeaderBatch or SendHeaderNoBatch; the shell's expectation is + * noted in the DRP Context Block passed to drpService. a shell + * that registers itself as expecting batched headers need not + * implement a SetResponseHeader callback. + */ +typedef int (* SendHeaderNoBatch_fn) + (void * pShellData, drpInt iStatusCode, const char * iStatusMesg, + size_t iMesgLength); + +/** + * DefinedLength_fn + * Return the length of the shell-specific ascii representation of the + * indicated DRP defined string. + * pShellData: shell-specific (request-specific) data object + * iDefined: DRP defined string String-ID. + * return: length of shell's representation of iDefined; 0 if the shell has + * no representation for iDefined + */ +typedef int (* DefinedLength_fn) + (void * pShellData, drpByte iDefined); + +/** + * DefinedAscii_fn + * Return the (null-terminated) shell-specific ascii representation of the + * indicated DRP defined string. + * pShellData: shell-specific (request-specific) data object + * iDefined: DRP defined string String-ID. + * return: shell's representation of iDefined; NULL if the shell has no + * representation for iDefined. + */ +typedef const char * (* DefinedAscii_fn) + (void * pShellData, drpByte iDefined); + +/** + * LogMessage_fn + * Log the message associated with iMessageNumber (with up to two optional + * arguments) to the HTTP-server's log (or WIN32 event log for ISAPI). + * pShellData: shell-specific (request-specific) data object + * iMessageType: indicates whether message is "Info", "Warning", or "Error" + * iMessageNumber: index of message to log + * iParam1, iParam2: optional parameters to include in the log message (can be + * NULL) + */ +typedef void (* LogMessage_fn) + (void * pShellData, int iMessageType, int iMessageNumber, + const char * iParam1, const char * iParam2); + +/* log message types */ +enum { + kLog_Info, + kLog_Warn, + kLog_Error +}; + + +/* structure definitions */ + +/* DRPContextBlock: maintains the information each service "context" + (service thread for multithreaded servers or service process for + multiprocess servers) needs to service requests; in the multithreaded + case, an instance of this structure is associated with each service + thread via the Thread-Local-Storage mechanism (see threadabstr.h) */ +struct _drpContextBlock { + /** INPUTS **/ + + /* call back functions (for accessing shell functionality) */ + GetParameter_fn getParameter; + GetNthHeader_fn getNthHeader; + ReadFromAgent_fn readFromAgent; + WriteToAgent_fn writeToAgent; + FlushData_fn flushData; + CloseData_fn closeData; + SendHeaderBatch_fn sendHeaderBatch; + SendHeaderNoBatch_fn sendHeaderNoBatch; + SetResponseHeader_fn setResponseHeader; + DefinedLength_fn definedStringLength; + DefinedAscii_fn definedStringToAscii; + LogMessage_fn logMessage; + + /* 0: CM shell expects response headers to be sent in one big block; + !0: CM shell expects response headers in name-value pairs. + see DRPClient.c:handleHeader*/ + short shellExpectsHeaderPairs; + + /* shellData: http-server-API-specific chunk of data the CM shell passes in; + to be sent back to shell in shell callbacks */ + void * shellData; + + + /** INTERNALS **/ + + int serviceStatus; + + /* socket IO buffers */ + sockBuf recvBuf; + sockBuf sendBuf; + + growBuffer ioBuffer; + growBuffer ioBuffer2; + + drpServerRecord * currentServer; + drpServerRecord drpServers[kMaxDRPRecords]; + drpServerRecord * drpServerPtrs[kMaxDRPRecords]; + int numDrpServers; + unsigned int drpServerInfoVersion; /* local DRP information version; + compared to + CMLDRP.h:gCMLDRP_InfoVersion */ + + short statusSetByServer; /* 0: DRP server has not yet set HTTP status */ + short statusSentToAgent; + drpInt statusCode; /* HTTP response code */ + drpTLiteral statusMesg; /* HTTP response message (or kNull) */ + growBuffer headers; + growBuffer headers2; + growBuffer statusBuffer; + + char sessionID[kMaxSessionIDLength]; /* SID (if any) for current requests */ + + unsigned int totalProb; /* total of "probabilities" (weights) for all + known DRP2 servers */ + + char isLoggedRequest; /* 0 for regular service request, 1 for logged request*/ + + char debugEnabled; /* 1 if debugging is turned on */ + char isTargetedRequest; /* 1 if dyn_server arg was specified */ + + int maxConnectTimeout; /* total time (seconds) to go around a loop + calling connect() and getting a timeout */ + + /* + * The address and port of the DRP server if isTargetedRequest is + * true + */ + unsigned long targetedServerAddr; + unsigned short targetedServerPort; +}; + + + +/* clearGrowBuffer: (_m : reminds me this is a macro :) + reset growbuffer to 0 bytes used; set first byte to null character + (in case buffer about to be used as C string) */ +#define clearGrowBuffer_m(/* (growBuffer *) */b) \ + { (b)->used = 0; \ + (b)->buffer[0] = kChar_Null; } + +/* ensureGrowBufferSize: (_m : reminds me this is a macro :) + if bytes allocated to growbuffer less than bytes requested, buffer is + grown (by realloc()) to requested size */ +#define ensureGrowBufferSize_m(/* (growBuffer *) */ b, /* size_t */ s) \ + { if ((b)->avail < (s)) \ + growGrowBuffer((b), (s) - (b)->avail + 1); } + +/* sets the value of a grow buffer + */ +int setGrowBuffer(growBuffer* b, const char* s); + +/* DRP-type to ASCII string converters */ +void identToAscii(DefinedLength_fn iDefinedLength, + DefinedAscii_fn iDefinedAscii, void * pShellData, + const drpIdentifier * iIdent, growBuffer * oBuffer); +void tliteralToAscii(DefinedLength_fn iDefinedLength, + DefinedAscii_fn iDefinedAscii, void * pShellData, + const drpTLiteral * iTLiteral, growBuffer * oBuffer); + +/* growbuffer manipulation */ +growBuffer * createGrowBuffer(growBuffer * pBuffer, size_t iInitialSize); +int concatenate(growBuffer * pBuffer, const char * iString); +int growGrowBuffer(growBuffer * pBuffer, size_t iGrowSize); +void destroyGrowBuffer(growBuffer * growBuffer); + + +/* DRP2 client service entry points */ +void drpInitialize(void); +void drpReset(drpContextBlock * pCB); +int drpService(drpContextBlock * pCB); + + +/* convert host identifier (IP address or host name) to struct in_addr */ +unsigned long hostToInetAddr(const char * iHost); + + +#endif /* _DRP_CLIENT_H_ */ diff --git a/lc-continuity/mk4/moddynamo/DRPServerIO.c b/lc-continuity/mk4/moddynamo/DRPServerIO.c new file mode 100644 index 0000000000000000000000000000000000000000..25ac4648b1052746d818a21b94a9e34f9f7ffebf --- /dev/null +++ b/lc-continuity/mk4/moddynamo/DRPServerIO.c @@ -0,0 +1,820 @@ +/* + * Copyright (C) 1997 Art Technology Group, Inc. + * All Rights Reserved. No use, copying or distribution of this + * work may be made except in accordance with a valid license + * agreement from Art Technology Group. This notice must be + * included on all copies, modifications and derivatives of this + * work. + * + * Art Technology Group (ATG) MAKES NO REPRESENTATIONS OR WARRANTIES + * ABOUT THE SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. ATG SHALL NOT BE + * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, + * MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. + * + * "Dynamo" is a trademark of Art Technology Group, Inc. + */ + +/* + DRPServerIO.c - routines for sending/receiving DRP objects, etc + */ + + +#include + +#ifndef WIN32 +/* UNIXen */ +#include +#include +#include +#include +#include +#include +#else +#define EINTR WSAEINTR +#endif + + +#include "DRPClient.h" +#include "DRPServerIO.h" + + +#include +#include + +/** + * do_recv + * locally-buffered interface to recv(). if requested amount of data + * is not already in the "receive" socket io buffer in the context block + * (pCB), then the io buffer is filled from socket iSock. + * (NB: assumed that iSock, flags always the same for given context) + * return: number of bytes received; 0 == sock closed; SOCKET_ERROR == failure + */ +static size_t +do_recv(drpContextBlock * pCB, socket_t iSock, char *oBuffer, + size_t iLength, int iFlags) +{ + size_t returnValue = 0; + sockBuf *recvBuf = &pCB->recvBuf; + size_t bytesAvail; + + if (recvBuf->used - recvBuf->curPtr < iLength) { + /* fewer bytes in recvBuf than requested */ + int result; + + if (recvBuf->curPtr > 0) { + /* move as-yet-unretrieved data in recvBuf to beginning of recvBuf */ + memmove(recvBuf->data, recvBuf->data + recvBuf->curPtr, + recvBuf->used - recvBuf->curPtr); + recvBuf->used -= recvBuf->curPtr; + recvBuf->curPtr = 0; + } + /* fill recvBuf with delicious data */ + tryagain: + result = recv(iSock, recvBuf->data + recvBuf->used, + recvBuf->capacity - recvBuf->used, iFlags); + if (result < 0) { + int errorNum = net_error(); + char buf[128]; + + if (errorNum == EINTR) { + if (pCB->debugEnabled) { + sprintf(buf, + "read failed from socket %d with errno %d retrying...", + iSock, errorNum); + + pCB->logMessage(pCB->shellData, kLog_Info, + kLogMessage_OneString, buf, NULL); + } + goto tryagain; + } + + if (pCB->debugEnabled) { + sprintf(buf, "read failed from socket %d with errno %d", + iSock, errorNum); + + pCB->logMessage(pCB->shellData, kLog_Info, + kLogMessage_OneString, buf, NULL); + } + returnValue = result; + goto DO_RECV_EXIT; + } else { + if (result == 0 && pCB->debugEnabled) { + pCB->logMessage(pCB->shellData, kLog_Info, + kLogMessage_OneString, "recv returned 0", + NULL); + } + recvBuf->used += result; + } + } + bytesAvail = recvBuf->used - recvBuf->curPtr; /* avail in recvBuf */ + returnValue = MIN(bytesAvail, iLength); /* bytes to copy into return buf */ + memcpy(oBuffer, recvBuf->data + recvBuf->curPtr, returnValue); + recvBuf->curPtr += returnValue; + + DO_RECV_EXIT: + + return returnValue; +} + + +/** + * do_send + * uses send() to send all data currently in the "send" socket io buffer + * in the context block (pCB) via socket iSock. + * return: number of bytes send; SOCKET_ERROR == failure + */ +static size_t do_send(drpContextBlock * pCB, socket_t iSock, int iFlags) +{ + size_t returnValue = 0; + sockBuf *sendBuf = &pCB->sendBuf; + size_t result = 1; + size_t bytesSentSoFar = 0; + + while ((bytesSentSoFar < sendBuf->used) && (result > 0)) { + result = send(iSock, sendBuf->data + bytesSentSoFar, + sendBuf->used - bytesSentSoFar, iFlags); + + if (result < 0) { + char buf[128]; + int errorNum = net_error(); + + if (errorNum == EINTR) + continue; + + if (pCB->debugEnabled) { + sprintf(buf, "write failed to socket %d with errno %d", + iSock, errorNum); + + pCB->logMessage(pCB->shellData, kLog_Info, + kLogMessage_OneString, buf, NULL); + } + } + bytesSentSoFar += result; + } + if (result == SOCKET_ERROR) { + returnValue = result; + goto DO_SEND_EXIT; + } else { + returnValue += result; + sendBuf->used = 0; + } + + DO_SEND_EXIT: + + return returnValue; +} + + +/** + * send_queue + * locally-buffered interface to send(). if there is not enough space + * in the "send" socket io buffer for the data, the buffer is flushed + * out to socket iSock. otherwise, data is copied into send buffer + * to be sent later. + * (NB: assumed that iSock, flags always the same for given context) + * return: number of bytes (queued to be) sent; SOCKET_ERROR == failure + */ +static size_t +send_queue(drpContextBlock * pCB, socket_t iSock, const char *iBuffer, + size_t iLength, int iFlags) +{ + size_t returnValue = 0; + sockBuf *sendBuf = &pCB->sendBuf; + size_t bytesAvail; + + if (sendBuf->capacity - sendBuf->used < iLength) { + size_t result; + + /* fewer bytes avail in sendBuf than needed to store data */ + result = do_send(pCB, iSock, iFlags); + if (result == SOCKET_ERROR) { + returnValue = result; + goto DO_SEND_EXIT; + } + } + bytesAvail = sendBuf->capacity - sendBuf->used; /* avail in sendBuf */ + returnValue = MIN(bytesAvail, iLength); /* bytes to copy into sendBuf */ + memcpy(sendBuf->data + sendBuf->used, iBuffer, returnValue); + sendBuf->used += returnValue; + + DO_SEND_EXIT: + + return returnValue; +} + + +/** + * send_flush + * forces send of data currently in "send" socket io buffer in the context + * block (pCB) via socket iSock. + * return: 0 == success; SOCKET_ERROR == failure + */ +int send_flush(drpContextBlock * pCB, socket_t iSock, int iFlags) +{ + size_t result; + + result = do_send(pCB, iSock, iFlags); + + return (result == SOCKET_ERROR ? result : 0); +} + + +/** + * recvByte + * Receive a single byte from the DRP server + * oByte: will be filled in with byte value received + * return: 0 == success; !0 == failure + */ +int recvByte(drpContextBlock * pCB, socket_t iSock, drpByte * oByte) +{ + int returnValue = 0; + size_t bytesRead; + + bytesRead = do_recv(pCB, iSock, oByte, sizeof(drpByte), 0); + if (bytesRead != sizeof(drpByte)) { + if (pCB->debugEnabled) { + char buf[128]; +#if defined(SOLARIS2) && !defined(_LP64) && !defined(_I32LPx) || defined(WIN32) || defined(LINUX) + sprintf(buf, "failed to read byte (size=%u) from socket %d", +#else + sprintf(buf, "failed to read byte (size=%lu) from socket %d", +#endif + bytesRead, iSock); + pCB->logMessage(pCB->shellData, kLog_Info, + kLogMessage_OneString, buf, NULL); + } + returnValue = -1; + } + + return returnValue; +} + + +/** + * sendByte + * Send a single byte to the DRP server + * iByte: byte to send + * return: 0 == success; !0 == failure + */ +int sendByte(drpContextBlock * pCB, socket_t iSock, const drpByte * iByte) +{ + int returnValue = 0; + int bytesSent; + + bytesSent = send_queue(pCB, iSock, iByte, sizeof(drpByte), 0); + if (bytesSent != sizeof(drpByte)) + returnValue = -1; + + return returnValue; +} + + +/** + * recvLong + * Receive a 4-byte integer from the DRP server + * oLong: will be filled in with the "long" value received + * return: 0 == success; !0 == failure + */ +int recvLong(drpContextBlock * pCB, socket_t iSock, drpInt * oLong) +{ + int returnValue = 0; + size_t bytesRead; + + bytesRead = do_recv(pCB, iSock, (char *) oLong, sizeof(drpInt), 0); + if (bytesRead != sizeof(drpInt)) { + if (pCB->debugEnabled) { + char buf[128]; +#if defined(SOLARIS2) && !defined(_LP64) && !defined(_I32LPx) || defined(WIN32) || defined(LINUX) + sprintf(buf, "failed to read long (size=%u) from socket %d", +#else + sprintf(buf, "failed to read long (size=%lu) from socket %d", +#endif + bytesRead, iSock); + pCB->logMessage(pCB->shellData, kLog_Info, + kLogMessage_OneString, buf, NULL); + } + returnValue = -1; + } else + *oLong = ntohl(*oLong); + + return returnValue; +} + + +/** + * sendLong + * Send a 4-byte integer to the DRP server + * iLong: the "long" value to send + * return: 0 == success; !0 == failure + */ +int sendLong(drpContextBlock * pCB, socket_t iSock, const drpInt * iLong) +{ + int returnValue = 0; + size_t bytesSent; + drpInt value; + + value = htonl(*iLong); + bytesSent = send_queue(pCB, iSock, (char *) &value, sizeof(drpInt), 0); + if (bytesSent != sizeof(drpInt)) + returnValue = -1; + + return returnValue; +} + + +/** + * recvBuffer + * Receive a byte stream from the DRP server + * oBuffer: buffer object to fill with data received + * iLength: number of bytes to receive + * return: 0 == success; !0 == failure + */ +int +recvBuffer(drpContextBlock * pCB, socket_t iSock, growBuffer * oBuffer, + size_t iLength) +{ + int returnValue = 0; + size_t bytesRead = 1; + + /* NB: not necessary to grow buffer */ + + oBuffer->used = 0; + + while ((oBuffer->used < iLength) && (bytesRead > 0)) { + bytesRead = do_recv(pCB, iSock, oBuffer->buffer + oBuffer->used, + iLength - oBuffer->used, 0); + + if (bytesRead > 0) + oBuffer->used += bytesRead; + } + + if (oBuffer->used < iLength) { + if (pCB->debugEnabled) { + char buf[128]; + sprintf(buf, "failed to read buffer stream " +#if defined(SOLARIS2) && !defined(_LP64) && !defined(_I32LPx) || defined(WIN32) || defined(LINUX) + "(size=%u != %u) read=%u from socket %d", +#else + "(size=%lu != %lu) read=%lu from socket %d", +#endif + oBuffer->used, iLength, bytesRead, iSock); + pCB->logMessage(pCB->shellData, kLog_Info, + kLogMessage_OneString, buf, NULL); + } + returnValue = -1; + } + + return returnValue; +} + + +/** + * sendBuffer + * Send a byte stream to the DRP server + * iBuffer: buffer object containing data to send + * (iBuffer->used is number of bytes to send) + * return: 0 == success; !0 == failure + */ +int +sendBuffer(drpContextBlock * pCB, socket_t iSock, + const growBuffer * iBuffer) +{ + int returnValue = 0; + + returnValue = + sendByteStream(pCB, iSock, iBuffer->buffer, iBuffer->used); + + return returnValue; +} + + +/** + * sendBytes + * Send a byte stream to the DRP server + * iBytes: bytes to send + * iLength: number of bytes to send + * return: 0 == success; !0 == failure + */ +int +sendByteStream(drpContextBlock * pCB, socket_t iSock, const char *iBytes, + size_t iLength) +{ + int returnValue = 0; + size_t bytesSent = 1; + size_t bytesSentSoFar = 0; + + while ((bytesSentSoFar < iLength) && (bytesSent > 0)) { + bytesSent = send_queue(pCB, iSock, iBytes + bytesSentSoFar, + iLength - bytesSentSoFar, 0); + bytesSentSoFar += bytesSent; + } + + if (bytesSentSoFar < iLength) + returnValue = -1; + + return returnValue; +} + + +/** + * recvIdentifier + * Receive a DRP Identifier object from the DRP server. + * oIdent: will be filled in with received Identifier data. + * oBuffer: if received Identifier includes string data, that data will + * be placed in oBuffer (and the appropriate Identifier field will be + * pointed to oBuffer) + * return: 0 == success; !0 == failure + */ +int +recvIdentifier(drpContextBlock * pCB, socket_t iSock, + drpIdentifier * oIdent, growBuffer * oBuffer) +{ + int returnValue = 0; + + /* recv has-index byte */ + returnValue = recvByte(pCB, iSock, &oIdent->hasIndex); + if (returnValue == 0) + /* recv ident name (TLiteral) */ + returnValue = recvTLiteral(pCB, iSock, &oIdent->name, oBuffer); + if (oIdent->hasIndex && (returnValue == 0)) + /* recv ident index (TLiteral) */ + returnValue = recvTLiteral(pCB, iSock, &oIdent->index, oBuffer); + else + memset(&oIdent->index, 0, sizeof(drpTLiteral)); + + return returnValue; +} + + +/** + * recvTLiteral + * Receive a DRP Typed Literal object from the DRP server. + * oTLiteral: will be filled in with received TLiteral data. + * oBuffer: if received TLiteral includes string data, that data will + * be placed in oBuffer (and the appropriate TLiteral field will be + * pointed to oBuffer); will be grown if necessary + * return: 0 == success; !0 == failure + */ +int +recvTLiteral(drpContextBlock * pCB, socket_t iSock, + drpTLiteral * oTLiteral, growBuffer * oBuffer) +{ + int returnValue = 0; + + oTLiteral->numChars = 0; + + /* recv TLiteral type byte */ + returnValue = recvByte(pCB, iSock, &oTLiteral->type); + if (returnValue == 0) { + switch (oTLiteral->type) { + case kNull: + /* do nothing */ + break; + case kInteger: + returnValue = recvLong(pCB, iSock, &oTLiteral->value.integer); + break; + case kAscii: + /* recv ascii data length */ + returnValue = + recvLong(pCB, iSock, (drpInt *) & oTLiteral->numChars); + if (returnValue == 0) { + /* recv ascii data */ + ensureGrowBufferSize_m(oBuffer, + (oBuffer->used + + oTLiteral->numChars)); + returnValue = + recvByteStream(pCB, iSock, + oBuffer->buffer + oBuffer->used, + oTLiteral->numChars); + if (returnValue == 0) { + oBuffer->used += oTLiteral->numChars; + oTLiteral->value.ascii = oBuffer->buffer; + } else + oTLiteral->numChars = 0; + } else + oTLiteral->numChars = 0; + break; + case kUnicode: + /* recv unicode data length */ + returnValue = + recvLong(pCB, iSock, (drpInt *) & oTLiteral->numChars); + if (returnValue == 0) { + /* recv unicode data */ + ensureGrowBufferSize_m(oBuffer, + (oBuffer->used + + oTLiteral->numChars * + sizeof(drpChar))); + returnValue = + recvByteStream(pCB, iSock, + oBuffer->buffer + oBuffer->used, + sizeof(drpChar) * oTLiteral->numChars); + if (returnValue == 0) { + oBuffer->used += oTLiteral->numChars * sizeof(drpChar); + /* DO NOT re-order unicode */ + oTLiteral->value.unicode = (drpChar *) oBuffer->buffer; + } else + oTLiteral->numChars = 0; + } else + oTLiteral->numChars = 0; + break; + case kDefined: + returnValue = recvByte(pCB, iSock, &oTLiteral->value.defined); + break; + default: + returnValue = -1; + break; + } + } + + return returnValue; +} + + +/** + * recvByteStream + * Receive a byte stream from the DRP server + * oBuffer: buffer in which to store received data + * iLength: number of bytes to receive + * return: 0 == success; !0 == failure + */ +int +recvByteStream(drpContextBlock * pCB, socket_t iSock, char *oBuffer, + size_t iLength) +{ + int returnValue = 0; + size_t bytesRead = 1; + size_t bytesReadSoFar = 0; + + while ((bytesReadSoFar < iLength) && (bytesRead > 0)) { + bytesRead = do_recv(pCB, iSock, oBuffer + bytesReadSoFar, + iLength - bytesReadSoFar, 0); + if (bytesRead > 0) + bytesReadSoFar += bytesRead; + } + + if (bytesReadSoFar < iLength) { + if (pCB->debugEnabled) { + char buf[128]; + sprintf(buf, "failed to read byte stream " +#if defined(SOLARIS2) && !defined(_LP64) && !defined(_I32LPx) || defined(WIN32) || defined(LINUX) + "(size=%u != %u) read=%u from socket %d", +#else + "(size=%lu != %lu) read=%lu from socket %d", +#endif + bytesReadSoFar, iLength, bytesRead, iSock); + pCB->logMessage(pCB->shellData, kLog_Info, + kLogMessage_OneString, buf, NULL); + } + returnValue = -1; + } + + return returnValue; +} + + +/** + * sendIdentifier + * Send a DRP Identifier object to the DRP server. + * iIdent: the Identifier to send. + * return: 0 == success; !0 == failure + */ +int +sendIdentifier(drpContextBlock * pCB, socket_t iSock, + const drpIdentifier * iIdent) +{ + int returnValue = 0; + + /* send has-index byte */ + returnValue = sendByte(pCB, iSock, &iIdent->hasIndex); + if (returnValue == 0) + /* send ident name (TLiteral) */ + returnValue = sendTLiteral(pCB, iSock, &iIdent->name); + if (iIdent->hasIndex && (returnValue == 0)) + /* send ident index (TLiteral) */ + returnValue = sendTLiteral(pCB, iSock, &iIdent->index); + + return returnValue; +} + + +/** + * sendTLiteral + * Send a DRP Typed Literal object to the DRP server. + */ +int +sendTLiteral(drpContextBlock * pCB, socket_t iSock, + const drpTLiteral * iTLiteral) +{ + int returnValue = 0; + + /* send TLiteral type byte */ + returnValue = sendByte(pCB, iSock, &iTLiteral->type); + if (returnValue == 0) { + switch (iTLiteral->type) { + case kNull: + /* do nothing */ + break; + case kInteger: + returnValue = sendLong(pCB, iSock, &iTLiteral->value.integer); + break; + case kDefined: + returnValue = sendByte(pCB, iSock, &iTLiteral->value.defined); + break; + case kAscii: + /* send ascii data length */ + returnValue = + sendLong(pCB, iSock, (drpInt *) & iTLiteral->numChars); + if (returnValue == 0) + /* send ascii data */ + returnValue = + sendByteStream(pCB, iSock, iTLiteral->value.ascii, + iTLiteral->numChars); + break; + case kUnicode: + /* send unicode data length */ + returnValue = + sendLong(pCB, iSock, (drpInt *) & iTLiteral->numChars); + if (returnValue == 0) { + /* send unicode data */ + /* DO NOT reorder unicode */ + returnValue = sendByteStream(pCB, iSock, + (char *) iTLiteral->value. + unicode, + iTLiteral->numChars * + sizeof(drpChar)); + } + break; + default: + returnValue = -1; + break; + } + } + + return returnValue; +} + + +/** + * sendAsciiTLiteral + * Send a DRP Typed Literal object with ASCII string data to the DRP server. + * iAsciiBuffer: the ASCII string data to send. + * return: 0 == success; !0 == failure + */ +int +sendAsciiTLiteral(drpContextBlock * pCB, socket_t iSock, + const growBuffer * iAsciiBuffer) +{ + int returnValue = 0; + drpByte _ascii = kAscii; + + /* send ascii typed-literal type byte */ + returnValue = sendByte(pCB, iSock, &_ascii); + if (returnValue == 0) + /* send length of ascii data */ + returnValue = + sendLong(pCB, iSock, (drpInt *) & iAsciiBuffer->used); + if (returnValue == 0) + /* send ascii data */ + returnValue = sendByteStream(pCB, iSock, iAsciiBuffer->buffer, + iAsciiBuffer->used); + + return returnValue; +} + + +/** + * sendIntTLiteral + * Send a DRP Typed Literal object with DRP-Integer data to the DRP server. + * iInt: the 4-byte integer to send. + * return: 0 == success; !0 == failure. + */ +int sendIntTLiteral(drpContextBlock * pCB, socket_t iSock, drpInt iInt) +{ + int returnValue = 0; + drpByte _int = kInteger; + + /* send integer typed-literal type byte */ + returnValue = sendByte(pCB, iSock, &_int); + if (returnValue == 0) + /* send integer value */ + returnValue = sendLong(pCB, iSock, &iInt); + + return returnValue; +} + + + +/** + * sendNameIndexedPair + * Send a Name-Value pair, indexed by (ascii string) iIndex. + * iDefinedName: defined-string index indicating "name" of pair + * iIndex: (null-terminated) ascii string indicating "index" of pair + * iAscii: (null-terminated) ascii string "value" of pair. + * return: 0 == success; !0 == failure + */ +int +sendNameIndexedPair(drpContextBlock * pCB, socket_t iSock, + drpByte iDefinedName, const drpByte * iIndex, + const drpByte * iAscii) +{ + int returnValue = 0; + drpByte _1 = 1; + drpByte _ascii = kAscii; + drpByte _defined = kDefined; + drpInt length = strlen(iIndex); + + /* send Identifier (pair name) */ + /* send byte: identifier has index */ + returnValue = sendByte(pCB, iSock, &_1); + + /* send TLiteral (identifier name): iDefinedName */ + if (returnValue == 0) + /* TLiteral type: defined string type */ + returnValue = sendByte(pCB, iSock, &_defined); + if (returnValue == 0) + /* TLiteral value: defined string ID */ + returnValue = sendByte(pCB, iSock, &iDefinedName); + + /* send TLiteral (identifier index): iIndex */ + if (returnValue == 0) + /* TLiteral type: ascii string type */ + returnValue = sendByte(pCB, iSock, &_ascii); + if (returnValue == 0) + /* ascii string length */ + returnValue = sendLong(pCB, iSock, &length); + if (returnValue == 0) + /* ascii string data */ + returnValue = sendByteStream(pCB, iSock, iIndex, length); + + length = strlen(iAscii); + + /* send TLiteral (pair value): iAscii */ + if (returnValue == 0) + /* TLiteral type: ascii string type */ + returnValue = sendByte(pCB, iSock, &_ascii); + if (returnValue == 0) + /* ascii string length */ + returnValue = sendLong(pCB, iSock, &length); + if (returnValue == 0) + /* ascii string data */ + returnValue = sendByteStream(pCB, iSock, iAscii, length); + + return returnValue; +} + + +/** + * sendIntIndexedPair + * Send a Name-Value pair, indexed by (integer) iIndex. + * iDefinedName: defined-string index indicating "name" of pair. + * iIndex: integer "index" of pair. + * iAscii: (null-terminated) ascii string "value" of pair. + * return: 0 == success; !0 == failure + */ +int +sendIntIndexedPair(drpContextBlock * pCB, socket_t iSock, + drpByte iDefinedName, int iIndex, + const drpByte * iAscii) +{ + int returnValue = 0; + drpByte _1 = 1; + drpByte _defined = kDefined; + drpByte _integer = kInteger; + drpByte _ascii = kAscii; + drpInt length = strlen(iAscii); + + /* send Identifier (pair name) */ + /* send byte: identifier has index */ + returnValue = sendByte(pCB, iSock, &_1); + + /* send TLiteral (identifier name): iDefinedName */ + if (returnValue == 0) + /* TLiteral type: defined string type */ + returnValue = sendByte(pCB, iSock, &_defined); + if (returnValue == 0) + /* TLiteral value: defined string ID */ + returnValue = sendByte(pCB, iSock, &iDefinedName); + + /* send TLiteral (identifier index): iIndex */ + if (returnValue == 0) + /* TLiteral type: integer type */ + returnValue = sendByte(pCB, iSock, &_integer); + if (returnValue == 0) + /* TLiteral value: iIndex */ + returnValue = sendLong(pCB, iSock, (drpInt *) & iIndex); + + /* send TLiteral (pair value): iAscii */ + if (returnValue == 0) + /* TLiteral type: ascii string type */ + returnValue = sendByte(pCB, iSock, &_ascii); + if (returnValue == 0) + /* ascii string length */ + returnValue = sendLong(pCB, iSock, &length); + if (returnValue == 0) + /* ascii string data */ + returnValue = sendByteStream(pCB, iSock, iAscii, length); + + return returnValue; +} diff --git a/lc-continuity/mk4/moddynamo/DRPServerIO.h b/lc-continuity/mk4/moddynamo/DRPServerIO.h new file mode 100644 index 0000000000000000000000000000000000000000..4bcf7d9f582f97b0ef9c3ee6de7e0b825e19894d --- /dev/null +++ b/lc-continuity/mk4/moddynamo/DRPServerIO.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 1997 Art Technology Group, Inc. + * All Rights Reserved. No use, copying or distribution of this + * work may be made except in accordance with a valid license + * agreement from Art Technology Group. This notice must be + * included on all copies, modifications and derivatives of this + * work. + * + * Art Technology Group (ATG) MAKES NO REPRESENTATIONS OR WARRANTIES + * ABOUT THE SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. ATG SHALL NOT BE + * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, + * MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. + * + * "Dynamo" is a trademark of Art Technology Group, Inc. + */ + +/* + DRPServerIO.h - API for sending/receiving DRP objects, etc + */ + +#ifndef _DRP_SERVER_IO_ +#define _DRP_SERVER_IO_ + +#include "DRPTypes.h" +#include "DRPClient.h" + + +int recvByte(drpContextBlock * pCB, socket_t iSock, drpByte * oByte); +int sendByte(drpContextBlock * pCB, socket_t iSock, const drpByte * iByte); +int recvLong(drpContextBlock * pCB, socket_t iSock, drpInt * oLong); +int sendLong(drpContextBlock * pCB, socket_t iSock, const drpInt * iLong); +int recvBuffer(drpContextBlock * pCB, socket_t iSock, growBuffer * oBuffer, + size_t iLength); +int sendBuffer(drpContextBlock * pCB, socket_t iSock, + const growBuffer * iBuffer); +int recvByteStream(drpContextBlock * pCB, socket_t iSock, char * oBuffer, + size_t iLength); +int sendByteStream(drpContextBlock * pCB, socket_t iSock, + const char * iBytes, size_t iLength); +int recvIdentifier(drpContextBlock * pCB, socket_t iSock, + drpIdentifier * oIdent, growBuffer * oBuffer); +int recvTLiteral(drpContextBlock * pCB, socket_t iSock, + drpTLiteral * oTLiteral, growBuffer * oBuffer); +int sendIdentifier(drpContextBlock * pCB, socket_t iSock, + const drpIdentifier * iIdent); +int sendTLiteral(drpContextBlock * pCB, socket_t iSock, + const drpTLiteral * iTLiteral); +int sendAsciiTLiteral(drpContextBlock * pCB, socket_t iSock, + const growBuffer * iAsciiBuffer); +int sendIntTLiteral(drpContextBlock * pCB, socket_t iSock, + drpInt iInt); +int sendNameIndexedPair(drpContextBlock * pCB, socket_t iSock, + drpByte iDefinedName, const drpByte * iIndex, + const drpByte * iValue); +int sendIntIndexedPair(drpContextBlock * pCB, socket_t iSock, + drpByte iDefinedName, int iIndex, + const drpByte * iAscii); +int send_flush(drpContextBlock * pCB, socket_t iSock, int iFlags); + + + +#endif diff --git a/lc-continuity/mk4/moddynamo/DRPTypes.h b/lc-continuity/mk4/moddynamo/DRPTypes.h new file mode 100644 index 0000000000000000000000000000000000000000..2f6e1fb50e36cf9cac07ac253cf9348a2fb06659 --- /dev/null +++ b/lc-continuity/mk4/moddynamo/DRPTypes.h @@ -0,0 +1,241 @@ +/* + * Copyright (C) 1997 Art Technology Group, Inc. + * All Rights Reserved. No use, copying or distribution of this + * work may be made except in accordance with a valid license + * agreement from Art Technology Group. This notice must be + * included on all copies, modifications and derivatives of this + * work. + * + * Art Technology Group (ATG) MAKES NO REPRESENTATIONS OR WARRANTIES + * ABOUT THE SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. ATG SHALL NOT BE + * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, + * MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. + * + * "Dynamo" is a trademark of Art Technology Group, Inc. + */ + + +/* + DRPTypes.h - typedefs and constant #defines + */ + + +#ifndef _DRP_TYPES_H_ +#define _DRP_TYPES_H_ + + +#ifdef WIN32 +/* NT */ +#include +#include +#else +/* UNIXen */ +#include +#include +#endif + + +/* DRP Packet identifiers: identify the type of DRP packet + being sent by the CM or DRP server */ +enum { + kUnknownType = 0, /* placeholder - not used */ + kBeginRequest, /* 1 */ /* CM sends to start response cycle */ + kReply, /* 2 */ /* server sends to supply response headers, + response data, etc */ + kGetParameters, /* 3 */ /* server sends to get add'l req params */ + kReadDataStream, /* 4 */ /* server sends to read agent data (post) */ + kBeginLogRequest, /* 5 */ /* server sends a log request */ + + kPacketTypePlaceholder /* placeholder - not used */ +}; + + +/* Typed-Literal data types: identify the type of object contained in a + DRP2 TypedLiteral */ +enum { + kNull = 0, /* null object (not placeholder) */ + kInteger, /* 1 */ /* 4-byte integer */ + kAscii, /* 2 */ + kUnicode, /* 3 */ + kDefined, /* 4 */ /* pre-defined string placeholder (integral) */ + + kTLiteralTypePlaceholder /* placeholder - not used */ +}; + + +/* defined string identifiers: pre-defined string placeholders */ +enum { + kContentLength = 1, + kContentType, /* 2 */ + kParameter, /* 3 */ + kParameters, /* 4 */ + kProtocol, /* 5 */ + kRemoteAddr, /* 6 */ + kRemoteHost, /* 7 */ + kServerName, /* 8 */ + kServerPort, /* 9 */ + kAuthType, /* 10 */ + kHeaderName, /* 11 */ + kHeaderVal, /* 12 */ + kHeaders, /* 13 */ + kMethod, /* 14 */ + kPathInfo, /* 15 */ + kPathTranslated, /* 16 */ + kQueryString, /* 17 */ + kRemoteUser, /* 18 */ + kRequestURI, /* 19 */ + kServletPath, /* 20 */ + kScheme, /* 21 */ + kUserAgent, /* 22 */ + + kDefinedPlaceholder +}; + + +/* socket_t: abstracted socket type for WIN32 & UNIXen */ +#ifdef WIN32 +typedef SOCKET socket_t; +#define kInvalidSocket INVALID_SOCKET +#else +typedef int socket_t; +#define kInvalidSocket -1 +#ifndef INADDR_NONE +#define INADDR_NONE -1 +#endif +#endif + +#define ATG_INVALID_DYNSOCKET NULL + +#ifdef WIN32 +# define ATG_INVALID_SOCKET INVALID_SOCKET +# define ATG_SOCKET_ERROR SOCKET_ERROR +# define ATG_INADDR_NONE INADDR_NONE +# define net_error() WSAGetLastError() +#else +# define ATG_INVALID_SOCKET -1 +# define ATG_SOCKET_ERROR -1 +# define ATG_INADDR_NONE -1 +# define net_error() errno +#endif + + + +/* DRP2 protocol's atomic types */ +typedef char drpByte; +typedef long drpInt; +typedef short drpChar; + +/* DRP2 protocol's complex types */ +typedef struct _drpTLiteral drpTLiteral; +typedef struct _drpIdentifier drpIdentifier; +typedef struct _growBuffer growBuffer; + + +/* TypedLiteral object type: represents a single value (e.g. a header name) */ +struct _drpTLiteral { + drpByte type; + size_t numChars; /* number of *characters*, not necessarily *bytes*; + relevant to kAscii and kUnicode TLiteral types */ + union { + drpInt integer; + drpByte defined; + drpByte * ascii; + drpChar * unicode; + } value; +}; + + +/* Identifier object type: associates a TypedLiteral object with an optional + (TypedLiteral) index value */ +struct _drpIdentifier { + drpByte hasIndex; + drpTLiteral name; + drpTLiteral index; +}; + + +/* GrowBuffer: growable (e.g. via realloc()) buffer object */ +struct _growBuffer { + int allocated; /* true if growBuffer structure was allocated by + * createGrowBuffer(). */ + char * buffer; + size_t avail; /* # bytes total allocated for buffer field */ + size_t used; /* # bytes of actual data in buffer */ +}; + + +/* character constants */ +#define kChar_Null '\0' +#define kChar_Ampersand '&' +#define kChar_Equals '=' +#define kChar_Colon ':' +#define kChar_Semicolon ';' +#define kChar_Comma ',' +#define kChar_Slash '/' +#define kChar_QMark '?' +#define kChar_Hash '#' +#define kChar_Backslash '\\' +#define kChar_Newline '\n' +#define kChar_Dot '.' +#define kChar_Space ' ' + +/* string constants */ +#define kString_HeaderNVDelim ": " +#define kString_Newline "\n" +#define kString_QMark "?" +#define kString_Space " " +#define kString_Star "*" +#define kString_Slash "/" +#define kString_Backslash "\\" +#define kString_Colon ":" +#define kString_HTTP_ "HTTP_" +#define kString_http "http" +#define kString_https "https" + +#define kEmptyString "" + + +#ifndef MIN +#define MIN(a,b) ((a)<(b)?(a):(b)) +#endif +#ifndef MAX +#define MAX(a,b) ((a)>(b)?(a):(b)) +#endif + + +/* Server-API-independent log messages */ +enum { + kLogMessage_DRPServerUnavailable = 1, + kLogMessage_NoDRPServerAvailable, + kLogMessage_CannotCreateSocket, + kLogMessage_CannotConnect, + kLogMessage_InternalProtoError, + kLogMessage_BadSIDCharacter, + kLogMessage_CannotCreateRWLock, + kLogMessage_CannotStartCMLDRPThread, + kLogMessage_BadCMLDRPResponseType, + kLogMessage_NoCMLDRPResponsePeriod, + kLogMessage_NoCMLDRPResponseFirst, + kLogMessage_OneString, + kLogMessage_CantResolveCMLDRPHost, + kLogMessage_NoGoodCMLDRPServers, + + kLogMessage_Placeholder /* placeholder used as starting point for + API-dependent log messages */ +}; + + +#ifdef WIN32 +#define net_error() WSAGetLastError() +#else +#define net_error() errno +#endif + +#ifndef SOCKET_ERROR +#define SOCKET_ERROR -1 +#endif + + +#endif diff --git a/lc-continuity/mk4/moddynamo/DynSock.c b/lc-continuity/mk4/moddynamo/DynSock.c new file mode 100644 index 0000000000000000000000000000000000000000..a309f56b7e868837f0ec33c2c04efa7b478ec35b --- /dev/null +++ b/lc-continuity/mk4/moddynamo/DynSock.c @@ -0,0 +1,302 @@ +/* + * Copyright (C) 2000 Art Technology Group, Inc. + * All Rights Reserved. No use, copying or distribution of this + * work may be made except in accordance with a valid license + * agreement from Art Technology Group. This notice must be + * included on all copies, modifications and derivatives of this + * work. + * + * Art Technology Group (ATG) MAKES NO REPRESENTATIONS OR WARRANTIES + * ABOUT THE SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. ATG SHALL NOT BE + * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, + * MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. + * + * "Dynamo" is a trademark of Art Technology Group, Inc. + */ + +#include "DynSock.h" +#include "DRPTypes.h" +#include +#include +#include + +#ifdef WIN32 +#include +#include +#else +#include +#include +#include +#include +#include +#endif + +#define DYNSOCKET_VERSION "dynSocket1.0" + +/************************** + * Communication Routines * + **************************/ + +/** + * dynSock_int(pInitData) + * + * Initialize any dynSocket global structures + * Returns 0 on sucess + */ +int dynSocket_init(void *pInitData) +{ + return 0; +} + +/** + * dynSocket *dynSocket_new(pInfo) + * + * Creates a new dynSocket using information contained in pInfo. + * Returns a pointer to the new dynSocket if successful, + * ATG_INVALID_DYNSOCKET otherwise. + * + * NOTE: NEVER call any of the other dynSocket_xxx calls with a + * pointer to an invalid dynSocket, i.e. the pointer has a value of + * ATG_INVALID_DYNSOCKET. + */ +#ifdef _ISAPI +dynSocket *dynSocket_new(HANDLE gHeap, dynSocketInfo * pInfo) +{ +#else +dynSocket *dynSocket_new(dynSocketInfo * pInfo) +{ +#endif + dynSocket *dynSock = NULL; + socket_t s = ATG_INVALID_SOCKET; + + /* Create a DynSocket */ +#ifdef _ISAPI + dynSock = (dynSocket *) HeapAlloc(gHeap, 0, sizeof(dynSocket)); +#else + dynSock = (dynSocket *) malloc(sizeof(dynSocket)); +#endif + if (dynSock == NULL) + return ATG_INVALID_DYNSOCKET; + + /* Zero out memory */ + memset(dynSock, 0, sizeof(dynSocket)); + + /*Set Version */ + strcpy(dynSock->version, DYNSOCKET_VERSION); + + /*Set Socket Info */ + dynSock->info = pInfo; + + /* Create the socket */ + s = socket(AF_INET, SOCK_STREAM, 0); + if (s == ATG_INVALID_SOCKET) { +#ifdef _ISAPI + (void) HeapFree(gHeap, 0, dynSock); +#else + free(dynSock); +#endif + return ATG_INVALID_DYNSOCKET; + } + dynSock->socket_data = (void *) s; + dynSock->connected = 0; + + /* Manipulate operating characteristics of + * socket with ioctl here + */ + + return dynSock; +} + +/** + * int dynSocket_connect(pDynSocket,pRemoteAddr,pLen) + * + * Connects pDynSocket to pRemoteAddr. Use dySocket_close(pDynSocket) + * to close this dynSocket. + * On success zero is returned. Otherwise ATG_SOCKET_ERROR is returned. + */ + +int dynSocket_connect(dynSocket * pDynSocket, + struct sockaddr *pRemoteAddr, int pLen) +{ + int ret = 0; + + /* Get the socket */ + socket_t s = (socket_t) pDynSocket->socket_data; + + /* Connect to the remote host */ + ret = connect(s, pRemoteAddr, pLen); + if (ret == ATG_SOCKET_ERROR) { + return ret; + } + memcpy(&(pDynSocket->remote_addr), pRemoteAddr, + sizeof(struct sockaddr)); + pDynSocket->remote_addr_len = pLen; + pDynSocket->connected = 1; + + return ret; +} + +/** + * int dynSocket_close(pDynSocket) + * + * Close a pDynSocket and does clean up. + * On success returns zero, or ATG_SOCKET_ERROR if an error occurred. + */ +#ifdef _ISAPI +int dynSocket_close(HANDLE gHeap, dynSocket * pDynSocket) +{ +#else +int dynSocket_close(dynSocket * pDynSocket) +{ +#endif + socket_t s = (socket_t) (pDynSocket->socket_data); + + pDynSocket->connected = 0; +#ifdef _ISAPI + (void) HeapFree(gHeap, 0, pDynSocket); +#else + free(pDynSocket); +#endif + +#ifdef WIN32 + return closesocket(s); +#else + return close(s); +#endif +} + +#ifndef WIN32 +/** + * int dynSocket_read(pDynSocket,pBuf,pCount) + * + * Only for UNIX. + * Read data from dynSocket. Attempt to read up to count bytes from + * pDynSocket into pBuf. + * On Success, the number of bytes read is returned. Zero indicates + * the end of file. On error -1 is returned. + */ +int dynSocket_read(dynSocket * pDynSocket, void *pBuf, size_t pCount) +{ + return read((socket_t) (pDynSocket->socket_data), pBuf, pCount); +} + +/** + * int dynSocket_write(pDynSocket,pBuf,pCount) + * + * Only for UNIX. + * Write data to dynSocket. Attempt to write up to pCount bytes to + * the pDynSocket from pBuf. + * On success, the number of byte written are returned. Zero indicates + * nothing was written. On error -1 is returned. + */ +int dynSocket_write(dynSocket * pDynSocket, const void *pBuf, + size_t pCount) +{ + return write((socket_t) (pDynSocket->socket_data), pBuf, pCount); +} +#endif + +/** + * dynSocket_recv(pDynSocket,pBuf,pLen,pFlags) + * + * Receive data from a dynSocket. Attepm to read up to pLen bytes from + * pDynSocket into pBuf + * On Success, the number of bytes reveived is returned. Zero indicates + * the end of file. On error ATG_SOCKET_ERROR is returned. + */ +int dynSocket_recv(dynSocket * pDynSocket, void *pBuf, int pLen, + int pFlags) +{ + return recv((socket_t) (pDynSocket->socket_data), pBuf, pLen, pFlags); +} + +/** + * dynSocket_send(pDynSocket,pMsg,pLen,pFlags) + * + * Send data on dynSocket. Attempt to send up to pCount bytes to + * the pDynSocket from pBuf. + * On success, the number of byte sent are returned. Zero indicates + * nothing was sent. On error ATG_SOCKET_ERROR is returned. + */ +int dynSocket_send(dynSocket * pDynSocket, const void *pMsg, int pLen, + int pFlags) +{ + return send((socket_t) (pDynSocket->socket_data), pMsg, pLen, pFlags); +} + +/********************** + * DynSock Properties * + **********************/ + +/** + * char *dynSocket_version(pDynSocket) + * + * Return version of pDynSocket + */ +char *dynSocket_version(dynSocket * pDynSocket) +{ + return pDynSocket->version; +} + +/** + * dynSocketInfo *dynSocket_info(pDynSocket) + * + * Return the info struct for pDynSocket + */ +dynSocketInfo *dynSocket_info(dynSocket * pDynSocket) +{ + return pDynSocket->info; +} + +/** + * void *dynSocket_socket_data(pDynSocket) + * + * Return the socket data for pDynSocket + */ +void *dynSocket_socket_data(dynSocket * pDynSocket) +{ + return pDynSocket->socket_data; +} + +/** + * int dynSocket_connected(pDynSocket) { + * + * Return the connected field for pDynSocket + */ +int dynSocket_connected(dynSocket * pDynSocket) +{ + return pDynSocket->connected; +} + + +/** + * struct sockaddr *dynSocket_remote_addr(pDynSocket) + * + * Return the remote address for pDynSocket + */ +struct sockaddr *dynSocket_remote_addr(dynSocket * pDynSocket) +{ + return &(pDynSocket->remote_addr); +} + +/** + * int dynSocket_remote_addr_len(*pDynSocket) + * + * Return remote address length for pDynSocket + */ +int dynSocket_remote_addr_len(dynSocket * pDynSocket) +{ + return pDynSocket->remote_addr_len; +} + +/** + * socket_t dynSocket_socket(pDynSocket) + * + * Return the raw socket for pDynSocket + */ +socket_t dynSocket_socket(dynSocket * pDynSocket) +{ + return (socket_t) (pDynSocket->socket_data); +} diff --git a/lc-continuity/mk4/moddynamo/DynSock.h b/lc-continuity/mk4/moddynamo/DynSock.h new file mode 100644 index 0000000000000000000000000000000000000000..cfc504da47f678f91c536207e15d6d9b5426c02b --- /dev/null +++ b/lc-continuity/mk4/moddynamo/DynSock.h @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2000 Art Technology Group, Inc. + * All Rights Reserved. No use, copying or distribution of this + * work may be made except in accordance with a valid license + * agreement from Art Technology Group. This notice must be + * included on all copies, modifications and derivatives of this + * work. + * + * Art Technology Group (ATG) MAKES NO REPRESENTATIONS OR WARRANTIES + * ABOUT THE SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. ATG SHALL NOT BE + * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, + * MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. + * + * "Dynamo" is a trademark of Art Technology Group, Inc. + */ + +/* + DynSock.h - public API for Socket adaption +*/ + +#ifndef _DYN_SOCK_H_ +#define _DYN_SOCK_H_ + +#ifdef WIN32 +/* NT */ +#include +#include +#else +/* UN?X */ +#include +#include + +#include +#endif + +/* socket_t: abstracted socket type for WIN32 & UNIXen */ +#ifdef WIN32 +typedef SOCKET socket_t; +#else +typedef int socket_t; +#endif + +/* struct used in creation of socket */ +typedef struct _dynSocketInfo { + void *info; /* Info used in creation of socket */ +} dynSocketInfo; + +/* struct used to represent a socket */ +typedef struct _dynSocket { + char version[24]; /* version identification */ + dynSocketInfo *info; /* pointer to socket info */ + void *socket_data; /* pointer to raw socket data */ + int connected; /* is this socket connected */ + struct sockaddr remote_addr; /* remote host address */ + int remote_addr_len; /* remote host address len */ +}dynSocket; + +/* Initialization Routines */ +int dynSocket_init(void *pInitData); + +/* Socket Communication Routines */ +#ifdef _ISAPI +dynSocket *dynSocket_new(HANDLE gHeap, dynSocketInfo *pInfo); +int dynSocket_close(HANDLE gHeap, dynSocket *pDynSocket); +#else +dynSocket *dynSocket_new(dynSocketInfo *pInfo); +int dynSocket_close(dynSocket *pDynSocket); +#endif +int dynSocket_connect(dynSocket *pDynSocket,struct sockaddr *pRemoteAddr,int pLen); +int dynSocket_read(dynSocket *pDynSocket,void *pBuf,size_t pCount); +int dynSocket_write(dynSocket *pDynSocket,const void *pBuf,size_t pCount); +int dynSocket_recv(dynSocket *pDynSocket, void *pBuf,int pLen,int pFlags); +int dynSocket_send(dynSocket *pDynSocket,const void *pMsg,int len,int pFlags); + +/* DynSock Properties */ +char *dynSocket_version(dynSocket *pDynSocket); +dynSocketInfo *dynSocket_info(dynSocket *pDynSocket); +void *dynSocket_socket_data(dynSocket *pDynSocket); +int dynSocket_connected(dynSocket *pDynSocket); +struct sockaddr *dynSocket_remote_addr(dynSocket *pDynSocket); +int dynSocket_remote_addr_len(dynSocket *pDynSocket); +socket_t dynSocket_socket(dynSocket *pDynSocket); + + +#endif /* _DYN_SOCK_H_ */ diff --git a/lc-continuity/mk4/moddynamo/Makefile b/lc-continuity/mk4/moddynamo/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..973fe3a7f51c4dc6048d91c7410cb65403ffaf87 --- /dev/null +++ b/lc-continuity/mk4/moddynamo/Makefile @@ -0,0 +1,22 @@ +# $Header: /san01/cvs/ashpool/csrc/moddynamo/Attic/Makefile,v 1.4 2004/06/22 14:36:14 aleigh Exp $ + +SRCS=CMLDRP.c DRPClient.c DRPServerIO.c DynSock.c pageroute.c io.c hook.c threadabstr.c sockerrs.c +OBJS=CMLDRP.o DRPClient.o DRPServerIO.o DynSock.o pageroute.o io.o hook.o threadabstr.o sockerrs.o + +include ../continuity/lib/env.mk + +CFLAGS=-D_DRP_MTHREAD -I../continuity/include $(CONT_FLAGS) + +world: install + +dynamo.so: $(OBJS) + $(LD_SHARECMD) -o dynamo.so $(OBJS) + +install: dynamo.so + cp dynamo.so ../continuity/lib + +clean: + rm -rf $(OBJS) *~ dynamo.so + +depend: + $(MAKEDEPEND) $(DEPFLAGS) -I ../continuity/include $(SRCS) diff --git a/lc-continuity/mk4/moddynamo/cmVersion.h b/lc-continuity/mk4/moddynamo/cmVersion.h new file mode 100644 index 0000000000000000000000000000000000000000..38bcd41321a49d1e783b4b16bd66fd42122de0a9 --- /dev/null +++ b/lc-continuity/mk4/moddynamo/cmVersion.h @@ -0,0 +1,228 @@ +/* + * Copyright (C) 1997 Art Technology Group, Inc. + * All Rights Reserved. No use, copying or distribution of this + * work may be made except in accordance with a valid license + * agreement from Art Technology Group. This notice must be + * included on all copies, modifications and derivatives of this + * work. + * + * Art Technology Group (ATG) MAKES NO REPRESENTATIONS OR WARRANTIES + * ABOUT THE SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. ATG SHALL NOT BE + * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, + * MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. + * + * "Dynamo" is a trademark of Art Technology Group, Inc. + */ + +/* + cmVersion.h - header file to determine CM version information at + compile time + */ + + + +#ifndef _CM_VERSION_H_ +#define _CM_VERSION_H_ + + +#define kCM_VersionNumber "0.500" + +#define kString_Version "version " + +#define kCM_Name "Dynamo 3 Connection Module for continuity aleigh@tessier.com\n" + +#ifdef NOTDEF + + +#ifdef WIN32 + +#ifdef _NSAPI1 + +#define kCM_Name \ + "Dynamo 3 Connection Module for Netscape Commerce and Communications 1.x\n" \ + "servers (Windows NT)" + +#elif defined(_NSAPI2) + +#define kCM_Name \ + "Dynamo 3 Connection Module for Netscape Enterprise and FastTrack 2.x\n" \ + "servers (Windows NT)" + +#elif defined(_NSAPI3) + +#define kCM_Name \ + "Dynamo 3 Connection Module for Netscape Enterprise and FastTrack 3.x\n" \ + "servers (Windows NT)" + +#elif defined(_NSAPI4) + +#define kCM_Name \ + "Dynamo 3 Connection Module for Netscape Enterprise 4.x\n" \ + "servers (Windows NT)" + +#elif defined(_ISAPI) + +#define kCM_Name \ + "Dynamo 3 Connection Module for Microsoft Internet Information Server\n" \ + "(Windows NT)" + +#else +#error "Unknown CM API" + +#endif /* def? _NSAPI1 */ + +#elif defined(SOLARIS2) + +#ifdef _NSAPI1 + +#define kCM_Name \ + "Dynamo 3 Connection Module for Netscape Commerce and Communications 1.x\n" \ + "servers (Solaris)" + +#elif defined(_NSAPI2) + +#define kCM_Name \ + "Dynamo 3 Connection Module for Netscape Enterprise and FastTrack 2.x\n" \ + "servers (Solaris)" + +#elif defined(_NSAPI3) + +#define kCM_Name \ + "Dynamo 3 Connection Module for Netscape Enterprise and FastTrack 3.x\n" \ + "servers (Solaris)" + +#elif defined(_NSAPI4) + +#define kCM_Name \ + "Dynamo 3 Connection Module for Netscape Enterprise 4.x\n" \ + "servers (Solaris)" + +#elif defined(_APACHE) + +#define kCM_Name \ + "Dynamo 3 Connection Module for Apache server (Solaris)\n" + +#else +#error "Unknown CM API" + +#endif /* def? _NSAPI1 */ + +#elif defined(_IRIX) + +#ifdef _NSAPI1 + +#define kCM_Name \ + "Dynamo 3 Connection Module for Netscape Commerce and Communications 1.x\n" \ + "servers (IRIX)" + +#elif defined(_NSAPI2) + +#define kCM_Name \ + "Dynamo 3 Connection Module for Netscape Enterprise and FastTrack 2.x\n" \ + "servers (IRIX)" + +#elif defined(_NSAPI3) + +#define kCM_Name \ + "Dynamo 3 Connection Module for Netscape Enterprise and FastTrack 3.x\n" \ + "servers (IRIX)" + +#elif defined(_NSAPI4) + +#define kCM_Name \ + "Dynamo 3 Connection Module for Netscape Enterprise 4.x\n" \ + "servers (IRIX)" + +#elif defined(_APACHE) + +#define kCM_Name \ + "Dynamo 3 Connection Module for Apache server (IRIX)\n" + +#else +#error "Unknown CM API" + +#endif /* def? _NSAPI1 */ + +#elif defined(_AIX) + +#ifdef _NSAPI1 + +#define kCM_Name \ + "Dynamo 3 Connection Module for Netscape Commerce and Communications 1.x\n" \ + "servers (AIX)" + +#elif defined(_NSAPI2) + +#define kCM_Name \ + "Dynamo 3 Connection Module for Netscape Enterprise and FastTrack 2.x\n" \ + "servers (AIX)" + +#elif defined(_NSAPI3) + +#define kCM_Name \ + "Dynamo 3 Connection Module for Netscape Enterprise and FastTrack 3.x\n" \ + "servers (AIX)" + +#elif defined(_NSAPI4) + +#define kCM_Name \ + "Dynamo 3 Connection Module for Netscape Enterprise 4.x\n" \ + "servers (AIX)" + +#elif defined(_APACHE) + +#define kCM_Name \ + "Dynamo 3 Connection Module for Apache server (AIX)\n" + +#else +#error "Unknown CM API" + +#endif /* def? _NSAPI1 */ + +#elif defined(_HPUX) + +#ifdef _NSAPI1 + +#define kCM_Name \ + "Dynamo 3 Connection Module for Netscape Commerce and Communications 1.x\n" \ + "servers (HPUX)" + +#elif defined(_NSAPI2) + +#define kCM_Name \ + "Dynamo 3 Connection Module for Netscape Enterprise and FastTrack 2.x\n" \ + "servers (HPUX)" + +#elif defined(_NSAPI3) + +#define kCM_Name \ + "Dynamo 3 Connection Module for Netscape Enterprise and FastTrack 3.x\n" \ + "servers (HPUX)" + +#elif defined(_NSAPI4) + +#define kCM_Name \ + "Dynamo 3 Connection Module for Netscape Enterprise 4.x\n" \ + "servers (HPUX)" + +#elif defined(_APACHE) + +#define kCM_Name \ + "Dynamo 3 Connection Module for Apache server (HPUX)\n" + +#else +#error "Unknown CM API" + +#endif /* def? _NSAPI1 */ + +#else +#error "Unknown Platform" + +#endif /* def? _WIN32 */ + +#endif /* ndef? _CM_VERSION_H_ */ + +#endif + diff --git a/lc-continuity/mk4/moddynamo/hook.c b/lc-continuity/mk4/moddynamo/hook.c new file mode 100644 index 0000000000000000000000000000000000000000..ad74481f5d4294d2783130602b651e7a9a57aea5 --- /dev/null +++ b/lc-continuity/mk4/moddynamo/hook.c @@ -0,0 +1,570 @@ +#pragma ident "$Header: /san01/cvs/ashpool/csrc/moddynamo/Attic/hook.c,v 1.12 2004/03/18 15:04:15 aleigh Exp $" + +/* + * Copyright (c) 2003 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Disclosure, copying, distribution, or transmission of of this code without + * express permission is prohibited. + */ + +#include "DRPClient.h" +#include "CMLDRP.h" +#include "cmVersion.h" + +#include +#include +#include "../continuity/mecha/lst.h" + +#undef DEBUG + +/** SHELL CALLBACK FUNCTION TYPE DEFINITIONS **/ +/* + * these prototypes indicate the callback interface used by the DRP2 client + * to access functionality in the CM "shell" specific to each server API + */ + +/* + * pBlock->logFunction(pBlock->logShellData, kLog_Error, + * kLogMessage_CantResolveCMLDRPHost, iServers[s].host, NULL); } + */ + +static const char *sLogMessages[] = { + NULL, + + /* server-api-independent messages */ + "mod/dynamo: Failure while attempting to use DRP server at %s:%s to service a request.", + "mod/dynamo: Could not find a functioning DRP server to service a request.", + "mod/dynamo: Cannot create socket for connection to DRP server; error number is: %s.", + "mod/dynamo: Cannot connect to DRP server; error number is: %s.", + "mod/dynamo: Internal protocol error: unexpected DRP packet type: %s.", + "mod/dynamo: Bad character found in Dynamo3 session identifier: %s.", + "mod/dynamo: CMLDRP subsystem cannot start: cannot create read-write lock.", + "mod/dynamo: CMLDRP subsystem cannot start: cannot start updater thread.", + "mod/dynamo: Bad CMLDRP packet response type received from CMLDRP server at %s:%s.", + "mod/dynamo: No response received from CMLDRP server at %s:%s for 150 seconds.", + "mod/dynamo: No response received from CMLDRP server at %s:%s.", + "mod/dynamo: %s", + "mod/dynamo: Cannot resolve the CMLDRP server host: %s.", + "mod/dynamo: Cannot continue; no acceptable CMLDRP servers specified.", + NULL +}; + +void logHook(void *shell, int log_level, int log_message, char *arg1, + char *arg2) +{ + int status; + + switch (log_level) { + case kLog_Info: + status = 0; + break; + case kLog_Warn: + status = 1; + break; + case kLog_Error: + status = 2; + break; + default: + status = 3; + } + + logFmsg(status, sLogMessages[log_message], arg1, arg2); +} + +/** + * GetParameter_fn + * Retrieve the value (in ascii) for a request parameter (e.g. URI, + * server port, etc). + * pShellData: shell-specific (request-specific) data object + * iName: incdicates parameter to retrieve + * oVal: (growable) buffer in which to store parameter value (in ascii) + * (if no value found, return successfully with empty oVal buffer) + * return: 0 == success; !0 == failure (other than val not found) + */ + +int GetParameter(void *pShellData, const drpIdentifier * iName, + growBuffer * oVal) +{ + httpTtrans *t = (httpTtrans *) pShellData; + char *value = NULL; + int returnValue = 0; + + oVal->used = 0; + oVal->buffer[0] = kChar_Null; + + if (iName->name.type == kDefined) { + drpByte defined = iName->name.value.defined; + + switch (defined) { + case kProtocol: + value = lstFset_get(t->vars, "protocol"); + break; + + case kServerName: /* HOSTNAME */ + value = "10.10.10.22"; + break; + + case kMethod: + value = lstFset_get(t->vars, "method"); + break; + + case kContentType: + value = lstFset_get(t->req_hdrs, "content-type"); + break; + + case kUserAgent: + value = lstFset_get(t->req_hdrs, "user-agent"); + break; + + case kContentLength: + value = lstFset_get(t->req_hdrs, "content-length"); + break; + + case kRequestURI: + /* request URI: parsed URI, no dynamo args or query args. */ + value = lstFset_get(t->vars, "uri"); + break; + + case kQueryString: + value = lstFset_get(t->vars, "query"); + break; + + case kPathInfo: + /* path-iinfo: path_info + dynamo-args */ + value = lstFset_get(t->vars, "req_uri"); + break; + + case kRemoteAddr: + value = lstFset_get(t->vars, "remote_addr"); + if (value == NULL) { + char remote_addr[16]; + utlFip_to_str(t->cli_ipv4_addr, remote_addr, 16); + lstFset_add(t->vars, "remote_addr", remote_addr); + value = lstFset_get(t->vars, "remote_addr"); + } + break; + + case kRemoteHost: + value = lstFset_get(t->vars, "remote_addr"); + if (value == NULL) { + char remote_addr[16]; + utlFip_to_str(t->cli_ipv4_addr, remote_addr, 16); + lstFset_add(t->vars, "remote_addr", remote_addr); + value = lstFset_get(t->vars, "remote_addr"); + } + break; + + case kAuthType: + break; + + case kRemoteUser: + + break; + + case kPathTranslated: + /* + * This should be the full path to the jhtml file on the dyanmo app + * server. If this is NULL, the dynamo server will try to work out + * the path from the request uri and it's idea of the document root, + * if it's configured to do so. + */ + value = lstFset_get(t->vars, "path"); + break; + + case kServerPort: + value = "8990"; + break; + + case kServletPath: + + break; + + case kScheme: + /* This is used by dynamo for building redirects. */ + value = "http"; + break; + + default: + break; + + } + } else { +#ifdef DEBUG + logFmsg(3, "mod/dynamo: getParameter: Called for undefined."); +#endif + } + + if (value) { + concatenate(oVal, value); + return returnValue; + } else { + return 0; + } +} + +/** + * GetNthHeader_fn + * Retrieve the name and value (in ascii) of the nth request header. + * pShellData: shell-specific (request-specific) data object + * iHeaderNum: 0-based index of header to retrieve + * oName, oVal: (growable) buffers in which to store header name and value + * (in ascii) (if no header for iHeaderNum, return successfully + * with empty name and val buffers) + * return: 0 == success; !0 == failure (other than no such header) + */ +int GetNthHeader(void *pShellData, int iHeaderNum, growBuffer * oName, + growBuffer * oVal) +{ + httpTtrans *t = (httpTtrans *) pShellData; + int index; + + index = lstFnth_find(t->req_hdrs, iHeaderNum); + + oName->used = 0; + oName->buffer[0] = kChar_Null; + oVal->used = 0; + oVal->buffer[0] = kChar_Null; + + if (index == -1) { + return 0; + } + concatenate(oName, t->req_hdrs->fields[index].name); + concatenate(oVal, t->req_hdrs->fields[index].value); + + return 0; +} + + +/** + * ReadFromAgent_fn + * Read at most iMaxLength bytes from the user agent (browser). + * pShellData: shell-specific (request-specific) data object + * oBuffer: buffer in which to store data read from browser; this callback + * should not increase the size available in oBuffer + * iMaxLength: maximum number of bytes to read from agent; actual number of + * bytes read is indicated via oBuffer->used. guaranteed to be + * <= bytes available in oBuffer. + * return: 0 == success (including EOF); !0 == failure (other than EOF) + * note: if the data stream to the agent has been closed (physically or + * logically), return failure. + */ +int ReadFromAgent(void *pShellData, growBuffer * oBuffer, + size_t iMaxLength) +{ + httpTtrans *t = (httpTtrans *) pShellData; + char *clen; + int read; + + if (t->client_read == 0) { + clen = lstFset_get(t->req_hdrs, "content-length"); + if (clen == NULL) + return 0; + t->client_read = atoi(clen); + } + if (t->client_read == -1) + return 0; + + if (iMaxLength < t->client_read) + read = httpFread(t, oBuffer->buffer, iMaxLength); + else + read = httpFread(t, oBuffer->buffer, t->client_read); + + + if (read < 1) + return -1; + + oBuffer->used = read; + + t->client_read -= read; + if (t->client_read == 0) + t->client_read = -1; + + return 0; +} + +/** + * WriteToAgent_fn + * Write iLength bytes to the user agent (browser). + * pShellData: shell-specific (request-specific) data object + * iBuffer: contains data to write to agent + * iLength: number of bytes to write to agent. + * return: 0 == success (all bytes were written); !0 == failure + * note: if the data stream to the agent has been closed (physically or + * logically), return failure. + */ +int WriteToAgent + (void *pShellData, const growBuffer * iBuffer, size_t iLength) { + httpTtrans *t = (httpTtrans *) pShellData; + + if (httpFwrite(t, iBuffer->buffer, iLength) != iLength) + return -1; + + return 0; +} + +/** + * FlushData_fn + * Flush the data stream to the user agent (browser), if possible. + * pShellData: shell-specific (request-specific) data object + * note: if the data stream to the agent has been closed (physically or + * logically), return failure. + */ +int FlushData(void *pShellData) { + httpTtrans *t = (httpTtrans *) pShellData; + + /* + * Flushing is not required for continuity, since writes aren't buffered + */ + + return 0; + +} + +/** + * CloseData_fn + * Close the data stream to the user agent (browser), if possible. + * pShellData: shell-specific (request-specific) data object + * note: if it is not possible or advisable for the CM shell to close the + * data stream, it is permissible to mark it as closed for the + * purpose of responding to future callbacks as if the stream were + * closed. + */ +int CloseData(void *pShellData) { + httpTtrans *t = (httpTtrans *) pShellData; + + /* Shouldn't do this under Continuity.. Just pretend. */ + /* close(t->sd); */ + + return 0; +} + +/** + * SendHeaderBatch_fn + * Send HTTP response status and header(s) to user agent (browser); + * headers are provided in a preformatted block. + * pShellData: shell-specific (request-specific) data object + * iStatusCode: HTTP status code (e.g. 200) + * iStatusMesg: optional status message for HTTP status line + * iMesgLength: number of relevant bytes in iStatusMesg; test iMesgLength + * rather than iStatusMesg for presence of message + * iHeaders: preformatted block of header name-value pairs, including + * newlines (should need no parsing by shell) + * iHeadersLength: number of relevant bytes in iHeaders + * return: 0 == success; !0 == failure + * note: a CM shell implementation need implement only one of + * SendHeaderBatch or SendHeaderNoBatch; the shell's expectation is + * noted in the DRP Context Block passed to drpService. a shell + * that registers itself as expecting batched headers need not + * implement a SetResponseHeader callback. + */ + +/* UNIMPLEMENTED */ + +/** + * SendHeaderNoBatch_fn + * Send HTTP response status and header(s) to user agent (browser); + * headers will have been provided already via SetResponseHeader callback, + * and must be sent with this callback. + * pShellData: shell-specific (request-specific) data object + * iStatusCode: HTTP status code (e.g. 200) + * iStatusMesg: optional status message for HTTP status line + * iMesgLength: number of relevant bytes in iStatusMesg; test iMesgLength + * rather than iStatusMesg for presence of message + * return: 0 == success; !0 == failure + * note: a CM shell implementation need implement only one of + * SendHeaderBatch or SendHeaderNoBatch; the shell's expectation is + * noted in the DRP Context Block passed to drpService. a shell + * that registers itself as expecting batched headers need not + * implement a SetResponseHeader callback. + */ + +int SendHeaderNoBatch + (void *pShellData, drpInt iStatusCode, const char *iStatusMesg, + size_t iMesgLength) { + httpTtrans *t = (httpTtrans *) pShellData; + + httpFset_status(t, iStatusCode, NULL); + httpFstart_response(t); + httpFsend_response(t); + + return 0; +} + +/** + * SetResponseHeader_fn + * Set a single HTTP response header name-value pair, to be sent to the agent + * when SendHeaderNoBatch is invoked. + * pShellData: shell-specific (request-specific) data object + * iHeaderName: name of response header (ascii, null-terminated) + * iHeaderValue: value of response header (ascii, null-terminated) + * return: 0 == success; !0 == failure + * note: a shell that registers itself as expecting batched headers need not + * implement a SetResponseHeader callback. + */ + +int SetResponseHeader + (void *pShellData, const growBuffer * iHeaderName, + const growBuffer * iHeaderValue) { + httpTtrans *t = (httpTtrans *) pShellData; + + /* strFtolower(iHeaderName->buffer); */ + + /* remove in case we already have it */ + lstFset_delete_key(t->res_hdrs, iHeaderName->buffer); + lstFset_add(t->res_hdrs, iHeaderName->buffer, iHeaderValue->buffer); + + return 0; +} + +/** + * cmldrpInitialize + * Initializes the CMLDRP subsystem and initiates the first attempt to + * obtain DRP server information from a CMLDRP server (in the multiprocess + * case) or starts the CMLDRP thread (in the multithreaded case). + * iNumServers: number of CMLDRP server info blocks in iServers + * iServers: array of CMLDRP_ServerInfo objects + * iBindAddress: address to which CMLDRP subsystem should bind its socket + * (NULL: bind to any appropriate local address) + * iHTTPPort: main service port of the host HTTP server (for purposes of + * identifying this CMLDRP client to the CMLDRP server). + * iLogFunction: http-server-API-specific logging routine + * iLogShellData: opaque shellData object to be passed to iLogFunction + * return: 0 == success; !0 == failure + */ + +/* + * cmldrpInitialize(int iNumServers, CMLDRP_ServerInfo * iServers, const char * + * iBindAddress, unsigned short iHTTPPort, LogMessage_fn iLogFunction, void * + * iLogShellData) { + */ + +int dynamoFinit(void *p, lstTset * o) +{ + CMLDRP_ServerInfo server; + char *host = lstFset_get(o, "cmldrp_host"); + char *port = lstFset_get(o, "cmldrp_port"); + + logFmsg(0, "mod/dynamo: Dynamo Connection Manager v.%s (module)", + kCM_VersionNumber); + logFmsg(0, "mod/dynamo: Copyright (c) 2003, Alex Leigh"); + logFmsg(0, "mod/dynamo: Copyright (c) 1997, Art Technology Group"); + + if (host == NULL || port == NULL) { + logFmsg(2, + "mod/dynamo: cmldrp_host and cmldrp_port not configured! Exiting.."); + exit(5); + } + server.host = malloc(strlen(host) + 1); + strcpy(server.host, host); + server.port = atoi(port); + + logFmsg(0, "mod/dynamo: Using CMLDDRP server %s:%s", host, port); + + return cmldrpInitialize(1, &server, NULL, 8990, &logHook, NULL); +} + +/** + * DefinedLength_fn + * Return the length of the shell-specific ascii representation of the + * indicated DRP defined string. + * iDefined: DRP defined string String-ID. + * return: length of shell's representation of iDefined; 0 if the shell has + * no representation for iDefined + */ +/* + * typedef int (* DefinedLength_fn) (drpByte iDefined); + */ + +int definedLength(void *shellData, drpByte iDefined) +{ + return 0; +} + +/** + * DefinedAscii_fn + * Return the (null-terminated) shell-specific ascii representation of the + * indicated DRP defined string. + * iDefined: DRP defined string String-ID. + * return: shell's representation of iDefined; NULL if the shell has no + * representation for iDefined. + */ +/* + * typedef const char * (* DefinedAscii_fn) (drpByte iDefined); + */ + +int definedAscii(void *shellData, drpByte iDefined) +{ + return NULL; +} + + +int dynamoFsession(httpTtrans * t, lstTset * arg) +{ + char *path = lstFset_get(t->vars, "uri"); + char *session; + + session = strstr(path, ";$sessionid"); + + if (session != NULL) { + *session = '\0'; /* truncate the session */ + session++; + lstFset_add(t->vars, "drp-session", session); + } + return STATUS_PROCEED; +} + +int dynamoFservice(httpTtrans * trans, lstTset * arg) +{ + drpContextBlock *gClientData = NULL; + int ret; + +#ifdef DEBUG + logFmsg(3, "mod/dynamo: dynamoFservice called."); +#endif + + tasFstat_counter_add("http_svc", 0, "dynamoFservice", 1); + + gClientData = (drpContextBlock *) malloc(sizeof(drpContextBlock)); + memset(gClientData, 0, sizeof(drpContextBlock)); + + drpReset(gClientData); + + gClientData->getParameter = &GetParameter; + gClientData->getNthHeader = &GetNthHeader; + gClientData->readFromAgent = &ReadFromAgent; + gClientData->writeToAgent = &WriteToAgent; + gClientData->flushData = &FlushData; + gClientData->closeData = &CloseData; + gClientData->sendHeaderBatch = NULL; + gClientData->sendHeaderNoBatch = &SendHeaderNoBatch; + gClientData->setResponseHeader = &SetResponseHeader; + gClientData->definedStringLength = &definedLength; + gClientData->definedStringToAscii = &definedAscii; + gClientData->logMessage = &logHook; + + gClientData->shellExpectsHeaderPairs = 1; /* not batched */ + gClientData->shellData = (void *) trans; + + /* set request logging */ + /* gClientData->isLoggedRequest = 1; */ + + /* set debugging */ + gClientData->debugEnabled = 1; + + /* Max DRP connect timeout */ + gClientData->maxConnectTimeout = 30; + + ret = drpService(gClientData); + + if (ret != 0) { + httpFset_status(trans, 500, "drpService() failed."); + httpFstart_response(trans); + httpFsend_response(trans); + httpFerror_page(trans, "drpService() failed."); + } + return STATUS_EXIT; +} diff --git a/lc-continuity/mk4/moddynamo/io.c b/lc-continuity/mk4/moddynamo/io.c new file mode 100644 index 0000000000000000000000000000000000000000..6f852750912f8127ca97a4c84c974dbb1eb1383c --- /dev/null +++ b/lc-continuity/mk4/moddynamo/io.c @@ -0,0 +1,1672 @@ +/* io.c: + * + * Implementation of buffered streams. + * + * Copyright (C) 1997 Art Technology Group, Inc. + * All Rights Reserved. No use, copying or distribution of this + * work may be made except in accordance with a valid license + * agreement from Art Technology Group. This notice must be + * included on all copies, modifications and derivatives of this + * work. + */ + +#include "DRPTypes.h" +#include "io.h" +#include "DynSock.h" + + +#define DEFAULT_BUFFER_SIZE 4098 + + +/*--------------------------------------------------------------- + * External Globals + */ + +#ifdef _ISAPI +/* + * Our own heap for handling frequent memory allocations. + */ +extern HANDLE gHeap; +#endif + + +static const char *IOStatusMessages[IOStatusCount] = { + "Succeeded", + "Generic failure", + "Feature has not been implemented", + "No more data", + "Read error", + "Write error", + "Bad URL", + "Unknown host", + "No more sockets", + "Connection refused", + "Network error", + "Memory exhausted", + "No more files can be opened", + "No such file", + "Permission denied", + "Buffer overflow", + "Protocol error", + "Protocol version mismatch", + "Operation failed due to excessive time", + "Socket system initialization failed", +}; + +#ifdef WIN32 +/*----------------------------------------------------------------------------- + * Used to manage WinSock subsystem initialization + */ +static BOOL WinsockInitialized = FALSE; + +static IOStatus initializeWinsock() +{ + WSADATA info; + if (WSAStartup(MAKEWORD(1, 1), &info) != 0) + return IOStatusInitializationFailed; + return IOStatusOk; +} +#endif /* WIN32 */ + +/*----------------------------------------------------------------------------- + * Returns a human-readable string describing the indicated IOStatus value. + */ +const char *getIOStatusString(IOStatus status) +{ + if ((status >= 0) && (status < IOStatusCount)) + return IOStatusMessages[(int) status]; + else + return "Unknown status value"; +} + +/*----------------------------------------------------------------------------- + * Creates a buffered input stream. + * Returns NULL if unable to create a stream because out of memory. + */ +InputStream *createInputStream(void *handle, + InputStreamReader reader, + InputStreamCloser closer, int bufferSize) +{ +#ifdef _ISAPI + InputStream *retStream = HeapAlloc(gHeap, 0, sizeof(InputStream)); +#else + InputStream *retStream = malloc(sizeof(InputStream)); +#endif + if (retStream == NULL) + return NULL; + + memset(retStream, 0, sizeof(InputStream)); + + if (bufferSize <= 0) + bufferSize = DEFAULT_BUFFER_SIZE; + if (retStream != NULL) { + retStream->handle = handle; + retStream->reader = reader; + retStream->closer = closer; + retStream->bufferSize = bufferSize; + retStream->timeout = 0; + retStream->status = IOStatusOk; +#ifdef _ISAPI + retStream->buffer = HeapAlloc(gHeap, 0, bufferSize); + if (retStream->buffer == NULL) { + (void) HeapFree(gHeap, 0, retStream); + retStream = NULL; + } +#else + retStream->buffer = malloc(bufferSize); + if (retStream->buffer == NULL) { + free(retStream); + retStream = NULL; + } +#endif + } + return retStream; +} + +/*----------------------------------------------------------------------------- + * Fills the buffer of an input stream as much as immediately possible. Waits + * for more input if none is immediately available. This is intended for + * internal use. + */ +IOStatus fillInputStream(InputStream * stream) +{ + int spaceAvail; + int bytesRead; + + if (stream->readp == stream->avail) /* reset read pointers */ + stream->readp = stream->avail = 0; + spaceAvail = stream->bufferSize - stream->avail; + if (spaceAvail > 0) { + stream->status = + stream->reader(stream->handle, &stream->buffer[stream->readp], + spaceAvail, stream->timeout, &bytesRead); + if (stream->status == IOStatusOk) + stream->avail += bytesRead; + } + return stream->status; +} + +/*----------------------------------------------------------------------------- + * Reads some data from an input stream. + */ +IOStatus readSomeFromInputStream(InputStream * stream, void *retBuffer, + int size, int *retBytesRead) +{ + /* if the buffer is empty, fill it. + */ + if (stream->readp == stream->avail) + fillInputStream(stream); + + /* return as much data from the read buffer as we can. + */ + if (size > stream->avail - stream->readp) + size = stream->avail - stream->readp; + memcpy(retBuffer, &stream->buffer[stream->readp], size); + stream->readp += size; + *retBytesRead = size; + return stream->status; +} + +/*----------------------------------------------------------------------------- + * Reads as much data as is requested from an input stream, if possible. + */ +IOStatus readFromInputStream(InputStream * stream, void *retBuffer, + int size, unsigned int *read) +{ + char *bp = retBuffer; + while ((stream->status == IOStatusOk) && (size > 0)) { + int bytesToCopy; + + if (stream->avail == stream->readp) + fillInputStream(stream); + bytesToCopy = stream->avail - stream->readp; + if (bytesToCopy > size) + bytesToCopy = size; + memcpy(bp, &stream->buffer[stream->readp], bytesToCopy); + stream->readp += bytesToCopy; + bp += bytesToCopy; + size -= bytesToCopy; + } + *read = size; + return stream->status; +} + +/*----------------------------------------------------------------------------- + * Destroys an input stream, closing its source if a closer function was specified. + */ +IOStatus destroyInputStream(InputStream * stream) +{ + IOStatus status = IOStatusOk; + if (stream->closer != NULL) + status = stream->closer(stream->handle); +#ifdef _ISAPI + (void) HeapFree(gHeap, 0, stream->buffer); + (void) HeapFree(gHeap, 0, stream); +#else + free(stream->buffer); + free(stream); +#endif + return status; +} + +/*----------------------------------------------------------------------------- + * Creates a buffered output stream. + * Returns NULL if unable to create a stream because out of memory. + */ +OutputStream *createOutputStream(void *handle, + OutputStreamWriter writer, + OutputStreamCloser closer, int bufferSize) +{ +#ifdef _ISAPI + OutputStream *retStream = HeapAlloc(gHeap, 0, sizeof(OutputStream)); +#else + OutputStream *retStream = malloc(sizeof(OutputStream)); +#endif + if (retStream == NULL) + return NULL; + + memset(retStream, 0, sizeof(OutputStream)); + + if (bufferSize <= 0) + bufferSize = DEFAULT_BUFFER_SIZE; + if (retStream != NULL) { + retStream->handle = handle; + retStream->writer = writer; + retStream->closer = closer; + retStream->bufferSize = bufferSize; + retStream->status = IOStatusOk; +#ifdef _ISAPI + retStream->buffer = HeapAlloc(gHeap, 0, bufferSize); + if (retStream->buffer == NULL) { + (void) HeapFree(gHeap, 0, retStream); + retStream = NULL; + } +#else + retStream->buffer = malloc(bufferSize); + if (retStream->buffer == NULL) { + free(retStream); + retStream = NULL; + } +#endif + } + return retStream; +} + +/*----------------------------------------------------------------------------- + * Writes data to a buffered output stream. + */ +IOStatus writeToOutputStream(OutputStream * stream, const void *buf, + int size) +{ + const char *bp = (const char *) buf; + while ((stream->status == IOStatusOk) && (size > 0)) { + /* if the buffer is empty and the data to write is larger than + * the buffer, send it straight through the writer to avoid the copy. + */ + if ((stream->writep == 0) && (size > stream->bufferSize)) { + stream->status = stream->writer(stream->handle, bp, size); + break; + } else { + int bytesToCopy = stream->bufferSize - stream->writep; + if (bytesToCopy > size) + bytesToCopy = size; + memcpy(&stream->buffer[stream->writep], bp, bytesToCopy); + bp += bytesToCopy; + stream->writep += bytesToCopy; + size -= bytesToCopy; + + /* if the buffer is full, flush it. */ + if (stream->writep == stream->bufferSize) { + stream->status = + stream->writer(stream->handle, stream->buffer, + stream->bufferSize); + stream->writep = 0; + } + } + } + return stream->status; +} + +/*----------------------------------------------------------------------------- + * Flushes buffered data to the output stream. + */ +IOStatus flushOutputStream(OutputStream * stream) +{ + if (stream->writep > 0) { + stream->status = + stream->writer(stream->handle, stream->buffer, stream->writep); + stream->writep = 0; + } + return stream->status; +} + +/*----------------------------------------------------------------------------- + * Copies an InputStream to an OutputStream. + */ +IOStatus copyToOutputStream(OutputStream * outStream, + InputStream * inStream) +{ + IOStatus status; + + /* copy any buffered input directly to the output + */ + if (inStream->readp < inStream->avail) { + status = writeToOutputStream(outStream, + &inStream->buffer[inStream->readp], + inStream->avail - inStream->readp); + inStream->avail = inStream->readp = 0; + if (status != IOStatusOk) + return status; + } + + /* flush the output buffer + */ + status = flushOutputStream(outStream); + + /* at this point both the input and output buffers are completely + * empty, allowing us to read directly into the output buffer and + * avoid a copy. + */ + while (status == IOStatusOk) { + int br; + + /* read a chunk of data */ + status = + inStream->reader(inStream->handle, outStream->buffer, + outStream->bufferSize, inStream->timeout, + &br); + if (status != IOStatusOk) { + if (status == IOStatusNoMoreData) + return IOStatusOk; + else + break; + } + + /* write the chunk of data */ + status = + outStream->writer(outStream->handle, outStream->buffer, br); + } + return status; +} + +/*----------------------------------------------------------------------------- + * Destroys an output stream, flushing its buffered data and closing its + * destination if a closer function was specified. + */ +IOStatus destroyOutputStream(OutputStream * stream) +{ + IOStatus status = IOStatusOk; + flushOutputStream(stream); + if (stream->closer != NULL) + status = stream->closer(stream->handle); +#ifdef _ISAPI + (void) HeapFree(gHeap, 0, stream->buffer); + (void) HeapFree(gHeap, 0, stream); +#else + free(stream->buffer); + free(stream); +#endif + return status; +} + +/*----------------------------------------------------------------------------- + * Flushes deferred output buffers to the raw output stream. + */ +static IOStatus flushDeferredOutputStreamBuffers(DeferredOutputStreamHandle + * doh) +{ + IOStatus status = IOStatusOk; + DeferredOutputStreamBuffer *dob = doh->deferredBuffers; + while (dob != NULL) { + DeferredOutputStreamBuffer *oldDob = dob; + dob = dob->next; + if (status == IOStatusOk) + status = + writeToOutputStream(doh->rawOutputStream, oldDob->buffer, + oldDob->bufferSize); +#ifdef _ISAPI + (void) HeapFree(gHeap, 0, oldDob->buffer); + (void) HeapFree(gHeap, 0, oldDob); +#else + free(oldDob->buffer); + free(oldDob); +#endif + } + doh->deferredBuffers = doh->lastDeferredBuffer = NULL; + if (status == IOStatusOk) + status = flushOutputStream(doh->rawOutputStream); + return status; +} + +/*----------------------------------------------------------------------------- + * Destroys both an input and output streams and handles the case when + * the two streams share the same handle. + * + * When you destroy a stream, you close its dynamo handle. In this + * case we are closing two streams. If these streams have the same + * handle then closing the same handle twice may be bad. For example + * closing the same dynamo socket more than once is bad because you + * will free the same memory more than once. + * + * To prevent this from happening in the case where both streams have + * the same handle we explicitly close the handle once and then set + * the closer functions of each stream to NULL so that they will not + * close their handles when they are destroyed. + */ +IOStatus destroyIOStreams(InputStream * pInStream, + OutputStream * pOutStream) +{ + IOStatus status = IOStatusOk, tempStatus; + if (pInStream && pOutStream) { + if (pInStream->handle && pInStream->handle == pOutStream->handle) { + tempStatus = pInStream->closer(pInStream->handle); + pInStream->closer = NULL; + pOutStream->closer = NULL; + } + status = destroyInputStream(pInStream); + status = destroyOutputStream(pOutStream); + } else if (pInStream) + status = destroyInputStream(pInStream); + else if (pOutStream) + status = destroyOutputStream(pOutStream); + + return status; +} + +/*----------------------------------------------------------------------------- + + * Handles deferred output buffering. + */ +static IOStatus deferredOutputWriter(void *handle, const void *buf, + int size) +{ + DeferredOutputStreamHandle *doh = + (DeferredOutputStreamHandle *) handle; + OutputStream *myOutStream = doh->myOutputStream; + + if (size == 0) + return IOStatusOk; + if (doh->mode == OutputDeferred) { +#ifdef _ISAPI + DeferredOutputStreamBuffer *dob = (DeferredOutputStreamBuffer *) + HeapAlloc(gHeap, HEAP_ZERO_MEMORY, + sizeof(DeferredOutputStreamBuffer)); +#else + DeferredOutputStreamBuffer *dob = (DeferredOutputStreamBuffer *) + calloc(1, sizeof(DeferredOutputStreamBuffer)); +#endif + if (dob == NULL) + return IOStatusMemoryExhausted; /* Doh! */ + + /* if we're writing the entire output stream buffer, just move the + * buffer into the buffer list and allocate a new one. this avoids + * a buffer copy in some common cases. + */ + if ((buf == myOutStream->buffer) + && (size == myOutStream->bufferSize)) { + dob->buffer = myOutStream->buffer; + dob->bufferSize = size; + + /* create a new output stream buffer + */ +#ifdef _ISAPI + myOutStream->buffer = + HeapAlloc(gHeap, 0, myOutStream->bufferSize); + if (myOutStream->buffer == NULL) { + (void) HeapFree(gHeap, 0, dob->buffer); + (void) HeapFree(gHeap, 0, dob); + return IOStatusMemoryExhausted; + } +#else + myOutStream->buffer = malloc(myOutStream->bufferSize); + if (myOutStream->buffer == NULL) { + free(dob->buffer); + free(dob); + return IOStatusMemoryExhausted; + } +#endif + } + + /* move written data into a buffer in the buffer list. + */ + else { +#ifdef _ISAPI + dob->buffer = HeapAlloc(gHeap, 0, size); + if (dob->buffer == NULL) { + (void) HeapFree(gHeap, 0, dob); + return IOStatusMemoryExhausted; + } +#else + dob->buffer = malloc(size); + if (dob->buffer == NULL) { + free(dob); + return IOStatusMemoryExhausted; + } +#endif + dob->bufferSize = size; + memcpy(dob->buffer, buf, size); + } + + /* append the new buffer to the deferred buffer list. + */ + if (doh->lastDeferredBuffer == NULL) + doh->deferredBuffers = dob; + else + doh->lastDeferredBuffer->next = dob; + doh->lastDeferredBuffer = dob; + + return IOStatusOk; + } else /* pass-through mode */ + return writeToOutputStream(doh->rawOutputStream, buf, size); +} + +/*----------------------------------------------------------------------------- + * Flushes deferred output and cleans up the handle. + */ +static IOStatus deferredOutputFinalizer(void *handle) +{ + DeferredOutputStreamHandle *doh = + (DeferredOutputStreamHandle *) handle; + IOStatus status = flushDeferredOutputStreamBuffers(doh); + destroyOutputStream(doh->rawOutputStream); + free(doh); + return status; +} + +/*----------------------------------------------------------------------------- + * Creates a deferred (buffered) output stream. + */ +IOStatus createDeferredOutputStream(OutputStream * rawOutputStream, + OutputStream ** retStream) +{ + OutputStream *outStream; +#ifdef _ISAPI + DeferredOutputStreamHandle *handle = + HeapAlloc(gHeap, HEAP_ZERO_MEMORY, + sizeof(DeferredOutputStreamHandle)); +#else + DeferredOutputStreamHandle *handle = + calloc(1, sizeof(DeferredOutputStreamHandle)); +#endif + if (handle == NULL) + return IOStatusMemoryExhausted; + outStream = + createOutputStream(handle, deferredOutputWriter, + deferredOutputFinalizer, -1); + if (outStream == NULL) { +#ifdef _ISAPI + (void) HeapFree(gHeap, 0, handle); +#else + free(handle); +#endif + return IOStatusMemoryExhausted; + } + handle->myOutputStream = outStream; + handle->rawOutputStream = rawOutputStream; + handle->mode = OutputDeferred; + *retStream = outStream; + return IOStatusOk; +} + +/*----------------------------------------------------------------------------- + * Changes the deferred output stream mode between buffered and passed-through. + */ +IOStatus setDeferredOutputMode(OutputStream * outStream, + DeferredOutputStreamMode mode) +{ + IOStatus status; + DeferredOutputStreamHandle *doh = + (DeferredOutputStreamHandle *) outStream->handle; + switch (mode) { + case OutputDeferred: + status = IOStatusOk; + doh->mode = mode; + break; + case OutputPassedThrough: + status = flushOutputStream(outStream); + if (status == IOStatusOk) + status = flushDeferredOutputStreamBuffers(doh); + doh->mode = mode; + break; + default: + status = IOStatusFailed; /* silly user, tricks are for kids */ + break; + } + return status; +} + +/*----------------------------------------------------------------------------- + * Writes all deferred output to the raw output stream. + */ +IOStatus writeDeferredOutput(OutputStream * outStream) +{ + return flushDeferredOutputStreamBuffers((DeferredOutputStreamHandle *) + outStream->handle); +} + +/*----------------------------------------------------------------------------- + * Given a host name and port number, this returns an internet address. + */ +IOStatus getSocketAddress(const char *hostname, int port, + struct sockaddr_in * retAddress) +{ + struct sockaddr_in address; + struct hostent *hp; + +#ifdef WIN32 + if (!WinsockInitialized) { + IOStatus status = initializeWinsock(); + if (status != IOStatusOk) + return status; + } +#endif /* WIN32 */ + + /* create an internet address from the host name and port number. + */ + hp = gethostbyname(hostname); + if (hp == NULL) + return IOStatusUnknownHost; + memset(&address, 0, sizeof(struct sockaddr_in)); + memcpy((char *) &address.sin_addr, hp->h_addr, hp->h_length); + address.sin_family = hp->h_addrtype; + address.sin_port = htons((unsigned short) port); + *retAddress = address; + return IOStatusOk; +} + +#ifdef WIN32 +/*----------------------------------------------------------------------------- + * Connects a socket to a server and returns input and output streams for it, + * or fails if a connection cannot be established in a given number of + * milliseconds. + * + * FIXME: Because createSocketIOStreamsFromAddressWithTimeout() is + * only supported on WIN32, this function can only be supported on + * WIN32. + */ +IOStatus createSocketIOStreamsWithTimeout(const char *hostname, int port, + int timeout, + InputStream ** retInStream, + OutputStream ** retOutStream) +{ + struct sockaddr_in address; + IOStatus status = getSocketAddress(hostname, port, &address); + if (status != IOStatusOk) + return status; + return createSocketIOStreamsFromAddressWithTimeout(address, timeout, + retInStream, + retOutStream); +} +#endif + +#ifdef WIN32 +/**************************************************** + * Win32-specific I/O stream implementations follow * + ****************************************************/ + +/*----------------------------------------------------------------------------- + * Converts a WIN32 "last error" value to an IOStatus value. + */ +static IOStatus lastErrorToIOStatus() +{ + switch (GetLastError()) { + case ERROR_FILE_NOT_FOUND: + case ERROR_PATH_NOT_FOUND: + case ERROR_INVALID_DRIVE: + case ERROR_BAD_UNIT: + case ERROR_BAD_NETPATH: + case ERROR_NETNAME_DELETED: + case ERROR_BAD_NET_NAME: + return IOStatusNoSuchFile; + case ERROR_ACCESS_DENIED: + case ERROR_WRITE_PROTECT: + case ERROR_SHARING_VIOLATION: + case ERROR_LOCK_VIOLATION: + case ERROR_SHARING_BUFFER_EXCEEDED: + case ERROR_NETWORK_ACCESS_DENIED: + return IOStatusPermissionDenied; + break; + case ERROR_NO_MORE_FILES: + case ERROR_TOO_MANY_SESS: + case ERROR_REQ_NOT_ACCEP: + return IOStatusNoMoreFiles; + case ERROR_OUTOFMEMORY: + case ERROR_NOT_ENOUGH_MEMORY: + case ERROR_OUT_OF_STRUCTURES: + return IOStatusMemoryExhausted; + case ERROR_CRC: + case ERROR_SEEK: + case ERROR_SECTOR_NOT_FOUND: + case ERROR_READ_FAULT: + return IOStatusReadError; + case ERROR_WRITE_FAULT: + case ERROR_HANDLE_DISK_FULL: + case ERROR_NET_WRITE_FAULT: + case ERROR_DISK_FULL: + return IOStatusWriteError; + case ERROR_HANDLE_EOF: + return IOStatusNoMoreData; + case ERROR_REM_NOT_LIST: + case ERROR_NETWORK_BUSY: + case ERROR_DEV_NOT_EXIST: + case ERROR_ADAP_HDW_ERR: + case ERROR_BAD_NET_RESP: + case ERROR_UNEXP_NET_ERR: + case ERROR_BAD_REM_ADAP: + return IOStatusNetworkError; + default: + return IOStatusFailed; + } +} + +/*----------------------------------------------------------------------------- + */ +static IOStatus handleReader(void *handle, void *retBuf, int size, + int timeout, int *retBytesRead) +{ + if (!ReadFile + ((HANDLE) handle, retBuf, size, (LPDWORD) retBytesRead, NULL)) + return IOStatusFailed; + else if (*retBytesRead == 0) + return IOStatusNoMoreData; + else + return IOStatusOk; +} + +/*----------------------------------------------------------------------------- + */ +static IOStatus handleWriter(void *handle, const void *buf, int size) +{ + const char *bp = (const char *) buf; + while (size > 0) { + DWORD bytesWritten; + if (!WriteFile((HANDLE) handle, bp, size, &bytesWritten, NULL)) + return IOStatusFailed; + bp += bytesWritten; + size -= bytesWritten; + } + return IOStatusOk; +} + +/*----------------------------------------------------------------------------- + */ +static IOStatus handleCloser(void *handle) +{ + CloseHandle((HANDLE) handle); + return IOStatusOk; +} + +/*----------------------------------------------------------------------------- + */ +static IOStatus socketReader(void *handle, void *retBuf, int size, + int timeout, int *retBytes) +{ + SOCKET sock = (SOCKET) handle; + + for (;;) { + int br; + + if (timeout > 0) { + fd_set readfds; + struct timeval timeout_val; + + FD_ZERO(&readfds); + FD_SET(sock, &readfds); + timeout_val.tv_sec = timeout / 1000; + timeout_val.tv_usec = timeout % 1000; + if (select(1, &readfds, NULL, NULL, &timeout_val) == + SOCKET_ERROR) + return IOStatusFailed; + if (!FD_ISSET(sock, &readfds)) + return IOStatusTimeout; + } + + br = recv(sock, retBuf, size, 0); + if (br == 0) { + *retBytes = 0; + return IOStatusNoMoreData; + } + if (br == SOCKET_ERROR) { + *retBytes = 0; + switch (WSAGetLastError()) { + case WSAEINTR: + continue; + case WSAECONNRESET: + return IOStatusNoMoreData; /* same thing */ + case WSAENETDOWN: + case WSAENETUNREACH: + case WSAENETRESET: + case WSAECONNABORTED: + case WSAEHOSTUNREACH: + case WSAEDISCON: + return IOStatusNetworkError; + default: + return IOStatusFailed; + } + } + *retBytes = br; + return IOStatusOk; + } +} + +/*----------------------------------------------------------------------------- + */ +static IOStatus socketWriter(void *handle, const void *buf, int size) +{ + SOCKET sock = (SOCKET) handle; + const char *bp = (const char *) buf; + + while (size > 0) { + int bw; + + bw = send(sock, bp, size, 0); + if (bw == SOCKET_ERROR) { + switch (WSAGetLastError()) { + case WSAEINTR: + continue; + case WSAENETDOWN: + case WSAENETUNREACH: + case WSAENETRESET: + case WSAECONNABORTED: + case WSAECONNRESET: + case WSAEHOSTUNREACH: + case WSAEDISCON: + return IOStatusNetworkError; + default: + return IOStatusFailed; + } + } + bp += bw; + size -= bw; + } + return IOStatusOk; +} + +/*----------------------------------------------------------------------------- + */ +static IOStatus socketCloser(void *handle) +{ + closesocket((SOCKET) handle); + return IOStatusOk; +} + +/*----------------------------------------------------------------------------- + * Creates (opens) a new file input stream. + */ +IOStatus createFileInputStream(const char *filename, + InputStream ** retStream) +{ + IOStatus status; + HANDLE handle = CreateFile(filename, + GENERIC_READ, +#if 1 + (FILE_SHARE_READ | FILE_SHARE_WRITE), +#else + FILE_SHARE_READ, +#endif + NULL, /* security */ + OPEN_EXISTING, + (FILE_ATTRIBUTE_NORMAL | + FILE_FLAG_SEQUENTIAL_SCAN), + INVALID_HANDLE_VALUE); + if (handle == INVALID_HANDLE_VALUE) { + status = lastErrorToIOStatus(); + } else { + status = createHandleInputStream(handle, TRUE, retStream); + if (status != IOStatusOk) + CloseHandle(handle); + } + return status; +} + +/*----------------------------------------------------------------------------- + * Creates (opens) a new file output stream. + */ +IOStatus createFileOutputStream(const char *filename, + OutputStream ** retStream) +{ + IOStatus status; + HANDLE handle = CreateFile(filename, + GENERIC_WRITE, +#if 1 + (FILE_SHARE_READ | FILE_SHARE_WRITE), +#else + 0, /* exclusive write */ +#endif + NULL, /* security */ + (CREATE_ALWAYS /*|TRUNCATE_EXISTING */ ), + FILE_ATTRIBUTE_NORMAL, + INVALID_HANDLE_VALUE); + if (handle == INVALID_HANDLE_VALUE) { + switch (GetLastError()) { + default: + status = IOStatusFailed; + } + } else { + status = createHandleOutputStream(handle, TRUE, retStream); + if (status != IOStatusOk) + CloseHandle(handle); + } + return status; +} + +/*----------------------------------------------------------------------------- + * Wraps a generic I/O handle with an input stream. + */ +IOStatus createHandleInputStream(HANDLE handle, int doClose, + InputStream ** retStream) +{ + *retStream = createInputStream((void *) handle, handleReader, + (doClose ? handleCloser : NULL), + DEFAULT_BUFFER_SIZE); + if (*retStream == NULL) + return IOStatusMemoryExhausted; + else + return IOStatusOk; +} + +/*----------------------------------------------------------------------------- + * Wraps a generic I/O handle with an output stream. + */ +IOStatus createHandleOutputStream(HANDLE handle, int doClose, + OutputStream ** retStream) +{ + *retStream = createOutputStream((void *) handle, handleWriter, + (doClose ? handleCloser : NULL), + DEFAULT_BUFFER_SIZE); + if (*retStream == NULL) + return IOStatusMemoryExhausted; + else + return IOStatusOk; +} + +/*----------------------------------------------------------------------------- + * Wraps a SOCKET with an input stream. + */ +IOStatus createSocketInputStream(SOCKET sock, int doClose, + InputStream ** retStream) +{ + *retStream = createInputStream((void *) sock, socketReader, + (doClose ? socketCloser : NULL), + DEFAULT_BUFFER_SIZE); + if (*retStream == NULL) + return IOStatusMemoryExhausted; + else + return IOStatusOk; +} + +/*----------------------------------------------------------------------------- + * Wraps a SOCKET with an output stream. + */ +IOStatus createSocketOutputStream(SOCKET sock, int doClose, + OutputStream ** retStream) +{ + *retStream = createOutputStream((void *) sock, socketWriter, + (doClose ? socketCloser : NULL), + DEFAULT_BUFFER_SIZE); + if (*retStream == NULL) + return IOStatusMemoryExhausted; + else + return IOStatusOk; +} + +/*----------------------------------------------------------------------------- + * Given a socket address structure, this connects a socket to a server and + * returns input and output streams for it. + * FIXME: Needs to be upgraded to support DynSock. + */ +IOStatus createSocketIOStreamsFromAddressWithTimeout(struct sockaddr_in + address, int timeout, + InputStream ** + retInStream, + OutputStream ** + retOutStream) +{ + int address_size = sizeof(struct sockaddr_in); + SOCKET sock; + IOStatus status; + + *retInStream = NULL; + *retOutStream = NULL; + if (!WinsockInitialized) { + IOStatus status = initializeWinsock(); + if (status != IOStatusOk) + return status; + } + /* create socket and socket event structures */ + sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock == SOCKET_ERROR) { + status = IOStatusNoMoreSockets; + goto cleanupAndFail; + } + + if (timeout > 0) { + DWORD blocking = 1; + if (ioctlsocket(sock, FIONBIO, &blocking) == SOCKET_ERROR) { + status = IOStatusFailed; + goto cleanupAndFail; + } + } + + if (connect(sock, (struct sockaddr *) &address, address_size) == + SOCKET_ERROR) { + switch (WSAGetLastError()) { + case WSAEWOULDBLOCK: /* ok so far */ + break; + case WSAECONNREFUSED: + status = IOStatusConnectionRefused; + goto cleanupAndFail; + default: + status = IOStatusFailed; + goto cleanupAndFail; + } + + /* wait for socket to connect */ + { + fd_set writefds; + fd_set exceptfds; + struct timeval timeout_val; + int result; + + FD_ZERO(&writefds); + FD_SET(sock, &writefds); + FD_ZERO(&exceptfds); + FD_SET(sock, &exceptfds); + timeout_val.tv_sec = timeout / 1000; + timeout_val.tv_usec = timeout % 1000; + result = select(1, NULL, &writefds, &exceptfds, &timeout_val); + if (result == SOCKET_ERROR) { + status = IOStatusFailed; + goto cleanupAndFail; + } + + /* see if connection failed */ + if (FD_ISSET(sock, &exceptfds)) { + status = IOStatusConnectionRefused; + goto cleanupAndFail; + } + + /* see if connection timed out */ + if (!FD_ISSET(sock, &writefds)) { + status = IOStatusTimeout; + goto cleanupAndFail; + } + } + + /* put socket back into blocking mode */ + if (timeout > 0) { + DWORD blocking = 0; + if (ioctlsocket(sock, FIONBIO, &blocking) == SOCKET_ERROR) { + status = IOStatusFailed; + goto cleanupAndFail; + } + } + } + + /* wrap the socket with I/O streams */ + status = createSocketInputStream(sock, TRUE, retInStream); + if (status != IOStatusOk) + goto cleanupAndFail; + status = createSocketOutputStream(sock, TRUE, retOutStream); + if (status != IOStatusOk) + goto cleanupAndFail; + + /* thank you for using AT&T */ + return IOStatusOk; + + cleanupAndFail: + if (*retInStream != NULL) + destroyInputStream(*retInStream); + if (*retOutStream != NULL) + destroyOutputStream(*retOutStream); + if (sock != SOCKET_ERROR) + closesocket(sock); + return status; +} + +#else /* assume it is UNIX */ + +/*************************************************** + * Unix-specific I/O stream implementations follow * + ***************************************************/ + +#include +#include +#include + +/*----------------------------------------------------------------------------- + * Converts a UNIX errno value to an IOStatus value + */ +static IOStatus errnoToIOStatus(int value) +{ + switch (value) { + case 0: + return IOStatusOk; + case ECONNREFUSED: + return IOStatusConnectionRefused; + case ENETDOWN: + case ENETUNREACH: + case ENETRESET: + case ECONNABORTED: + case ECONNRESET: + case EHOSTUNREACH: + return IOStatusNetworkError; + case ENOENT: + return IOStatusNoSuchFile; + case EPERM: + return IOStatusPermissionDenied; + default: + return IOStatusFailed; + } +} + +/*----------------------------------------------------------------------------- + */ +static IOStatus fdReader(void *handle, void *buf, int size, + int timeout, int *retBytesRead) +{ + int br; + + for (;;) { + if (timeout > 0) { + for (;;) { + int nfds; + struct pollfd read_fds[1]; + read_fds[0].fd = (int) handle; + read_fds[0].events = POLLIN; + read_fds[0].revents = 0; + nfds = poll(read_fds, 1, timeout); + if (nfds < 0) { + switch (errno) { + case EINTR: + continue; + default: + return IOStatusFailed; + } + } else if (nfds == 0) + return IOStatusTimeout; + else /* have data */ + goto doRead; + } + } + + doRead: + br = read((int) handle, buf, size); + if (br <= 0) { + *retBytesRead = 0; + if (br == 0) + return IOStatusNoMoreData; + switch (errno) { + case EINTR: + continue; + case EIO: /* old macdonald had a farm */ + return IOStatusReadError; + default: + return errnoToIOStatus(errno); + } + } + *retBytesRead = br; + return IOStatusOk; + } +} + +/*----------------------------------------------------------------------------- + */ +static IOStatus fdWriter(void *handle, const void *buf, int size) +{ + const char *bp = (const char *) buf; + while (size > 0) { + int bw = write((int) handle, bp, size); + if (bw < 0) { + switch (errno) { + case EINTR: + continue; + case EIO: /* old macdonald had a farm */ + return IOStatusWriteError; + default: + return errnoToIOStatus(errno); + } + } + bp += bw; + size -= bw; + } + return IOStatusOk; +} + +static IOStatus fdCloser(void *handle) +{ + if (close((int) handle) < 0) + return IOStatusFailed; + else + return IOStatusOk; +} + + /**/ +/*----------------------------------------------------------------------------- + */ +static IOStatus dynSockReader(void *handle, void *buf, int size, + int timeout, int *retBytesRead) +{ + int br; + + for (;;) { + if (timeout > 0) { + for (;;) { + int nfds; + struct pollfd read_fds[1]; + read_fds[0].fd = dynSocket_socket((dynSocket *) handle); + read_fds[0].events = POLLIN; + read_fds[0].revents = 0; + nfds = poll(read_fds, 1, timeout); + if (nfds < 0) { + switch (errno) { + case EINTR: + continue; + default: + return IOStatusFailed; + } + } else if (nfds == 0) + return IOStatusTimeout; + else /* have data */ + goto doRead; + } + } + + doRead: + br = dynSocket_read((dynSocket *) handle, buf, size); + if (br <= 0) { + *retBytesRead = 0; + if (br == 0) + return IOStatusNoMoreData; + switch (errno) { + case EINTR: + continue; + case EIO: /* old macdonald had a farm */ + return IOStatusReadError; + default: + return errnoToIOStatus(errno); + } + } + *retBytesRead = br; + return IOStatusOk; + } +} + +/*----------------------------------------------------------------------------- + */ +static IOStatus dynSockWriter(void *handle, const void *buf, int size) +{ + const char *bp = (const char *) buf; + while (size > 0) { + int bw = dynSocket_write((dynSocket *) handle, bp, size); + if (bw < 0) { + switch (errno) { + case EINTR: + continue; + case EIO: /* old macdonald had a farm */ + return IOStatusWriteError; + default: + return errnoToIOStatus(errno); + } + } + bp += bw; + size -= bw; + } + return IOStatusOk; +} + +static IOStatus dynSockCloser(void *handle) +{ + if (dynSocket_close((dynSocket *) handle) == ATG_SOCKET_ERROR) + return IOStatusFailed; + else + return IOStatusOk; +} + +/*----------------------------------------------------------------------------- + * Creates (opens) a new file input stream. + */ +IOStatus createFileInputStream(const char *filename, + InputStream ** retStream) +{ + int fd = open(filename, O_RDONLY); + if (fd < 0) { + IOStatus status; + switch (errno) { + case EIO: + status = IOStatusWriteError; + break; + default: + status = errnoToIOStatus(errno); + break; + } + *retStream = NULL; + return status; + } + *retStream = createInputStream((void *) fd, fdReader, fdCloser, -1); + if (*retStream == NULL) + return IOStatusMemoryExhausted; + else + return IOStatusOk; +} + +/*----------------------------------------------------------------------------- + * Creates (opens) a new file output stream. + */ +IOStatus createFileOutputStream(const char *filename, + OutputStream ** retStream) +{ + int fd = open(filename, O_WRONLY); + if (fd < 0) { + IOStatus status; + switch (errno) { + case EIO: + status = IOStatusWriteError; + break; + default: + status = errnoToIOStatus(errno); + break; + } + *retStream = NULL; + return status; + } + *retStream = createOutputStream((void *) fd, fdWriter, fdCloser, -1); + if (*retStream == NULL) + return IOStatusMemoryExhausted; + else + return IOStatusOk; +} + +/*----------------------------------------------------------------------------- + * Wraps a file descriptor with an input stream + */ +IOStatus createFdInputStream(int fd, int doClose, InputStream ** retStream) +{ + *retStream = createInputStream((void *) fd, fdReader, + (doClose ? fdCloser : NULL), + DEFAULT_BUFFER_SIZE); + if (*retStream == NULL) + return IOStatusMemoryExhausted; + else + return IOStatusOk; +} + +/*----------------------------------------------------------------------------- + * Wraps a file descriptor with an output stream. + */ +IOStatus createFdOutputStream(int fd, int doClose, + OutputStream ** retStream) +{ + *retStream = createOutputStream((void *) fd, fdWriter, fdCloser, + DEFAULT_BUFFER_SIZE); + if (*retStream == NULL) + return IOStatusMemoryExhausted; + else + return IOStatusOk; +} + +/*----------------------------------------------------------------------------- + * Wraps a dynSocket with an input stream + */ +IOStatus createDynSocketInputStream(dynSocket * s, int doClose, + InputStream ** retStream) +{ + *retStream = createInputStream((void *) s, dynSockReader, + (doClose ? dynSockCloser : NULL), + DEFAULT_BUFFER_SIZE); + if (*retStream == NULL) + return IOStatusMemoryExhausted; + else + return IOStatusOk; +} + +/*----------------------------------------------------------------------------- + * Wraps a dynSocket with an output stream. + */ +IOStatus createDynSocketOutputStream(dynSocket * s, int doClose, + OutputStream ** retStream) +{ + *retStream = + createOutputStream((void *) s, dynSockWriter, dynSockCloser, + DEFAULT_BUFFER_SIZE); + if (*retStream == NULL) + return IOStatusMemoryExhausted; + else + return IOStatusOk; +} + +/*----------------------------------------------------------------------------- + * Sleeps for a given number of milliseconds. + */ +/* NOTE: Currently not used so not defined. - Frank Kim, 12/28/99 */ +#if 0 +static void millisecondWait(int ms) +{ + poll(NULL, 0, ms); +} +#endif + +/*----------------------------------------------------------------------------- + * Given a socket address structure, this connects a socket to a server and + * returns input and output streams for it. + * + * FIXME: This function never worked reliably on UNIX hence the reason + * Allan Scott wrote createSocketIOStreamsFromAddressWithBlocking(). + * For now this function is NOT DEFINED so that no one will use it. + * + * Here is what Jim Frost, the author of this function, says on + * 3/2/2001. + * + * I had a lot of trouble getting it to work on Solaris in my tests. + * I literally tried every single technique I could think of to do + * the timeout -- there were several OS bugs that I found in the + * process (usually the connection success would not be reported as + * it should have been). I had thought I'd worked it out, but IIRC + * one or another of you guys had to go back in there because it + * still wasn't working right. It may well have been an issue of + * Solaris version -- I did my tests on the old Solaris/Intel box, + * not on a SPARC box. + * + * I kind of blame this on the really crappy socket implementation + * on SysV/Solaris. + */ +#if 0 +IOStatus createSocketIOStreamsFromAddressWithTimeout(struct sockaddr_in + address, int timeout, + InputStream ** + retInStream, + OutputStream ** + retOutStream) +{ + int address_size = sizeof(struct sockaddr_in); + dynSocket *sock; + IOStatus status, tempStatus; + int sock_flags, temp; +#ifndef FIONBIO + int orig_sock_flags; +#endif /* !SOLARIS */ + + *retInStream = NULL; + *retOutStream = NULL; + sock = dynSocket_new((void *) IO_SOCKET); + if (sock == ATG_INVALID_DYNSOCKET) { + status = IOStatusNoMoreSockets; + return status; + } + + /* if a timeout was specified, set socket up as nonblocking so we can + * determine if it has been too long. + */ + if (timeout > 0) { +#ifdef FIONBIO + + /* if FIONBIO is defined, use it. this is necessary on Solaris where + * sockets do not honor O_NONBLOCK. + */ + sock_flags = 1; + if (ioctl(dynSocket_socket(sock), FIONBIO, &sock_flags) < 0) + return IOStatusFailed; + +#else /* !FIONBIO */ + + /* if FIONBIO is not defined, try to set nonblocking mode using either + * the POSIX O_NONBLOCK or the BSD O_NDELAY. + */ + orig_sock_flags = fcntl(dynSocket_socket(sock), F_GETFL); + if (orig_sock_flags == -1) + return IOStatusFailed; +#ifdef O_NONBLOCK /* POSIX-style nonblocking */ + sock_flags = orig_sock_flags | O_NONBLOCK; +#else /* !O_NONBLOCK */ +#ifdef O_NDELAY /* BSD-style nonblocking */ + sock_flags = orig_sock_flags | O_NDELAY; +#endif /* O_NDELAY */ +#endif /* !O_NONBLOCK */ + if (fcntl(dynSocket_socket(sock), F_SETFL, orig_sock_flags) < 0) + return IOStatusFailed; +#endif /* !FIONBIO */ + } + + /* start the connection request. */ + for (;;) { + if (dynSocket_connect + (sock, (struct sockaddr *) &address, address_size) + == ATG_SOCKET_ERROR) { + switch (errno) { + case EINTR: + continue; + case EALREADY: + case EINPROGRESS: + case EISCONN: + goto waitForConnection; + default: + status = errnoToIOStatus(errno); + temp = dynSocket_close(sock); + return status; + } + } + } + + waitForConnection: + /* if timeout was specified, wait for the connection to finish */ + if (timeout > 0) { + struct pollfd fds[1]; + int result; + + fds[0].fd = dynSocket_socket(sock); + fds[0].events = POLLOUT; + fds[0].revents = 0; + + result = poll(fds, 1, timeout); + if (result < 0) { + switch (errno) { + case EINTR: + goto waitForConnection; + default: + return errnoToIOStatus(errno); + } + } else if (result == 0) { + status = IOStatusTimeout; + temp = dynSocket_close(sock); + return status; + } + + /* check the status of the connect request */ + if (dynSocket_connect + (sock, (struct sockaddr *) &address, address_size) + == ATG_SOCKET_ERROR) { + switch (errno) { + case EISCONN: + break; + default: + return errnoToIOStatus(errno); + } + } + + /* restore socket to blocking mode */ +#ifdef FIONBIO + sock_flags = 0; + if (ioctl(dynSocket_socket(sock), FIONBIO, &sock_flags) < 0) + return IOStatusFailed; +#else /* !FIONBIO */ + fcntl(dynSocket_socket(sock), F_SETFL, orig_sock_flags); +#endif /* !FIONBIO */ + } + + /* wrap the socket with I/O streams */ + status = createDynSocketInputStream(sock, TRUE, retInStream); + if (status != IOStatusOk) { + tempStatus = destroyIOStreams(*retInStream, NULL); + return status; + } + status = createDynSocketOutputStream(sock, TRUE, retOutStream); + if (status != IOStatusOk) { + tempStatus = destroyIOStreams(*retInStream, *retOutStream); + return status; + } + + /* thank you for using AT&T */ + return IOStatusOk; +} +#endif /* #if 0 */ + +/*----------------------------------------------------------------------------- + * Given a socket address structure, this connects a socket to a server and + * returns input and output streams for it. This uses a blocking socket. + */ +IOStatus +createSocketIOStreamsFromAddressWithBlocking(struct sockaddr_in address, + InputStream ** retInStream, + OutputStream ** retOutStream) +{ + int address_size = sizeof(struct sockaddr_in); + dynSocket *sock = ATG_INVALID_DYNSOCKET; + IOStatus status, tempStatus; + *retInStream = NULL; + *retOutStream = NULL; + + /* start the connection request. */ + { + int tries = 0, temp; + + /* try to create a dynamo socket */ + sock = dynSocket_new(NULL); + if (sock == ATG_INVALID_DYNSOCKET) { + status = IOStatusNoMoreSockets; + return status; + } + + while (1) { + + /* try to connect to server specified by address */ + if (dynSocket_connect + (sock, (struct sockaddr *) &address, address_size) + != ATG_SOCKET_ERROR) { + /* successfully connected, break out of the loop */ + break; + } + + /* did not successfully connect to server */ + switch (errno) { + + case EINTR: + + /* The connection attempt was interrupted before any data + arrived by the delivery of a signal. Try to connect again. + Eventually after several tries if it does not connect you + will get an ETIMEDOUT */ + continue; + case ETIMEDOUT: + + /* Timed out while attempting connection. The server may be + too busy to accept new connections. Close this socket and + try to create another one. */ + + status = errnoToIOStatus(errno); + + temp = dynSocket_close(sock); + sock = dynSocket_new(NULL); + if (sock == ATG_INVALID_DYNSOCKET) { + status = IOStatusNoMoreSockets; + return status; + } + break; + default: + status = errnoToIOStatus(errno); + temp = dynSocket_close(sock); + if (status == IOStatusOk) + return IOStatusConnectionRefused; + return status; + } + + tries++; + if (tries == 3) { + temp = dynSocket_close(sock); + if (status == IOStatusOk) + return IOStatusConnectionRefused; + return status; + } + } + } + + /* At this point we have successfully connected to the server with + our socket. Wrap this socket with I/O streams */ + status = createDynSocketInputStream(sock, TRUE, retInStream); + if (status != IOStatusOk) { + tempStatus = destroyIOStreams(*retInStream, NULL); + *retInStream = NULL; + return status; + } + + status = createDynSocketOutputStream(sock, TRUE, retOutStream); + if (status != IOStatusOk) { + tempStatus = destroyIOStreams(*retInStream, *retOutStream); + *retInStream = NULL; + *retOutStream = NULL; + return status; + } + + return IOStatusOk; +} + +#endif /* WIN32 */ diff --git a/lc-continuity/mk4/moddynamo/io.h b/lc-continuity/mk4/moddynamo/io.h new file mode 100644 index 0000000000000000000000000000000000000000..a549731a7ce4b3386cf714ed3af0772d30fc0fb6 --- /dev/null +++ b/lc-continuity/mk4/moddynamo/io.h @@ -0,0 +1,341 @@ +#ifndef _IO_H_ +#define _IO_H_ +/* io.h: + * + * Copyright (C) 1997 Art Technology Group, Inc. + * All Rights Reserved. No use, copying or distribution of this + * work may be made except in accordance with a valid license + * agreement from Art Technology Group. This notice must be + * included on all copies, modifications and derivatives of this + * work. + */ + +#include "system.h" + +/* IOStatus error values. + * + * WARNING: IF YOU CHANGE THIS, YOU MUST ALSO INSERT THE TEXT VERSION OF YOUR + * NEW ERROR(S) IN THE CORRESPONDING MESSAGE TABLE IN sockpool.c. + */ +typedef enum IOStatus +{ + IOStatusOk = 0, + IOStatusFailed, + IOStatusNotImplemented, + IOStatusNoMoreData, + IOStatusReadError, + IOStatusWriteError, + IOStatusBadUrl, + IOStatusUnknownHost, + IOStatusNoMoreSockets, + IOStatusConnectionRefused, + IOStatusNetworkError, + IOStatusMemoryExhausted, + IOStatusNoMoreFiles, + IOStatusNoSuchFile, + IOStatusPermissionDenied, + IOStatusBufferOverflow, + IOStatusProtocolError, + IOStatusProtocolVersionMismatch, + IOStatusTimeout, + IOStatusInitializationFailed, + IOStatusCount +} IOStatus; + +typedef enum IOStreamOption { + IOStreamOptionTimeout = 1 +} IOStreamOption; + +#define IO_SOCKET 1001 + +/* Returns a human-readable string describing the indicated IOStatus value. + */ +const char* getIOStatusString(IOStatus status); + +/* Signature of an input stream reader function. The reader must read as much + * data as is immediately available, but never return before reading something. + */ +typedef IOStatus (*InputStreamReader)(void* handle, void* buf, int size, + int timeout, int* written); + +/* Signature of an input stream closer function. If NULL is passed for one of + * these, it is not closed when the stream is destroyed. + */ +typedef IOStatus (*InputStreamCloser)(void* handle); + +/* Signature of an output stream writer function. The writer must not return + * until all information has been written. + */ +typedef IOStatus (*OutputStreamWriter)(void* handle, const void* buf, int size); + +/* Signature of an output stream closer function. If NULL is passed for one + * of these, it is not closed when the stream is destroyed. + */ +typedef IOStatus (*OutputStreamCloser)(void* handle); + +/* An input stream structure. + */ +typedef struct InputStream +{ + void* handle; + InputStreamReader reader; + InputStreamCloser closer; + char* buffer; + int bufferSize; + int avail; + int readp; + int timeout; /* length of time to wait for input, in ms */ + IOStatus status; /* status of last source read */ +} InputStream; + +/* An output stream structure. + */ +typedef struct OutputStream +{ + void* handle; + OutputStreamWriter writer; + OutputStreamCloser closer; + char* buffer; + int bufferSize; + int writep; + IOStatus status; +} OutputStream; + +/* Creates a buffered input stream. + */ +InputStream* createInputStream(void* handle, + InputStreamReader reader, + InputStreamCloser closer, + int bufferSize); + +/* Fills the buffer of an input stream as much as immediately possible. Waits + * for more input if none is immediately available. This is intended for + * internal use. + */ +IOStatus fillInputStream(InputStream* stream); + +/* Reads some data from an input stream. + */ +IOStatus readSomeFromInputStream(InputStream* stream, void* buf, int size, int* bytesRead); + +/* Reads as much data as is requested from an input stream, if possible. + */ +IOStatus readFromInputStream(InputStream* stream, void* retBuffer, int size, unsigned int *read); + +/* Fast way to read a single character from an input stream. + */ +#define readCharFromInputStream(STREAM, RETCHAR) \ + (((STREAM)->readp == (STREAM)->avail ? fillInputStream(STREAM) : \ + IOStatusOk),\ + ((STREAM)->readp < (STREAM)->avail ? \ + (*(RETCHAR) = (STREAM)->buffer[(STREAM)->readp++]), IOStatusOk : \ + (STREAM)->status)) + +/* Pushes the last char read back onto the input stream. This is + * only valid if the last InputStream operation was readCharFromInputSTream(). + */ +#define pushCharBackOnInputStream(STREAM) \ + ((STREAM)->readp > 0 ? ((STREAM)->readp--, IOStatusOk) : \ + IOStatusBufferOverflow) + +/* Fast way to write a single character to an output stream. + */ +#define writeCharToOutputStream(STREAM, CHAR) \ + ((STREAM)->buffer[(STREAM)->writep++] = (CHAR), \ + ((STREAM)->writep == (STREAM)->bufferSize ? flushOutputStream(STREAM) : \ + IOStatusOk)) + +/* Destroys an input stream, closing its source if a closer function was + * specified. + */ +IOStatus destroyInputStream(InputStream* stream); + +/* Sets the timeout value, in ms, for an input stream. + */ +#define setInputStreamTimeout(STREAM, TIMEOUT) \ + (STREAM)->timeout = (TIMEOUT) + +/* Creates a buffered output stream. + */ +OutputStream* createOutputStream(void* handle, + OutputStreamWriter writer, + OutputStreamCloser closer, + int bufferSize); + +/* Writes data to a buffered output stream. All data will be written before this returns + * if possible. + */ +IOStatus writeToOutputStream(OutputStream* stream, const void* buf, int size); + +/* Prints a C-style string to the output stream. + */ +#define printToOutputStream(STREAM, STRING) \ + writeToOutputStream((STREAM),(STRING),strlen(STRING)) + +/* Flushes buffered data to the output stream. + */ +IOStatus flushOutputStream(OutputStream* stream); + +/* Copies an InputStream to an OutputStream. + */ +IOStatus copyToOutputStream(OutputStream* outStream, InputStream* inStream); + +/* Destroys an output stream, flushing its buffered data and closing its + * destination if a closer function was specified. + */ +IOStatus destroyOutputStream(OutputStream* stream); + +/* Mode values for deferred output streams. + */ +typedef enum DeferredOutputStreamMode { + OutputDeferred, /* All output buffered */ + OutputPassedThrough /* Buffered output flushed, subsequent output passed through */ +} DeferredOutputStreamMode; + +/* Buffer chain structure for deferred output streams. + */ +typedef struct DeferredOutputStreamBuffer +{ + char* buffer; + int bufferSize; + struct DeferredOutputStreamBuffer* next; +} DeferredOutputStreamBuffer; + +/* Handle information for a deferred output stream + */ +typedef struct DeferredOutputStreamHandle +{ + /* Output stream object that holds this handle + */ + OutputStream* myOutputStream; + + /* Output mode for the stream, either deferred or passed-through. + */ + DeferredOutputStreamMode mode; + + /* Raw output stream. + */ + OutputStream* rawOutputStream; + + /* Chain of deferred output buffers + */ + DeferredOutputStreamBuffer* deferredBuffers; + + /* Last deferred buffer in chain. + */ + DeferredOutputStreamBuffer* lastDeferredBuffer; +} DeferredOutputStreamHandle; + +/* Creates a deferred (buffered) output stream. + */ +IOStatus createDeferredOutputStream(OutputStream* rawOutputStream, OutputStream** retStream); + +/* Returns the raw output stream for a deferred output stream. + */ +#define getRawOutputStreamForDeferred(OUTSTREAM) \ + ((DeferredOutputStreamHandle*)outStream->handle)->rawOutputStream + +/* Changes the deferred output stream mode between buffered and passed-through. + */ +IOStatus setDeferredOutputMode(OutputStream* outStream, DeferredOutputStreamMode mode); + +/* Writes all deferred output to the raw output stream. + */ +IOStatus writeDeferredOutput(OutputStream* outStream); + +/* Creates (opens) a new file input stream. + */ +IOStatus createFileInputStream(const char* filename, InputStream** retStream); + +/* Creates (opens) a new file output stream. + */ +IOStatus createFileOutputStream(const char* filename, OutputStream** retStream); + +/* Connects a socket to a server and returns input and output streams for it. + */ +#define createSocketIOStreams(HOSTNAME, PORT, RETINSTREAM, RETOUTSTREAM) \ + createSocketIOStreamsWithTimeout((HOSTNAME), (PORT), 0, (RETINSTREAM), (RETOUTSTREAM)) + + +#ifdef WIN32 +/* Connects a socket to a server and returns input and output streams for it, + * or fails if a connection cannot be established in a given number of + * milliseconds. + * + * FIXME: Because createSocketIOStreamsFromAddressWithTimeout() is + * only supported on WIN32, this function can only be supported on + * WIN32 + */ +IOStatus createSocketIOStreamsWithTimeout(const char* hostname, int port, + int timeout, + InputStream** retStream, + OutputStream** outStream); +#endif + +/* Creates a new pair of I/O streams around a socket that is connected + * at the indicated address. + */ +#define createSocketIOStreamsFromAddress(ADDR, RETINSTREAM, RETOUTSTREAM) \ + createSocketIOStreamsFromAddressWithTimeout((ADDR), 0, (RETINSTREAM), (RETOUTSTREAM)) + +#ifdef WIN32 +/* FIXME: This function never worked reliably on UNIX hence the reason + * it is only defined on WIN32. + */ +IOStatus +createSocketIOStreamsFromAddressWithTimeout(struct sockaddr_in address, + int timeout, + InputStream** retInStream, + OutputStream** retOutStream); +#endif + +#ifndef WIN32 /* assume it's UNIX */ +IOStatus createSocketIOStreamsFromAddressWithBlocking(struct sockaddr_in address, + InputStream** retInStream, + OutputStream** retOutStream); +#endif + +/* Given a host name and port number, this returns an internet address. + */ +IOStatus getSocketAddress(const char* hostname, int port, struct sockaddr_in* retAddress); + +#ifdef WIN32 +/* Wraps a generic I/O handle with an input stream. + */ +IOStatus createHandleInputStream(HANDLE handle, int doClose, InputStream** retStream); + +/* Wraps a generic I/O handle with an output stream. + */ +IOStatus createHandleOutputStream(HANDLE handle, int doClose, OutputStream** retStream); + +/* Wraps a SOCKET with an input stream. + */ +IOStatus createSocketInputStream(SOCKET sock, int doClose, InputStream** retStream); + +/* Wraps a SOCKET with an output stream. + */ +IOStatus createSocketOutputStream(SOCKET sock, int doClose, OutputStream** retStream); +#endif /* WIN32 */ + +#ifdef UNIX +/* Wraps a file descriptor with an input stream + */ +IOStatus createFdInputStream(int fd, int doClose, InputStream** retStream); + +/* Wraps a file descriptor with an output stream. + */ +IOStatus createFdOutputStream(int fd, int doClose, OutputStream** retStream); +#endif /* UNIX */ + +/* Destroy Input/Output stream pair + */ +IOStatus destroyIOStreams(InputStream* pInStream,OutputStream* pOutStream); + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +#endif /* !_IO_H_ */ diff --git a/lc-continuity/mk4/moddynamo/pageroute.c b/lc-continuity/mk4/moddynamo/pageroute.c new file mode 100644 index 0000000000000000000000000000000000000000..5af3b5ff286234edb691d9fb9820afa704aa1201 --- /dev/null +++ b/lc-continuity/mk4/moddynamo/pageroute.c @@ -0,0 +1,320 @@ +/* pageroute.c + * + * manages routing of pages where a consistent dynamo target is required. + * + * jim frost 11.10.97 + * + * Copyright (C) 1997 Art Technology Group, Inc. + * All Rights Reserved. No use, copying or distribution of this + * work may be made except in accordance with a valid license + * agreement from Art Technology Group. This notice must be + * included on all copies, modifications and derivatives of this + * work. + */ + +#include +#include +#include +#include "pageroute.h" + +#ifdef SOLARIS2 +char *strdup(const char *); /* morons forgot to include it in string.h */ +#endif /* SOLARIS2 */ + +/* An entry in the statically routed page table. + */ +typedef struct RoutedPage { + /* the URL or prefix portion of the URL of a routed page. + */ + char *url; + + /* the length of the URL string to compare if this is a prefix URL. + */ + int prefixLen; + + /* next page in table + */ + struct RoutedPage *next; +} RoutedPage; + +/* The statically routed page table. + */ +static RoutedPage *PageTable; + +#if 1 /* debug code */ +#include +void debugOut(const char *message) +{ + FILE *fp; + + fp = fopen("d:\\debug.log", "a"); + if (fp == NULL) + return; + fwrite(message, 1, strlen(message), fp); + fclose(fp); +} + +void debugOutInt(int value) +{ + char buf[32]; + sprintf(buf, "%d", value); + debugOut(buf); +} +#endif /* debug code */ + +/*---------------------------------------------------------------------------- + * Appends a page or list of pages to the page list. + */ +static void appendPage(RoutedPage * newPage) +{ + if (PageTable == NULL) + PageTable = newPage; + else { + RoutedPage *rp; + + for (rp = PageTable; rp->next != NULL; rp = rp->next) + /* EMPTY */ ; + rp->next = newPage; + } +} + +/*---------------------------------------------------------------------------- + * Looks for a trailing asterisk and sets the prefix length if it finds one. + */ +static void setPrefixValue(RoutedPage * rp) +{ + int len = strlen(rp->url); + if ((len > 0) && (rp->url[len - 1] == '*')) + rp->prefixLen = len - 1; +} + +/*---------------------------------------------------------------------------- + * Adds another statically routed page to the table. + */ +int addStaticallyRoutedPage(const char *pageUrl) +{ + RoutedPage *rp = (RoutedPage *) calloc(1, sizeof(RoutedPage)); + if (rp == NULL) + return 0; + rp->url = strdup(pageUrl); + if (rp->url == NULL) { + free(rp); + return 0; + } + setPrefixValue(rp); + appendPage(rp); + return 1; +} + +/*---------------------------------------------------------------------------- + * Adds a list of URLs (comma-delimited) to the statically routed page table. + */ +int addStaticallyRoutedPageList(const char *pageList) +{ + RoutedPage *newPages = NULL; + RoutedPage *lastPage = NULL; + const char *start = pageList; + const char *end; + + while ((start != NULL) && (*start != '\0')) { + char *url; + RoutedPage *rp; + + /* skip leading comma delimiters + */ + while (*start == ',') + start++; + + /* look for trailing comma delimiter + */ + end = strchr(start, ','); + if (end == NULL) { + url = strdup(start); + if (url == NULL) + goto cleanupAndFail; + } else { + int len = end - start; + url = (char *) malloc(len + 1); + if (url == NULL) + goto cleanupAndFail; + strncpy(url, start, len); + url[len] = '\0'; + } + + rp = (RoutedPage *) calloc(1, sizeof(RoutedPage)); + if (rp == NULL) { + free(url); + goto cleanupAndFail; + } + rp->url = url; + setPrefixValue(rp); + + /* append to the new page list + */ + if (lastPage == NULL) + newPages = lastPage = rp; + else { + lastPage->next = rp; + lastPage = rp; + } + start = end; + } + + /* concatenate the new page and routed page lists. + */ + if (newPages != NULL) + appendPage(newPages); + + return 1; + + cleanupAndFail: + /* clean up anything in the new page list + */ + while (newPages != NULL) { + RoutedPage *oldrp = newPages; + newPages = newPages->next; + if (oldrp->url != NULL) + free(oldrp->url); + free(oldrp); + } + return 0; +} + +/*---------------------------------------------------------------------------- + * Clears the statically routed page table. + */ +void clearStaticallyPageTable(void) +{ + while (PageTable != NULL) { + RoutedPage *oldrp = PageTable; + PageTable = PageTable->next; + if (oldrp->url != NULL) + free(oldrp->url); + free(oldrp); + } +} + +/*---------------------------------------------------------------------------- + * Computes a hash value for a string using a 32-bit CRC. + */ +int getStringHashValue(const char *string) +{ + unsigned int crc32_table[256] = { /* lookup table */ + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, + 0x706AF48F, + 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, + 0x97D2D988, + 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, + 0x6AB020F2, + 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, + 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, + 0x63066CD9, + 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, + 0xA2677172, + 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, + 0x42B2986C, + 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, + 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, + 0x56B3C423, + 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, + 0xB10BE924, + 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, + 0x01DB7106, + 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, + 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, + 0x086D3D2D, + 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, + 0xF262004E, + 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, + 0x12B7E950, + 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, + 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, + 0x3DD895D7, + 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, + 0xDA60B8D0, + 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, + 0x270241AA, + 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, + 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, + 0x2EB40D81, + 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, + 0x74B1D29A, + 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, + 0x94643B84, + 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, + 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, + 0x806567CB, + 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, + 0x67DD4ACC, + 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, + 0xA1D1937E, + 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, + 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, + 0xA867DF55, + 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, + 0x5268E236, + 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, + 0xB2BD0B28, + 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, + 0x5BDEAE1D, + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, + 0xEB0E363F, + 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, + 0x0CB61B38, + 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, + 0xF1D4E242, + 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, + 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, + 0xF862AE69, + 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, + 0x3903B3C2, + 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, + 0xD9D65ADC, + 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, + 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, + 0xCDD70693, + 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, + 0x2A6F2B94, + 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D + }; + + unsigned int crc; /* CRC value */ + int i; + + crc = 0xFFFFFFFF; /* preconditioning sets non zero value */ + /* loop through the file and calculate CRC */ + for (i = 0; string[i] != '\0'; i++) { + int v = (crc ^ string[i]) & 0x000000FF; + crc = ((crc >> 8) & 0x00FFFFFF) ^ crc32_table[v]; + } + + return ~crc; /* postconditioning */ +} + +/*---------------------------------------------------------------------------- + * Returns true if the URL is found in the statically routed page table. + */ +int isStaticallyRoutedPage(const char *url) +{ + RoutedPage *rp; + + for (rp = PageTable; rp != NULL; rp = rp->next) { + if (rp->prefixLen > 0) { /* compare URL prefix rather than a whole URL */ + if (!strncmp(rp->url, url, rp->prefixLen)) + return 1; + } else { + if (!strcmp(rp->url, url)) + return 1; + } + } + return 0; +} diff --git a/lc-continuity/mk4/moddynamo/pageroute.h b/lc-continuity/mk4/moddynamo/pageroute.h new file mode 100644 index 0000000000000000000000000000000000000000..991fd30cd6d3616f8d8c54012f5ee2132cb04d94 --- /dev/null +++ b/lc-continuity/mk4/moddynamo/pageroute.h @@ -0,0 +1,31 @@ +/* pageroute.h: + * + * jim frost 11.10.97 + * + * Copyright (C) 1997 Art Technology Group, Inc. + * All Rights Reserved. No use, copying or distribution of this + * work may be made except in accordance with a valid license + * agreement from Art Technology Group. This notice must be + * included on all copies, modifications and derivatives of this + * work. + */ + +/* Adds another statically routed page to the table. + */ +int addStaticallyRoutedPage(const char* pageUrl); + +/* Adds a list of URLs (comma-delimited) to the statically routed page table. + */ +int addStaticallyRoutedPageList(const char* pageList); + +/* Clears the statically routed page table. + */ +void clearStaticallyRoutedPages(void); + +/* Computes a hash value for a string using a 32-bit CRC. + */ +int getStringHashValue(const char* url); + +/* Returns true if the URL is found in the statically routed page table. + */ +int isStaticallyRoutedPage(const char* url); diff --git a/lc-continuity/mk4/moddynamo/rwLocks.h b/lc-continuity/mk4/moddynamo/rwLocks.h new file mode 100644 index 0000000000000000000000000000000000000000..45c96c75db692fb30380122bfc40a9fc85f3afac --- /dev/null +++ b/lc-continuity/mk4/moddynamo/rwLocks.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 1997 Art Technology Group, Inc. + * All Rights Reserved. No use, copying or distribution of this + * work may be made except in accordance with a valid license + * agreement from Art Technology Group. This notice must be + * included on all copies, modifications and derivatives of this + * work. + * + * Art Technology Group (ATG) MAKES NO REPRESENTATIONS OR WARRANTIES + * ABOUT THE SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. ATG SHALL NOT BE + * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, + * MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. + * + * "Dynamo" is a trademark of Art Technology Group, Inc. + */ + +/* + rwLocks.h - interface for read-write locks + */ + + + +#ifndef _RWLOCKS_H_ +#define _RWLOCKS_H_ + + +#ifdef _DRP_MTHREAD + +#include "threadabstr.h" + + +/*typedef struct _RWLock RWLock; */ + + +/* RWLock: read-write lock object */ +struct _RWLock { + Thread_CSKey critKey; /* critical-section key for this read-write + lock (see threadabstr.h) */ + unsigned int readLocks; /* number of read locks currently held on + this rwlock */ + unsigned int writeLocks; /* number of write locks currently held on + this rwLock (should be 0 or 1) */ + unsigned int writersWaiting; /* number of entities that are currently + trying to obtain a write lock */ +}; + + +/* default timeout values for obtaining read and write locks */ +#define kRWL_DefaultReadTimeout 50 +#define kRWL_DefaultWriteTimeout 100 + + +int initializeRWLock(RWLock * oLock); +void discardRWLock(RWLock * oLock); + +int getReadLock(RWLock * iLock, unsigned long iTimeout); +int releaseReadLock(RWLock * iLock); +int getWriteLock(RWLock * iLock, unsigned long iTimeout); +int releaseWriteLock(RWLock * iLock); + +#else /* i.e. ndef _DRP_MTHREAD */ + +/* define functions to empty macros */ +#define initializeRWLock(l) 0 +#define discardRWLock(l) 0 +#define getReadLock(l,t) 0 +#define releaseReadLock(l) 0 +#define getWriteLock(l,t) 0 +#define releaseWriteLock(l) 0 + +#endif + +#endif diff --git a/lc-continuity/mk4/moddynamo/sockerrs.c b/lc-continuity/mk4/moddynamo/sockerrs.c new file mode 100644 index 0000000000000000000000000000000000000000..71d00c648880b21629e4e264be98432da03c5465 --- /dev/null +++ b/lc-continuity/mk4/moddynamo/sockerrs.c @@ -0,0 +1,220 @@ +/* + * Copyright (C) 2001 Art Technology Group, Inc. + * All Rights Reserved. No use, copying or distribution of this + * work may be made except in accordance with a valid license + * agreement from Art Technology Group. This notice must be + * included on all copies, modifications and derivatives of this + * work. + * + * Art Technology Group (ATG) MAKES NO REPRESENTATIONS OR WARRANTIES + * ABOUT THE SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. ATG SHALL NOT BE + * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, + * MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. + * + * "Dynamo" is a trademark of Art Technology Group, Inc. + */ + +/* + * sockerrs.c -- provides a method for getting human-readable strings from + * error codes (errno on Unix, WSAGetLastError on NT) + */ + +#ifdef WIN32 +/* NT */ +#include +#else +/* UNIXEN */ +#include +#endif + +#include "sockerrs.h" + +/* + * Return the appropriate message string for the error + * pErrno is errno on Unix, the return from WSAGetLastError() on NT + */ +const char *getMessageStringForSocketError(int pErrno) +{ +#if (defined (WIN32)) + char *message; + switch (pErrno) { + case WSAEINTR: + message = "A blocking operation was cancelled (WASEINTR)"; + break; + case WSAEBADF: + message = "Bad file number (WSAEBADF)"; + break; + case WSAEACCES: + message = + "Permission to access socket forbidden by its access permissions (WSAEACCES)"; + break; + case WSAEFAULT: + message = + "Invalid pointer address specified in function call (WSAEFAULT)"; + break; + case WSAEINVAL: + message = "Invalid argument passed to a function (WSAEINVAL)"; + break; + case WSAEMFILE: + message = "Too many open sockets (WSAEMFILE)"; + break; + case WSAEWOULDBLOCK: + message = "Resources temporarily unavailable (WSAEWOULDBLOCK)"; + break; + case WSAEINPROGRESS: + message = "Blocking operation now in progress (WSAEINPROGRESS)"; + break; + case WSAEALREADY: + message = + "Operation already in progress on a non-binding socket (WSAEALREADY)"; + break; + case WSAENOTSOCK: + message = + "Socket operation attempted on a non-socket (WSAENOTSOCK)"; + break; + case WSAEDESTADDRREQ: + message = "Destination address required (WSAEDESTADDRREQ)"; + break; + case WSAEMSGSIZE: + message = "Message too long (WSAEMSGSIZE)"; + break; + case WSAEPROTOTYPE: + message = "Protocol wrong type for socket (WSAEPROTOTYPE)"; + break; + case WSAENOPROTOOPT: + message = + "Unknown, invalid, or unsupported protocol option or level was specified (WSAENOPROTOOPT)"; + break; + case WSAEPROTONOSUPPORT: + message = "Protocol not supported (WSAEPROTONOSUPPORT)"; + break; + case WSAESOCKTNOSUPPORT: + message = + "Socket type not supported in the address family (WSAESOCKTNOSUPPORT)"; + break; + case WSAEOPNOTSUPP: + message = "Operation not supported on socket (WSAEOPNOTSUPP)"; + break; + case WSAEPFNOSUPPORT: + message = "Protocol family not supported (WSAEPFNOSUPPORT)"; + break; + case WSAEAFNOSUPPORT: + message = + "Address family not supported by protocol family (WSAEAFNOSUPPORT)"; + break; + case WSAEADDRINUSE: + message = "Address already in use (WSAEADDRINUSE)"; + break; + case WSAEADDRNOTAVAIL: + message = "Cannot assign requested address (WSAEADDRNOTAVAIL)"; + break; + case WSAENETDOWN: + message = "Network is down (WSAENETDOWN)"; + break; + case WSAENETUNREACH: + message = "Network is unreachable (WSAENETUNREACH)"; + break; + case WSAENETRESET: + message = "Network dropped connection on reset (WSAENETRESET)"; + break; + case WSAECONNABORTED: + message = "Software caused connection abort (WSAECONNABORTED)"; + break; + case WSAECONNRESET: + message = "Connection reset by peer (WSAECONNRESET)"; + break; + case WSAENOBUFS: + message = "No buffer space available (WSAENOBUFS)"; + break; + case WSAEISCONN: + message = "Socket is already connected (WSAEISCONN)"; + break; + case WSAENOTCONN: + message = "Socket is not connected (WSAENOTCONN)"; + break; + case WSAESHUTDOWN: + message = "Cannot send after socket shutdown (WSAESHUTDOWN)"; + break; + case WSAETOOMANYREFS: + message = "Too many references, cannot splice (WSAETOOMANYREFS)"; + break; + case WSAETIMEDOUT: + message = "Connection timed out (WSAETIMEDOUT)"; + break; + case WSAECONNREFUSED: + message = "Connection refused (WSAECONNREFUSED)"; + break; + case WSAELOOP: + message = "Too many levles of symbolic links (WSAELOOP)"; + break; + case WSAENAMETOOLONG: + message = "File name is too long (WSAENAMETOOLONG)"; + break; + case WSAEHOSTDOWN: + message = "Host is down (WSAEHOSTDOWN)"; + break; + case WSAEHOSTUNREACH: + message = "No route to host (WSAEHOSTUNREACH)"; + break; + case WSAENOTEMPTY: + message = "Directory not empty (WSAENOTEMPTY)"; + break; + case WSAEPROCLIM: + message = "Too many processes (WSAEPROCLIM)"; + break; + case WSAEUSERS: + message = "Too many users (WSAEUSERS)"; + break; + case WSAEDQUOT: + message = "Disc quota exceeded (WSAEDQUOT)"; + break; + case WSAESTALE: + message = "Stale NFS file handle (WSAESTALE)"; + break; + case WSAEREMOTE: + message = "Too many levels of remote in path (WSAEREMOTE)"; + break; + case WSAEDISCON: + message = "Graceful shutdown in progress (WSAEDISCON)"; + break; + case WSASYSNOTREADY: + message = "Network subsystem is unavailable (WSASYSNOTREADY)"; + break; + case WSAVERNOTSUPPORTED: + message = "Winsock.dll version out of range (WSAVERNOTSUPPORTED)"; + break; + case WSANOTINITIALISED: + message = + "Successful WSASTARTUP not yet performed (WSANOTINITIALISED)"; + break; + case 10109: /* case WSATYPE_NOT_FOUND */ + message = "Class type not found (WSATYPE_NOT_FOUND)"; + break; + case WSAHOST_NOT_FOUND: + message = "Host not found (WSA_HOST_NOT_FOUND)"; + break; + case WSATRY_AGAIN: + message = "Non-authoritative host not found (WSATRY_AGAIN)"; + break; + case WSANO_RECOVERY: + message = "Non-recoverable error (WSANO_RECOVERY)"; + break; + case WSANO_DATA: + message = + "Valid name, no data record or requested name (WSANO_DATA)"; + break; + default: + message = "WSA error not recognized"; + } + return (message); +#else + if (pErrno == 0) { + const char *message = "Uninterpretable socket error occurred."; + return message; + } else { + return (strerror(pErrno)); + } +#endif +} diff --git a/lc-continuity/mk4/moddynamo/sockerrs.h b/lc-continuity/mk4/moddynamo/sockerrs.h new file mode 100644 index 0000000000000000000000000000000000000000..eb5575659c051f97eaa90331c06d693c8ef8ee00 --- /dev/null +++ b/lc-continuity/mk4/moddynamo/sockerrs.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2001 Art Technology Group, Inc. + * All Rights Reserved. No use, copying or distribution of this + * work may be made except in accordance with a valid license + * agreement from Art Technology Group. This notice must be + * included on all copies, modifications and derivatives of this + * work. + * + * Art Technology Group (ATG) MAKES NO REPRESENTATIONS OR WARRANTIES + * ABOUT THE SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. ATG SHALL NOT BE + * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, + * MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. + * + * "Dynamo" is a trademark of Art Technology Group, Inc. + */ + +/* + sockerrs.h -- provide string messages for socket errors + */ + +#ifndef _SOCKERRS_H +#define _SOCKERRS_H + +/* PROTYPES */ +const char * getMessageStringForSocketError(int pErrno); + +#endif /* _SOCKERRS_H */ diff --git a/lc-continuity/mk4/moddynamo/system.h b/lc-continuity/mk4/moddynamo/system.h new file mode 100644 index 0000000000000000000000000000000000000000..637bbc2c943a9b9321cc2b85acbb70ef73ad86bf --- /dev/null +++ b/lc-continuity/mk4/moddynamo/system.h @@ -0,0 +1,52 @@ +#ifndef _ATG_SYSTEM_H_ +#define _ATG_SYSTEM_H_ +/* system.h: + * + * system-specific includes and definitions. + * + * Copyright (C) 1997 Art Technology Group, Inc. + * All Rights Reserved. No use, copying or distribution of this + * work may be made except in accordance with a valid license + * agreement from Art Technology Group. This notice must be + * included on all copies, modifications and derivatives of this + * work. + */ +#ifdef WIN32 +#include +#include +#include + +#else /* assume it is UNIX */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(SOLARIS) || defined(SOLARIS2) +/* we need to pick up FIONBIO from ioctl.h, which is only defined in BSD + * compatibility mode in Solaris. + */ +#define BSD_COMP +#endif /* SOLARIS */ + +#if defined(AIX) || defined(_AIX) || defined(LINUX) || defined(_HPUX) || defined(OPENBSD) +#include +#endif /* AIX */ + +#include + +#define stricmp strcasecmp +#define strnicmp strncasecmp + +#ifndef LINUX +char* strdup(const char*); +#endif + +#endif /* WIN32 */ + +#endif /* !_ATG_SYSTEM_H_ */ diff --git a/lc-continuity/mk4/moddynamo/threadabstr.c b/lc-continuity/mk4/moddynamo/threadabstr.c new file mode 100644 index 0000000000000000000000000000000000000000..b86ae7dd3a51f4241e4b2c33f5c6bb02e45883c3 --- /dev/null +++ b/lc-continuity/mk4/moddynamo/threadabstr.c @@ -0,0 +1,94 @@ +#pragma ident "$Header: /san01/cvs/ashpool/csrc/moddynamo/Attic/threadabstr.c,v 1.2 2004/03/18 15:04:15 aleigh Exp $" + +/* Copyright (c) 1994, 2001 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH + * The copyright notice above does not evidence any + * actual or intended publication of such source code. + * + * Disclosure, copying, distribution, or transmission of of + * this code without express permission is prohibited. + */ + +/* + * threadabstr.c : evolution thread interface for dynamo CM PURE LIQUID EVIL + * Alex Leigh (aleigh@tessier.com) 2001 + */ + +#include +#include + +#include "threadabstr.h" + +/* + * thread_startNewThread(kThread_defaultStackSize, cmldrpThreadFunction, + * (kThread_argType) pBlock); if (gCMLDRPThread == kThread_InvalidThread) { + * gCMLDRPBlock.logFunction(gCMLDRPBlock.logShellData, kLog_Error, + * kLogMessage_CannotStartCMLDRPThread, NULL, NULL); returnValue = -1; } + */ + +Thread_t thread_startNewThread(int StackSize, void *start_func(void *), + void *arg) +{ + pthread_t tid; + + pthread_create(&tid, NULL, start_func, arg); + + return tid; +} + +/* TODO: This function does not support the timeout value */ +int getReadLock(RWLock * lock, int timeout) +{ + return pthread_rwlock_rdlock(lock); +} + +/* TODO: This function does not support the timeout value */ +int getWriteLock(RWLock * lock, int timeout) +{ + return pthread_rwlock_wrlock(lock); +} + +int releaseWriteLock(RWLock * lock) +{ + return pthread_rwlock_unlock(lock); +} + +int releaseReadLock(RWLock * lock) +{ + return pthread_rwlock_unlock(lock); +} + + +/* if (initializeRWLock(&gLoadDataLock)) { */ +int initializeRWLock(RWLock * lock) +{ + return pthread_rwlock_init(lock, NULL); +} + +int thread_return(int retval) +{ + pthread_exit(NULL); +} + +/* TODO: Unsafe assumptions about timespec and tm */ +int thread_sleep(int ms) +{ + pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; + pthread_cond_t cond = PTHREAD_COND_INITIALIZER; + struct timeval now; + struct timespec then; + int deltams; + +/* logFmsg(0,"thread_sleep: called [tid: 0x%x] [ms: %d]", pthread_self(), ms); */ + gettimeofday(&now, NULL); + + deltams = (now.tv_usec / 1000) + ms; + + then.tv_sec = now.tv_sec + (deltams / 1000); + then.tv_nsec = (deltams % 1000) * 1000000; + + pthread_cond_timedwait(&cond, &mut, (struct timespec *) &then); + + return 0; +} diff --git a/lc-continuity/mk4/moddynamo/threadabstr.h b/lc-continuity/mk4/moddynamo/threadabstr.h new file mode 100644 index 0000000000000000000000000000000000000000..8d644a7da3a74eea94375d0035a88fff92b161e5 --- /dev/null +++ b/lc-continuity/mk4/moddynamo/threadabstr.h @@ -0,0 +1,28 @@ +/* Copyright (c) 1994, 2001 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH + * The copyright notice above does not evidence any + * actual or intended publication of such source code. + * + * Disclosure, copying, distribution, or transmission of of + * this code without express permission is prohibited. + */ + +#ifndef _TA_THREADABSTR_H +#define _TA_THREADABSTR_H + +#pragma ident "$Header: /san01/cvs/ashpool/csrc/moddynamo/Attic/threadabstr.h,v 1.1 2003/12/12 15:08:04 aleigh Exp $" + +#include + +#define Thread_CSKey pthread_mutex_t * +#define kThread_returnType void * +#define kThread_argType void * +#define Thread_t pthread_t +#define kThread_defaultStackSize 4096 /* !! */ +#define kThread_InvalidThread NULL + +typedef pthread_rwlock_t RWLock; + +#endif + diff --git a/lc-continuity/mk4/modexample/CVS/Entries b/lc-continuity/mk4/modexample/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..b86e9226b466cf78dcd5f1851b78a9d314121f68 --- /dev/null +++ b/lc-continuity/mk4/modexample/CVS/Entries @@ -0,0 +1,5 @@ +/Makefile/1.2/Mon Apr 26 14:28:52 2004//Tmk4_mod6_rc2 +/auth.c/1.2/Thu Mar 18 15:04:15 2004//Tmk4_mod6_rc2 +/example.c/1.2/Thu Mar 18 15:04:15 2004//Tmk4_mod6_rc2 +/hello.c/1.2/Thu Mar 18 15:04:15 2004//Tmk4_mod6_rc2 +D diff --git a/lc-continuity/mk4/modexample/CVS/Repository b/lc-continuity/mk4/modexample/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..2717d10d5bbb14b425f65b158e2a9aee10e661f6 --- /dev/null +++ b/lc-continuity/mk4/modexample/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/modexample diff --git a/lc-continuity/mk4/modexample/CVS/Root b/lc-continuity/mk4/modexample/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/modexample/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/modexample/CVS/Tag b/lc-continuity/mk4/modexample/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/modexample/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/modexample/Makefile b/lc-continuity/mk4/modexample/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..c33ded29b7eab1982c652b5ca64d2e785b530410 --- /dev/null +++ b/lc-continuity/mk4/modexample/Makefile @@ -0,0 +1,23 @@ +# $Header: /san01/cvs/ashpool/csrc/modexample/Attic/Makefile,v 1.2 2004/04/26 14:28:52 aleigh Exp $ + +include ../continuity/lib/env.mk + +SRCS=example.c +OBJS=example.o + +CFLAGS=-I../continuity/include $(CONT_FLAGS) + +world: install + +example.so: $(OBJS) + $(LD_SHARECMD) -o example.so $(OBJS) +clean: + $(RM) $(OBJS) *~ example.so + +install: example.so + cp example.so ../continuity/lib + + +depend: + makedepend $(DEPFLAGS) -I ../continuity/include $(SRCS) + diff --git a/lc-continuity/mk4/modexample/auth.c b/lc-continuity/mk4/modexample/auth.c new file mode 100644 index 0000000000000000000000000000000000000000..8f7bbe11655888abbe1e21c8f00d0d9d8175f1fc --- /dev/null +++ b/lc-continuity/mk4/modexample/auth.c @@ -0,0 +1,59 @@ +#include +#include + +int check_user(const char *username, const char *password); +int require_authentication(httpTtrans * t, lstTset * opt); + +/* + * Check to see if the username and password are valid. + * Return 1 if they are, 0 if they are not + */ +int check_user(const char *username, const char *password) +{ + if (strcmp(username, "admin") == 0 && strcmp(password, "pencil") == 0) + return 1; + return 0; +} + +int require_authentication(httpTtrans * t, lstTset * opt) +{ + char *authorization = lstFset_get(t->req_hdrs, "authorization"); + char b64decode[64]; + int ret; + char *u = NULL, *p = NULL; + char *st_p; + + authorization = lstFset_get(t->req_hdrs, "authorization"); + + if (authorization != NULL) { + bzero(b64decode, 64); + + ret = + b64Fdecode(authorization + 6, (unsigned char *) b64decode, + sizeof(b64decode)); + b64decode[ret] = '\0'; + + u = strtok_r(b64decode, ":", &st_p); + p = strtok_r(NULL, ":", &st_p); + + if (u != NULL && p != NULL) { + ret = check_user(u, p); + + if (ret == 1) { + lstFset_add(t->vars, "auth-type", "basic"); + lstFset_add(t->vars, "auth-user", u); + return STATUS_PROCEED; + } + } + } + + /* require authentication */ + httpFset_status(t, HTTP_UNAUTHORIZED, NULL); + lstFset_add(t->res_hdrs, "WWW-authenticate", + "basic realm=\"Members Area\""); + + httpFstart_response(t); + httpFwrite(t, "Authorization required.", 24); + + return STATUS_EXIT; +} diff --git a/lc-continuity/mk4/modexample/example.c b/lc-continuity/mk4/modexample/example.c new file mode 100644 index 0000000000000000000000000000000000000000..e18efb1ecafa89a01d07adea1434bbec6517d448 --- /dev/null +++ b/lc-continuity/mk4/modexample/example.c @@ -0,0 +1,16 @@ +#include +#include + +int redirector(httpTtrans * t, lstTset * opt); + +int redirector(httpTtrans * t, lstTset * opt) +{ + const char *target; + + target = httpFquery_val(t, "target"); + + if (target == NULL) + return STATUS_PROCEED; + + return httpFredirect(t, target); +} diff --git a/lc-continuity/mk4/modexample/hello.c b/lc-continuity/mk4/modexample/hello.c new file mode 100644 index 0000000000000000000000000000000000000000..b2208452d54b1ecc2172ca007d8ee9eb3ab6c9ec --- /dev/null +++ b/lc-continuity/mk4/modexample/hello.c @@ -0,0 +1,19 @@ +#include +#include + +int my_handler(httpTtrans * t, lstTset * opts); + +int my_handler(httpTtrans * t, lstTset * opts) +{ + const char *hello = "Hello World\n"; + + assert(t != NULL); + + httpFset_status(t, 200, NULL); + httpFstart_response(t); + + httpFwrite(t, hello, strlen(hello)); + + /* we have served the request, so exit the pipeline */ + return STATUS_EXIT; +} diff --git a/lc-continuity/mk4/modharmony/CVS/Entries b/lc-continuity/mk4/modharmony/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..8ef189fc49e78e9bcd2e8664502492800a8dbeb0 --- /dev/null +++ b/lc-continuity/mk4/modharmony/CVS/Entries @@ -0,0 +1,5 @@ +/Makefile.in/1.1/Fri May 7 20:22:30 2004//Tmk4_mod6_rc2 +/harmony.c/1.4/Mon May 10 15:38:03 2004//Tmk4_mod6_rc2 +/harmony.h/1.2/Fri May 7 20:38:46 2004//Tmk4_mod6_rc2 +/hproto.h/1.1/Mon May 10 15:38:03 2004//Tmk4_mod6_rc2 +D diff --git a/lc-continuity/mk4/modharmony/CVS/Repository b/lc-continuity/mk4/modharmony/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..dd8ab090113728d3611432ba319b1b2269908033 --- /dev/null +++ b/lc-continuity/mk4/modharmony/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/modharmony diff --git a/lc-continuity/mk4/modharmony/CVS/Root b/lc-continuity/mk4/modharmony/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/modharmony/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/modharmony/CVS/Tag b/lc-continuity/mk4/modharmony/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/modharmony/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/modharmony/Makefile.in b/lc-continuity/mk4/modharmony/Makefile.in new file mode 100644 index 0000000000000000000000000000000000000000..16674fafcb9812b56c1bc19bc224f60084dd4fc7 --- /dev/null +++ b/lc-continuity/mk4/modharmony/Makefile.in @@ -0,0 +1,21 @@ +# $Header: /san01/cvs/ashpool/csrc/modharmony/Attic/Makefile.in,v 1.1 2004/05/07 20:22:30 aleigh Exp $ + +include ../continuity/lib/env.mk + +SRCS=harmony.c +OBJS=harmony.o + +CFLAGS=-I../continuity/include $(CONT_FLAGS) + +world: install + +harmony.so: $(OBJS) + $(LD_SHARECMD) -o harmony.so $(OBJS) +clean: + $(RM) $(OBJS) *~ harmony.so + +install: harmony.so + (rm -f ../continuity/lib/harmony.so ; cp harmony.so ../continuity/lib) + cp harmony.h ../continuity/include +depend: + $(MAKEDEPEND) -I../continuity/include $(DEPFLAGS) $(SRCS) diff --git a/lc-continuity/mk4/modharmony/harmony.c b/lc-continuity/mk4/modharmony/harmony.c new file mode 100644 index 0000000000000000000000000000000000000000..7f4fdaf63119142d07237baf552f4b5f781e63d9 --- /dev/null +++ b/lc-continuity/mk4/modharmony/harmony.c @@ -0,0 +1,140 @@ +/* $Id: harmony.c,v 1.4 2004/05/10 15:38:03 aleigh Exp $ */ + +/* + * Copyright (c) 1994, 2001 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Use, disclosure, copying, distribution, or transmission of this code without + * express permission is prohibited. + */ + +#include "harmony.h" +#include "hproto.h" + +#define MCAST_GROUP "225.0.0.37" + +static int harGbcast_socket; +static int harGcid; +static unsigned int harGhostid; + +static int harFhandle_pkt(const char *data, size_t data_len); +static void harFlisten_thread(void); +static uint32_t harFframe_crc(const harTframe_hdr *hdr); + +#define MSGBUFSIZE 1024 + +static uint32_t harFframe_crc(const harTframe_hdr *hdr) { + return htonl(crcFcrc32((const unsigned char *)hdr,sizeof(uint32_t)*4)); +} + +static void harFlisten_thread(void) +{ + struct sockaddr_in addr; + char msgbuf[MSGBUFSIZE]; + int nbytes,addrlen; + + logFmsg(3,"Started."); + + while (1) { + addrlen=sizeof(addr); + + if ((nbytes=recvfrom(harGbcast_socket,msgbuf,MSGBUFSIZE,0, + NULL,0)) < 0) { + logFmsg(2,"recvfrom() failed. [e: %d]", errno); + } + harFhandle_pkt(msgbuf,nbytes); + } +} + +static int harFhandle_pkt(const char *data, size_t data_len) { + harTframe_hdr *frame; + + frame=(harTframe_hdr *)data; + + if(data_lenframe_crc) { + logFmsg(3,"CRC does not match; discarding corrupt packet."); + return 0; + } + + logFmsg(3,"rcv'd packet %u -> %u", frame->from_addr, frame->rcpt_addr); + + if(frame->from_addr==harGhostid) { + logFmsg(3,"discarding echo"); + return 0; + } + + if(frame->rcpt_addr!=harGhostid && frame->rcpt_addr!=HARMONY_BROADCAST_ADDR) { + logFmsg(3,"discarding 3rd party unicast packet"); + return 0; + } + + logFmsg(3,"Received unicast packet for me."); + + return 0; +} + +static int harFadvertise(void) +{ + harTframe_hdr pkt; + ssize_t ret; + + pkt.from_addr=harGhostid; + pkt.rcpt_addr=HARMONY_BROADCAST_ADDR; + pkt.msg_type=1; + pkt.data_len=0; + pkt.frame_crc=harFframe_crc(&pkt); + + if(ret=netFudp_send(harGbcast_socket,&pkt,sizeof(pkt), + harGcid,utlFstr_to_ip(MCAST_GROUP))==-1) { + logFmsg(3,"netFudp_send() returns error. [e: %d]", errno); + } else { + logFmsg(3,"cluster advertisement sent. %d", ret); + } + + return 0; +} + +int harFinit(void *p, lstTset *opt) +{ + const char *constellation; + pthread_t listen_thread; + + logFmsg(0, "mod/harmony: Clustering Engine"); + logFmsg(0, "Copyright (c) 2004, Alex Leigh"); + + constellation=lstFset_get(opt,"constellation"); + + if(constellation==NULL) { + logFmsg(2,"Constellation not configured. Aborting."); + exit(1); + } + + harGcid=atoi(constellation); + harGhostid=utlFgethostid(); + + logFmsg(0,"Rigging cluster constellation for id %u.", harGcid); + logFmsg(0,"Assumed cluster address %u.",harGhostid); + + harGbcast_socket=netFipv4_mcast_create(harGcid,MCAST_GROUP); + + if(harGbcast_socket<0) { + logFmsg(2,"Unable to create network transport. [e: %d]", errno); + exit(1); + } + + logFmsg(0,"Transport created."); + + harFadvertise(); + + pthread_create(&listen_thread,NULL,harFlisten_thread,NULL); + + return STATUS_OK; +} diff --git a/lc-continuity/mk4/modharmony/harmony.h b/lc-continuity/mk4/modharmony/harmony.h new file mode 100644 index 0000000000000000000000000000000000000000..f2e846489b11c9b33628cce7009264b44c337610 --- /dev/null +++ b/lc-continuity/mk4/modharmony/harmony.h @@ -0,0 +1,8 @@ +#ifndef _HARMONY_H +#define _HARMONY_H + +#include + +int harFinit(void *p, lstTset *opt); + +#endif diff --git a/lc-continuity/mk4/modharmony/hproto.h b/lc-continuity/mk4/modharmony/hproto.h new file mode 100644 index 0000000000000000000000000000000000000000..3e2fd5763f722f3f33dd60a3527cbd648f708415 --- /dev/null +++ b/lc-continuity/mk4/modharmony/hproto.h @@ -0,0 +1,15 @@ +#ifndef HARMONY_PROTO_H +#define HARMONY_PROTO_H + +struct harSframe_hdr { + uint32_t from_addr; + uint32_t rcpt_addr; + uint32_t msg_type; + uint32_t data_len; + uint32_t frame_crc; +}; +typedef struct harSframe_hdr harTframe_hdr; + +#define HARMONY_BROADCAST_ADDR 0 + +#endif diff --git a/lc-continuity/mk4/modhtaccess/CVS/Entries b/lc-continuity/mk4/modhtaccess/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..392e83ca579051add3e6134d1fd231d756557672 --- /dev/null +++ b/lc-continuity/mk4/modhtaccess/CVS/Entries @@ -0,0 +1,3 @@ +/Makefile/1.3/Fri May 14 17:30:52 2004//Tmk4_mod6_rc2 +D/include//// +D/src//// diff --git a/lc-continuity/mk4/modhtaccess/CVS/Repository b/lc-continuity/mk4/modhtaccess/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..7023115d5aa53e1738a2ea83ec1c42ee8d042839 --- /dev/null +++ b/lc-continuity/mk4/modhtaccess/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/modhtaccess diff --git a/lc-continuity/mk4/modhtaccess/CVS/Root b/lc-continuity/mk4/modhtaccess/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/modhtaccess/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/modhtaccess/CVS/Tag b/lc-continuity/mk4/modhtaccess/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/modhtaccess/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/modhtaccess/Makefile b/lc-continuity/mk4/modhtaccess/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..c8bbe4e24b437daeb5e3ede617d2babc3d814cc9 --- /dev/null +++ b/lc-continuity/mk4/modhtaccess/Makefile @@ -0,0 +1,15 @@ +CONTINUITY = ../continuity + +INCLUDES += -Iinclude +#INCLUDES += -I../lib/aura/include + +LOCAL_CFLAGS += + +#STATIC_LIBS += $(AURA)/libaura.a + +SOURCES = src/htaccess.c src/htaccess_parser.c \ + src/htaccess_basic_auth.c src/htaccess_engine.c + +TARGET = htaccess + +include $(CONTINUITY)/lib/build.mk diff --git a/lc-continuity/mk4/modhtaccess/include/CVS/Entries b/lc-continuity/mk4/modhtaccess/include/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..c0728c327e24f156e2eb684896fde9abfce4c730 --- /dev/null +++ b/lc-continuity/mk4/modhtaccess/include/CVS/Entries @@ -0,0 +1,5 @@ +/htaccess_basic_auth.h/1.1/Fri May 14 06:07:47 2004//Tmk4_mod6_rc2 +/htaccess_engine.h/1.1/Fri May 14 06:07:47 2004//Tmk4_mod6_rc2 +/htaccess_parser.h/1.1/Fri May 14 06:07:47 2004//Tmk4_mod6_rc2 +/iauthentication_scheme.h/1.1/Fri May 14 06:07:47 2004//Tmk4_mod6_rc2 +D diff --git a/lc-continuity/mk4/modhtaccess/include/CVS/Repository b/lc-continuity/mk4/modhtaccess/include/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..818ab1f1f08de7ecfa3287d0cb9add08e0cda321 --- /dev/null +++ b/lc-continuity/mk4/modhtaccess/include/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/modhtaccess/include diff --git a/lc-continuity/mk4/modhtaccess/include/CVS/Root b/lc-continuity/mk4/modhtaccess/include/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/modhtaccess/include/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/modhtaccess/include/CVS/Tag b/lc-continuity/mk4/modhtaccess/include/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/modhtaccess/include/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/modhtaccess/include/htaccess_basic_auth.h b/lc-continuity/mk4/modhtaccess/include/htaccess_basic_auth.h new file mode 100644 index 0000000000000000000000000000000000000000..bd61a6423e9dcbc8daabf7ae935587d88932398c --- /dev/null +++ b/lc-continuity/mk4/modhtaccess/include/htaccess_basic_auth.h @@ -0,0 +1,10 @@ + +#ifndef __HTACCESS_BASIC_AUTH_H__ +#define __HTACCESS_BASIC_AUTH_H__ + +typedef struct s_HtaccessBasicAuth HtaccessBasicAuth; + +HtaccessBasicAuth * htaccess_basic_auth_new (void); +void htaccess_basic_auth_destroy (void *ptr); + +#endif diff --git a/lc-continuity/mk4/modhtaccess/include/htaccess_engine.h b/lc-continuity/mk4/modhtaccess/include/htaccess_engine.h new file mode 100644 index 0000000000000000000000000000000000000000..8f7f6f591809155215413b331db08515ad381416 --- /dev/null +++ b/lc-continuity/mk4/modhtaccess/include/htaccess_engine.h @@ -0,0 +1,14 @@ + +#ifndef __HTACCESS_ENGINE_H__ +#define __HTACCESS_ENGINE_H__ + +#include "http.h" + +typedef struct s_HtaccessEngine HtaccessEngine; + +HtaccessEngine * htaccess_engine_new (httpTtrans *t); +void htaccess_engine_destroy (void *ptr); + +int htaccess_engine_process (HtaccessEngine *instance); + +#endif diff --git a/lc-continuity/mk4/modhtaccess/include/htaccess_parser.h b/lc-continuity/mk4/modhtaccess/include/htaccess_parser.h new file mode 100644 index 0000000000000000000000000000000000000000..96e02291705d02e7f2e26c434dd95c53151af035 --- /dev/null +++ b/lc-continuity/mk4/modhtaccess/include/htaccess_parser.h @@ -0,0 +1,16 @@ + +#ifndef __HTACCESS_PARSER_H__ +#define __HTACCESS_PARSER_H__ + +#include "mecha.h" + +typedef struct s_HtaccessParser HtaccessParser; + +HtaccessParser * htaccess_parser_new (const char *filename); +void htaccess_parser_destroy (void *ptr); + +bool htaccess_parser_parse (HtaccessParser *instance); + +const char * htaccess_parser_get_value (HtaccessParser *instance, const char *key); + +#endif diff --git a/lc-continuity/mk4/modhtaccess/include/iauthentication_scheme.h b/lc-continuity/mk4/modhtaccess/include/iauthentication_scheme.h new file mode 100644 index 0000000000000000000000000000000000000000..e4aed3574aba1d4916a306235a6a034ab36b75dc --- /dev/null +++ b/lc-continuity/mk4/modhtaccess/include/iauthentication_scheme.h @@ -0,0 +1,33 @@ +#ifndef __IAUTHENTICATION_SCHEME_H__ +#define __IAUTHENTICATION_SCHEME_H__ + +#include "htaccess_parser.h" + +#include "http.h" + +#include "mecha.h" + +typedef struct IAuthenticationScheme_s IAuthenticationScheme; + +typedef void (*IAuthenticationSchemeDestroy) (IAuthenticationScheme *instance); + +enum AuthenticateResult_e +{ + AuthenticateResultReject, + AuthenticateResultAccept +}; + +typedef enum AuthenticateResult_e AuthenticateResult; + +struct IAuthenticationScheme_s +{ + bool (*read_config) (IAuthenticationScheme *instance, HtaccessParser *config); + + AuthenticateResult (*auth_user) (IAuthenticationScheme *instance, + httpTtrans *trans, const char *authData); + + IAuthenticationSchemeDestroy destroy; +}; + + +#endif diff --git a/lc-continuity/mk4/modhtaccess/src/CVS/Entries b/lc-continuity/mk4/modhtaccess/src/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..371e934ba3a4c85965f2fd7c03755e98c41c6b09 --- /dev/null +++ b/lc-continuity/mk4/modhtaccess/src/CVS/Entries @@ -0,0 +1,5 @@ +/htaccess.c/1.1/Fri May 14 06:07:47 2004//Tmk4_mod6_rc2 +/htaccess_basic_auth.c/1.2/Fri May 14 17:31:35 2004//Tmk4_mod6_rc2 +/htaccess_engine.c/1.2/Fri May 14 16:51:26 2004//Tmk4_mod6_rc2 +/htaccess_parser.c/1.1/Fri May 14 06:07:47 2004//Tmk4_mod6_rc2 +D diff --git a/lc-continuity/mk4/modhtaccess/src/CVS/Repository b/lc-continuity/mk4/modhtaccess/src/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..28f550af2418ce38a4140bb98788a9c6a3eac0a7 --- /dev/null +++ b/lc-continuity/mk4/modhtaccess/src/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/modhtaccess/src diff --git a/lc-continuity/mk4/modhtaccess/src/CVS/Root b/lc-continuity/mk4/modhtaccess/src/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/modhtaccess/src/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/modhtaccess/src/CVS/Tag b/lc-continuity/mk4/modhtaccess/src/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/modhtaccess/src/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/modhtaccess/src/htaccess.c b/lc-continuity/mk4/modhtaccess/src/htaccess.c new file mode 100644 index 0000000000000000000000000000000000000000..90e059836aff330abaacb4034e9f8e443edbe41c --- /dev/null +++ b/lc-continuity/mk4/modhtaccess/src/htaccess.c @@ -0,0 +1,20 @@ + +#include "mecha.h" +#include "http.h" + +#include "htaccess_engine.h" + +int htaccess_handler (httpTtrans *t, lstTset *opts); + +int +htaccess_handler (httpTtrans *t, MECHA_UNUSED_ARGUMENT lstTset *opts) +{ + HtaccessEngine *engine = htaccess_engine_new (t); + int retVal; + + retVal = htaccess_engine_process (engine); + + htaccess_engine_destroy (engine); + + return (retVal); +} diff --git a/lc-continuity/mk4/modhtaccess/src/htaccess_basic_auth.c b/lc-continuity/mk4/modhtaccess/src/htaccess_basic_auth.c new file mode 100644 index 0000000000000000000000000000000000000000..78f0a884f8510d72ee2e42ddf377b4948a4be267 --- /dev/null +++ b/lc-continuity/mk4/modhtaccess/src/htaccess_basic_auth.c @@ -0,0 +1,253 @@ + +#include + +#include "htaccess_basic_auth.h" + +#include "iauthentication_scheme.h" + +#include "mecha.h" +#include "http.h" + +#ifdef SOLARIS +#include +#endif + +enum RequireType_e +{ + RequireTypeValidUser, + RequireTypeUser, + RequireTypeGroup, + RequireTypeNone +}; + +typedef enum RequireType_e RequireType; + +struct s_HtaccessBasicAuth +{ + IAuthenticationScheme authInterface; + + const char *realm; + const char *userFile; + const char *groupFile; + RequireType requireType; + + char *requestedUser; + char *requestedPassword; +}; + + +static bool htaccess_basic_auth_read_config (IAuthenticationScheme *inst, HtaccessParser *config); +static AuthenticateResult htaccess_basic_auth_auth_user (IAuthenticationScheme *inst, httpTtrans *trans, const char *data); +static bool htaccess_basic_auth_parse_data (HtaccessBasicAuth *instance, const char *data); + +HtaccessBasicAuth * +htaccess_basic_auth_new (void) +{ + HtaccessBasicAuth *instance = (HtaccessBasicAuth *) malloc (sizeof (HtaccessBasicAuth)); + + instance->authInterface.read_config = htaccess_basic_auth_read_config; + instance->authInterface.auth_user = htaccess_basic_auth_auth_user; + instance->authInterface.destroy = (IAuthenticationSchemeDestroy) htaccess_basic_auth_destroy; + + instance->realm = NULL; + instance->userFile = NULL; + instance->groupFile = NULL; + instance->requireType = RequireTypeNone; + + instance->requestedUser = NULL; + instance->requestedPassword = NULL; + + return (instance); +} + +void +htaccess_basic_auth_destroy (void *ptr) +{ + HtaccessBasicAuth *instance = (HtaccessBasicAuth *) ptr; + + if (instance->requestedUser != NULL) + { + free (instance->requestedUser); + } + + if (instance->requestedPassword != NULL) + { + free (instance->requestedPassword); + } + + free (instance); +} + +static bool +htaccess_basic_auth_read_config (IAuthenticationScheme *inst, HtaccessParser *config) +{ + HtaccessBasicAuth *instance = (HtaccessBasicAuth *) inst; + const char *requireField; + + requireField = htaccess_parser_get_value (config, "Require"); + + if (requireField == NULL) + { + instance->requireType = RequireTypeNone; + } + else if (strncmp (requireField, "valid-user", 10) == 0) + { + instance->requireType = RequireTypeValidUser; + } + else if (strncmp (requireField, "user ", 5) == 0) + { + instance->requireType = RequireTypeUser; + + logFmsg (CONT_LOG_ERROR, "mod/htaccess: 'Require user' unsupported."); + + return (false); + } + else if (strncmp (requireField, "group ", 5) == 0) + { + instance->requireType = RequireTypeGroup; + + logFmsg (CONT_LOG_ERROR, "mod/htaccess: 'Require group' unsupported."); + + return (false); + } + + instance->userFile = htaccess_parser_get_value (config, "AuthUserFile"); + instance->groupFile = htaccess_parser_get_value (config, "AuthGroupFile"); + + instance->realm = htaccess_parser_get_value (config, "AuthName"); + + return (true); +} + +static bool +htaccess_basic_auth_parse_data (HtaccessBasicAuth *instance, const char *data) +{ + char decodeBuf[1024]; + char *user, *pass; + char *st_p; + int ret; + + ret = b64Fdecode (data, (unsigned char *) decodeBuf, sizeof (decodeBuf)); + + decodeBuf[ret] = 0; + + user = strtok_r (decodeBuf, ":", &st_p); + pass = strtok_r (NULL, ":", &st_p); + + if (user != NULL && pass != NULL) + { + instance->requestedUser = strFcopy (user); + instance->requestedPassword = strFcopy (pass); + + return (true); + } + else + { + return (false); + } +} + +static AuthenticateResult +htaccess_basic_auth_auth_user (IAuthenticationScheme *inst, + httpTtrans *trans, const char *data) +{ + HtaccessBasicAuth *instance = (HtaccessBasicAuth *) inst; + FILE *fp; + char line[1024]; + bool retSuccess = false; + + if (htaccess_basic_auth_parse_data (instance, data) == false) + { + if (instance->requireType == RequireTypeNone) + { + return (AuthenticateResultAccept); + } + else + { + return (AuthenticateResultReject); + } + } + + fp = fopen (instance->userFile, "r"); + + if (fp == NULL) + { + if (instance->requireType == RequireTypeNone) + { + logFmsg (CONT_LOG_WARN, "mod/htaccess: Could not open UserFile: %s. Authentication succeeding.", + instance->userFile); + + return (AuthenticateResultAccept); + } + else + { + logFmsg (CONT_LOG_WARN, "mod/htaccess: Could not open UserFile: %s. Authentication failing.", + instance->userFile); + + return (AuthenticateResultReject); + } + } + + while (fgets (line, sizeof (line), fp) != NULL) + { + char *tokCtx; + char *curUser, *curPassword; + + strFstrip_crlf (line, strlen (line)); + + curUser = strtok_r (line, ":", &tokCtx); + + curPassword = strtok_r (NULL, ":", &tokCtx); + + if (curPassword == NULL) + { + continue; + } + + /* if we found the user */ + if (strcmp (instance->requestedUser, curUser) == 0) + { + char *encryptedPass; + + encryptedPass = crypt (instance->requestedPassword, curPassword); + + if (strcmp (encryptedPass, curPassword) == 0) + { + retSuccess = true; + } + else + { +#if HTACCESS_DEBUG + logFmsg (CONT_LOG_DEBUG, "mod/htaccess: File password %s does not match encrypted: %s", + curPassword, encryptedPass); +#endif + + retSuccess = false; + } + + break; + } + } + + fclose (fp); + + if (retSuccess == true) + { + lstFset_update (trans->vars, "auth-type", "basic"); + lstFset_update (trans->vars, "auth-user", instance->requestedUser); + + return (AuthenticateResultAccept); + } + else + { + if (instance->requireType == RequireTypeNone) + { + return (AuthenticateResultAccept); + } + else + { + return (AuthenticateResultReject); + } + } +} + diff --git a/lc-continuity/mk4/modhtaccess/src/htaccess_engine.c b/lc-continuity/mk4/modhtaccess/src/htaccess_engine.c new file mode 100644 index 0000000000000000000000000000000000000000..9896b323050a4331074e5daa69bed155ce909b76 --- /dev/null +++ b/lc-continuity/mk4/modhtaccess/src/htaccess_engine.c @@ -0,0 +1,260 @@ + +#include + +#include "mecha.h" + +#include "htaccess_engine.h" + +#include "htaccess_basic_auth.h" + +#include "htaccess_parser.h" +#include "iauthentication_scheme.h" + +#define HTACCESS_FILENAME ".htaccess" + +struct s_HtaccessEngine +{ + httpTtrans *trans; + + HtaccessParser *parser; + + IAuthenticationScheme *authScheme; + + dynTstring *requestAuthType; + dynTstring *requestAuthData; + + char *htaccessFilename; +}; + +HtaccessEngine * +htaccess_engine_new (httpTtrans *t) +{ + HtaccessEngine *instance = (HtaccessEngine *) malloc (sizeof (HtaccessEngine)); + + instance->trans = t; + + instance->parser = NULL; + + instance->requestAuthType = NULL; + instance->requestAuthData = NULL; + + instance->htaccessFilename = NULL; + + instance->authScheme = NULL; + + return (instance); +} + +void +htaccess_engine_destroy (void *ptr) +{ + HtaccessEngine *instance = (HtaccessEngine *) ptr; + + if (instance->parser != NULL) + { + htaccess_parser_destroy (instance->parser); + } + + if (instance->requestAuthType != NULL) + { + dynFfree (instance->requestAuthType); + } + + if (instance->requestAuthData != NULL) + { + dynFfree (instance->requestAuthData); + } + + if (instance->htaccessFilename != NULL) + { + free (instance->htaccessFilename); + } + + if (instance->authScheme != NULL) + { + instance->authScheme->destroy (instance->authScheme); + } + + free (instance); +} + +static bool +htaccess_engine_find_file (HtaccessEngine *instance) +{ + const lstTfield *path = lstFset_get_field (instance->trans->vars, "path", 4); + char pathBuf[1024]; + char htfileBuf[1024]; + char *slashPtr; + + strncpy (pathBuf, lstFfield_value (path), sizeof (pathBuf)); + + while ((slashPtr = rindex (pathBuf, '/')) != NULL) + { + struct stat sbuf; + + *slashPtr = 0; + + snprintf (htfileBuf, sizeof (htfileBuf), "%s/%s", pathBuf, HTACCESS_FILENAME); + + if (stat (htfileBuf, &sbuf) != -1) + { + if (S_ISREG (sbuf.st_mode)) + { + instance->htaccessFilename = strFcopy (htfileBuf); + + instance->parser = htaccess_parser_new (htfileBuf); + + if (htaccess_parser_parse (instance->parser) == true) + { + return (true); + } + else + { + return (false); + } + } + } + } + + return (false); +} + +static void +htaccess_engine_populate_auth_data (HtaccessEngine *instance) +{ + char *spacePtr; + const lstTfield *auth = lstFset_get_field (instance->trans->req_hdrs, + "authorization", 13); + + if (auth == NULL) + { + return; + } + + spacePtr = index (lstFfield_value (auth), ' '); + + if (spacePtr == NULL) + { + return; + } + + { + int wordLen = spacePtr - lstFfield_value (auth); + + instance->requestAuthType = dynFinit(); + + dynFappend (instance->requestAuthType, lstFfield_value (auth), wordLen); + } + + instance->requestAuthData = dynFinit(); + + spacePtr++; + + dynFsappend (instance->requestAuthData, spacePtr); +} + +static int +htaccess_engine_send_unauthorized_response (HtaccessEngine *instance) +{ + char authResp[1024]; + const char *authRealm; + const char *authType; + + httpFset_status (instance->trans, HTTP_UNAUTHORIZED, NULL); + + authRealm = htaccess_parser_get_value (instance->parser, "AuthName"); + authType = htaccess_parser_get_value (instance->parser, "AuthType"); + + snprintf (authResp, sizeof (authResp), "%s realm=\"%s\"", + authType, authRealm); + + lstFset_update (instance->trans->res_hdrs, "WWW-Authenticate", authResp); + + httpFstart_response (instance->trans); + + httpFwrite (instance->trans, "Authorization required.", 23); + + return (STATUS_EXIT); +} + +static IAuthenticationScheme * +htaccess_engine_get_auth_scheme (HtaccessEngine *instance) +{ + if (strcmp (htaccess_parser_get_value (instance->parser, "AuthType"), "Basic") == 0) + { + return ((IAuthenticationScheme *) htaccess_basic_auth_new()); + } + + /* + * we only support the Basic authentication type right now because we're + * lazy. + * + * -eric@5stops.com 3.14.2004 + */ + return (NULL); +} + +int +htaccess_engine_process (HtaccessEngine *instance) +{ + AuthenticateResult authResult = AuthenticateResultReject; + const char *authType; + + if (htaccess_engine_find_file (instance) == false) + { + return (STATUS_PROCEED); + } + + htaccess_engine_populate_auth_data (instance); + + authType = htaccess_parser_get_value (instance->parser, "AuthType"); + + if (authType == NULL) + { + logFmsg (CONT_LOG_WARN, "mod/htaccess: Could not find an AuthType. Ignoring %s.", + instance->htaccessFilename); + + return (STATUS_PROCEED); + } + + if (instance->requestAuthType == NULL || instance->requestAuthData == NULL) + { + return (htaccess_engine_send_unauthorized_response (instance)); + } + + if (strcmp (authType, dynFgetstr (instance->requestAuthType)) != 0) + { + logFmsg (CONT_LOG_ERROR, "mod/htaccess: The requested authentication type \"%s\" did not match the expected type \"%s\".", + dynFgetstr (instance->requestAuthType), authType); + + return (htaccess_engine_send_unauthorized_response (instance)); + } + + instance->authScheme = htaccess_engine_get_auth_scheme (instance); + + if (instance->authScheme == NULL) + { + logFmsg (CONT_LOG_ERROR, "mod/htaccess: %s: The authentication type \"%s\" is not supported.", + instance->htaccessFilename, authType); + + return (STATUS_PROCEED); + } + + if (instance->authScheme->read_config (instance->authScheme, instance->parser) == false) + { + logFmsg (CONT_LOG_WARN, "mod/htaccess: %s: An error occured while reading config data.", + instance->htaccessFilename); + + return (STATUS_PROCEED); + } + + authResult = instance->authScheme->auth_user (instance->authScheme, instance->trans, + dynFgetstr (instance->requestAuthData)); + + if (authResult == AuthenticateResultReject) + { + return (htaccess_engine_send_unauthorized_response (instance)); + } + + return (STATUS_PROCEED); +} diff --git a/lc-continuity/mk4/modhtaccess/src/htaccess_parser.c b/lc-continuity/mk4/modhtaccess/src/htaccess_parser.c new file mode 100644 index 0000000000000000000000000000000000000000..a8db88b93a63f2b3ff0eb1eeb33593ecaf9b4d21 --- /dev/null +++ b/lc-continuity/mk4/modhtaccess/src/htaccess_parser.c @@ -0,0 +1,96 @@ + +#include + +#include "mecha.h" + +#include "htaccess_parser.h" + +struct s_HtaccessParser +{ + char *filename; + hshTvoid_list *data; +}; + +HtaccessParser * +htaccess_parser_new (const char *file) +{ + HtaccessParser *instance = (HtaccessParser *) malloc (sizeof (HtaccessParser)); + + instance->filename = strFcopy (file); + + instance->data = hshFvoid_init (free); + + return (instance); +} + +void +htaccess_parser_destroy (void *ptr) +{ + HtaccessParser *instance = (HtaccessParser *) ptr; + + free (instance->filename); + + hshFvoid_destroy (instance->data); + + free (instance); +} + +const char * +htaccess_parser_get_value (HtaccessParser *instance, const char *key) +{ + return ((const char *) hshFvoid_find (instance->data, key)); +} + +bool +htaccess_parser_parse (HtaccessParser *instance) +{ + FILE *fp; + char line[1024]; + + fp = fopen (instance->filename, "r"); + + if (fp == NULL) + { + return (false); + } + + while (fgets (line, sizeof (line), fp) != NULL) + { + char *firstSpace; + + strFstrip_crlf (line, strlen (line)); + + firstSpace = index (line, ' '); + + if (firstSpace == NULL) + { + logFmsg (CONT_LOG_WARN, "htaccess: unknown line: %s", line); + } + + *firstSpace = 0; + + firstSpace++; + + if (*firstSpace == '"') + { + firstSpace++; + } + + { + int secondLength = strlen (firstSpace); + + + + if (firstSpace[secondLength - 1] == '"') + { + firstSpace[secondLength - 1] = 0; + } + } + + hshFvoid_add (instance->data, line, strFcopy (firstSpace)); + } + + fclose (fp); + + return (true); +} diff --git a/lc-continuity/mk4/modhttp/CVS/Entries b/lc-continuity/mk4/modhttp/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..a44f7130e1a42c7c9605e743de9e2cd89441c6f2 --- /dev/null +++ b/lc-continuity/mk4/modhttp/CVS/Entries @@ -0,0 +1,5 @@ +/Makefile.in/1.3/Wed May 12 13:50:37 2004//Tmk4_mod6_rc2 +/http.c/1.49/Sun May 23 21:35:50 2004//Tmk4_mod6_rc2 +/http.h/1.18/Fri Apr 2 16:17:18 2004//Tmk4_mod6_rc2 +/http.xml/1.2/Wed May 12 14:29:44 2004//Tmk4_mod6_rc2 +D diff --git a/lc-continuity/mk4/modhttp/CVS/Repository b/lc-continuity/mk4/modhttp/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..f62db10ae74732cf5c3acd953c34daf8b45b49dd --- /dev/null +++ b/lc-continuity/mk4/modhttp/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/modhttp diff --git a/lc-continuity/mk4/modhttp/CVS/Root b/lc-continuity/mk4/modhttp/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/modhttp/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/modhttp/CVS/Tag b/lc-continuity/mk4/modhttp/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/modhttp/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/modhttp/Makefile.in b/lc-continuity/mk4/modhttp/Makefile.in new file mode 100644 index 0000000000000000000000000000000000000000..db6620e165404507c08940f613751fe8c7a81ec3 --- /dev/null +++ b/lc-continuity/mk4/modhttp/Makefile.in @@ -0,0 +1,24 @@ +# $Header: /san01/cvs/ashpool/csrc/modhttp/Attic/Makefile.in,v 1.3 2004/05/12 13:50:37 aleigh Exp $ + +include ../continuity/lib/env.mk + +SRCS=http.c +OBJS=http.o + +CFLAGS=-I../continuity/include $(CONT_FLAGS) -fPIC + +world: install + +http.so: $(OBJS) + $(LD_SHARECMD) -o http.so $(OBJS) +clean: + $(RM) $(OBJS) *~ http.so + +install: http.so http.h + (rm -f ../continuity/lib/http.so ; cp http.so ../continuity/lib) + cp http.h ../continuity/include + cp http.xml ../continuity/lib + +depend: + $(MAKEDEPEND) $(DEPFLAGS) -I ../continuity/include $(SRCS) + diff --git a/lc-continuity/mk4/modhttp/http.c b/lc-continuity/mk4/modhttp/http.c new file mode 100644 index 0000000000000000000000000000000000000000..5221638209940a376c1e73cfe468d9f0f6244fff --- /dev/null +++ b/lc-continuity/mk4/modhttp/http.c @@ -0,0 +1,1030 @@ +/* + * $Header: /cvsroot/csrc/modhttp/http.c,v 1.18 2003/12/02 14:49:22 aleigh + * Exp $ + */ + +/* + * Copyright (c) 1994, 2004 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Disclosure, copying, distribution, or transmission of this code without + * express permission is prohibited. + */ + +#include "../continuity/include/csys.h" +#include "../continuity/mecha/dyn.h" +#include "../continuity/mecha/net.h" +#include "../continuity/include/continuity.h" +#include "../continuity/mecha/lst.h" +#include "http.h" + +#define EAGAIN_TRYCOUNT 100 +#define EAGAIN_WAIT 250 + +static void httpFat_end(char **sPtr, char **ePtr); +static int httpFparse_multiquery(httpTtrans * t, char *start, char *end, + lstTset * set); + +pthread_key_t httpKtrans_key = 0; +int natr_id; +int srvc_id; +int mime_id; +int wlog_id; + +static void httpFcleanup(httpTtrans * t) +{ + httpFthread_settrans(NULL); + t->conn->io_close(t->conn); + tlsFclean(); + httpFtrans_free(t); +} + +/* + * This function is called by the dispatcher when a new connection is + * received on the listen socket. This overall controls the flow of the HTTP + * transaction, from start to finish, and dictates which module classes are + * going to be called in order to service the transaction. + */ +void httpFhandler(void *p, MECHA_UNUSED_ARGUMENT const lstTset * arg) +{ + netTconn *conn = (netTconn *) p; + httpTtrans *trans; + int ret; + + trans = httpFtrans_alloc(); + + trans->sd = conn->sd; + trans->cli_ipv4_addr = conn->cli_ipv4_addr; + trans->conn = p; + + /* + * Set the new transaction structure to be associated with the thread, so + * that httpFthread_gettrans will work later. + */ + httpFthread_settrans(trans); + + ret = httpFparse(trans); + + if (ret == STATUS_ERROR) { + /* There was something totally wrong with the query so we are going + * to return a 400. Since there is no valid information in the transaction + * the pipelines are not executed, so 400 requests do not log. + */ + httpFset_status(trans, 400, NULL); + httpFstart_response(trans); + httpFerror_page(trans, NULL); + httpFcleanup(trans); + return; + } + + ret = dlFpipeline_exec(trans, natr_id, NULL, NULL); + + if (trans->started == REQ_UNSTARTED) { + + ret = dlFpipeline_exec(trans, mime_id, NULL, NULL); + } + if (trans->started == REQ_UNSTARTED) { + + ret = + dlFpipeline_exec(trans, srvc_id, "type", + lstFset_get(trans->res_hdrs, "Content-Type")); + } + if (ret != STATUS_EXIT) { + httpFset_status(trans, 500, NULL); + httpFstart_response(trans); + httpFerror_page(trans, NULL); + } + if (trans->started == REQ_STARTED) + httpFsend_response(trans); + + dlFpipeline_exec(trans, wlog_id, NULL, NULL); + + httpFcleanup(trans); + + return; +} + +int httpFinit(MECHA_UNUSED_ARGUMENT void *p, + MECHA_UNUSED_ARGUMENT const lstTset * opts) +{ + if (pthread_key_create(&httpKtrans_key, NULL) != 0) { + logFmsg(2, "Unable to create httpKtrans_key. [e: %d]", + errno); + abort(); + } + logFmsg(0, "mod/http: Hyper-Text Transfer Protocol Engine"); + logFmsg(0, "Copyright (c) 2002, Alex Leigh"); + + natr_id = dlFpipeline_getid("http_natr"); + mime_id = dlFpipeline_getid("http_mime"); + srvc_id = dlFpipeline_getid("http_srvc"); + wlog_id = dlFpipeline_getid("http_log"); + + return STATUS_OK; +} + +int httpFthread_settrans(httpTtrans * t) +{ + return pthread_setspecific(httpKtrans_key, t); +} + +httpTtrans *httpFthread_gettrans(void) +{ + return (httpTtrans *) pthread_getspecific(httpKtrans_key); +} + +httpTtrans *httpFtrans_alloc(void) +{ + httpTtrans *t; + + t = (httpTtrans *) malloc(sizeof(httpTtrans)); + + t->req_hdrs = lstFset_create("request headers"); + t->res_hdrs = lstFset_create("response headers"); + t->vars = lstFset_create("vars"); + t->response = dynFinit(); + t->reader = netFreader_init(); + t->query = NULL; + + t->res_code = 200; + t->res_reason = "OK"; + t->started = REQ_UNSTARTED; + t->client_read = 0; + + memFclear(&t->statb, sizeof(t->statb)); + + assert(t->req_hdrs != NULL); + assert(t->res_hdrs != NULL); + assert(t->vars != NULL); + + return t; +} + +void httpFtrans_free(httpTtrans * t) +{ + assert(t != NULL); + assert(t->req_hdrs != NULL); + assert(t->res_hdrs != NULL); + assert(t->vars != NULL); + assert(t->conn != NULL); + + netFconn_free(t->conn); + + lstFset_free(t->req_hdrs); + lstFset_free(t->res_hdrs); + lstFset_free(t->vars); + lstFset_free(t->query); + + dynFfree(t->response); + netFreader_free(t->reader); + + free(t); +} + +int httpFerror_page(httpTtrans * t, const char *msg) +{ + char buf[1024]; + + assert(t != NULL); + + httpFsend_response(t); + + snprintf(buf, sizeof(buf), + "ERROR: No functions handled this request.\n\n%s", + conFget_build()); + + httpFwrite(t, buf, strlen(buf)); + + if (msg != NULL) { + httpFwrite(t, msg, strlen(msg)); + } + return STATUS_PROCEED; +} + +void httpFset_status(httpTtrans * t, int status, const char *reason) +{ + assert(t != NULL); + + t->res_code = status; + if (reason != NULL) { + t->res_reason = reason; + } +} + +/* + * This just outputs the headers. It's useful if your module has served the + * HTTP response line, or you are returning a non HTTP response and you want + * to send the entities. + */ + +int httpFsend_resp_headers(httpTtrans * t) +{ + int i; + char buf[128]; + size_t length = 0; + + assert(t != NULL); + assert(t->res_hdrs != NULL); + + for (i = 0; i < t->res_hdrs->size; i++) { + if (t->res_hdrs->fields[i].name != NULL + && t->res_hdrs->fields[i].value != NULL) { + snprintf(buf, sizeof(buf), "%s: %s\r\n", + t->res_hdrs->fields[i].name, + t->res_hdrs->fields[i].value); + length += + t->res_hdrs->fields[i].n_len + + t->res_hdrs->fields[i].v_len + 4; + + buf[0] = toupper(buf[0]); + + httpFwrite(t, buf, length); + } + } + return 0; +} + +/* + * this function is used in case we have never called httpFwrite() by the + * time the request is finished, or if we don't intend to call it. + */ +void httpFsend_response(httpTtrans * t) +{ + netFconn_write(t->conn, t->response->str, t->response->strlen); + + t->started = REQ_HEADERSENT; +} + +void httpFstart_response(httpTtrans * t) +{ + int i; + + assert(t != NULL); + assert(t->res_hdrs != NULL); + + /* we only need to send these once */ + if (t->started == REQ_STARTED || t->started == REQ_HEADERSENT) { + return; + } + + t->started = REQ_STARTED; + + switch (t->res_code) { + case HTTP_OK: + dynFappend(t->response, "HTTP/1.0 200 OK\r\n", 17); + break; + case HTTP_CREATED: + dynFappend(t->response, "HTTP/1.0 201 CREATED\r\n", 22); + break; + case HTTP_ACCEPTED: + dynFappend(t->response, "HTTP/1.0 202 ACCEPTED\r\n", 23); + break; + case HTTP_PARTIAL: + dynFappend(t->response, "HTTP/1.0 203 PARTIAL\r\n", 22); + break; + case HTTP_NORESPONSE: + dynFappend(t->response, "HTTP/1.0 204 NO RESPONSE\r\n", 26); + break; + case HTTP_MOVED: + dynFappend(t->response, "HTTP/1.0 301 MOVED\r\n", 20); + break; + case HTTP_FOUND: + dynFappend(t->response, "HTTP/1.0 302 FOUND\r\n", 20); + break; + case HTTP_NOTMODIFIED: + dynFappend(t->response, "HTTP/1.0 304 NOT MODIFIED\r\n", 27); + break; + case HTTP_BADREQUEST: + dynFappend(t->response, "HTTP/1.0 400 BAD REQUEST\r\n", 26); + break; + case HTTP_UNAUTHORIZED: + dynFappend(t->response, "HTTP/1.0 401 UNAUTHORIZED\r\n", 27); + break; + case HTTP_PAYMENTREQUIRED: + dynFappend(t->response, "HTTP/1.0 402 PAYMENT REQUIRED\r\n", 31); + break; + case HTTP_FORBIDDEN: + dynFappend(t->response, "HTTP/1.0 403 FORBIDDEN\r\n", 24); + break; + case HTTP_NOTFOUND: + dynFappend(t->response, "HTTP/1.0 404 NOT FOUND\r\n", 24); + break; + case HTTP_ERROR: + dynFappend(t->response, "HTTP/1.0 500 ERROR\r\n", 20); + break; + case HTTP_UNIMPLEMENTED: + dynFappend(t->response, "HTTP/1.0 501 NOT IMPLEMENTED\r\n", 30); + break; + case HTTP_TIMEDOUT: + dynFappend(t->response, "HTTP/1.0 502 TIMED OUT\r\n", 24); + break; + default: + dynFappend(t->response, "HTTP/1.0 500 ERROR\r\n", 20); + break; + } + + for (i = 0; i < t->res_hdrs->size; i++) { + if (t->res_hdrs->fields[i].name != NULL + && t->res_hdrs->fields[i].value != NULL) { + + + /* dynFsappend(t->response, t->res_hdrs->fields[i].name); */ + + dynFappend(t->response, t->res_hdrs->fields[i].name, + t->res_hdrs->fields[i].n_len); + + dynFappend(t->response, ": ", 2); + + /* dynFsappend(t->response, t->res_hdrs->fields[i].value); */ + + dynFappend(t->response, t->res_hdrs->fields[i].value, + t->res_hdrs->fields[i].v_len); + + dynFappend(t->response, "\r\n", 2); + } + } + + dynFappend(t->response, "\r\n", 2); +} + +/* + * httpFparse + * + * Read a HTTP request from the network and fill out the transaction. This + * function assumes that t->vars are empty and that the network socket + * descriptor is at the beginning of the input stream. + * + * After this function exits, the transaction will contain the following + * + * t->vars clf-request The complete request line the client provided. t->vars + * uri The URI of the request, stripped of any query information. t->vars + * query Anything after the first ? in clf-request. t->vars method The method + * of the request, as specified by the client. Uppercase. t->vars protocol + * The protocol the client provided, if any. Uppercase. + * + * STATUS_PROCEED A request was read. STATUS_ERROR The request could not be + * read. Discard the connection. + */ + +int httpFparse(httpTtrans * t) +{ + /* 1024 hardocded later */ + char req_line[1024]; + dynTstring *decoded; + char *st_p; /* strtok pointer */ + char *method_p = NULL, *uri_p = NULL, *proto_p = NULL, *query_p = NULL; + int method_len, proto_len; + int ret; + size_t rqsize; + + ret = + netFconn_read_line(t->conn, t->reader, req_line, sizeof(req_line)); + + if (ret < 1) { + return STATUS_ERROR; + } + + if (req_line[0] == '\0') + return STATUS_ERROR; + + if (ret >= 1024) { + /* + * The input buffer was of insufficient size for us to store the entire + * line. + */ + logFmsg(1, "Request would not fit in buffer."); + return STATUS_ERROR; + } + rqsize = ret; + + lstFset_badd(t->vars, "clf-request", 11, req_line, ret); + + method_p = (char *) strtok_r(req_line, " ", &st_p); + + /* we don't want to include the " " in this calculation */ + method_len = st_p - method_p - 1; + + uri_p = (char *) strtok_r(NULL, " ", &st_p); + proto_p = (char *) strtok_r(NULL, " ", &st_p); + + proto_len = (req_line + ret) - proto_p; + + if (method_p == NULL || uri_p == NULL) { + /* logFmsg (1, "short request"); */ + return STATUS_ERROR; + } + lstFset_badd(t->res_hdrs, "Server", 6, "continuity/" BUILD_REV, + 11 + BUILD_LEV_LEN); + + strFtoupper(method_p); + lstFset_badd(t->vars, "method", 6, method_p, method_len); + + if (proto_p != NULL) { + strFtoupper(proto_p); + lstFset_badd(t->vars, "protocol", 8, proto_p, proto_len); + } + /* Check to see if we had GET query parameters */ + st_p = NULL; + query_p = (char *) strtok_r(uri_p, "?", &st_p); + + decoded = dynFinit(); + + /* decode the portion of the uri before the query */ + utlFurl_decode(decoded, query_p); + + lstFset_badd(t->vars, "uri", 3, decoded->str, decoded->strlen); + lstFset_badd(t->vars, "req_uri", 7, decoded->str, decoded->strlen); + + dynFfree(decoded); + + query_p = (char *) strtok_r(NULL, "?", &st_p); + + if (query_p != NULL) { + lstFset_badd(t->vars, "query", 5, query_p, strlen(query_p)); + } + + /* + * 4.2 Message Headers + * + * HTTP header fields, which include General-Header (Section 4.3), + * Request-Header (Section 5.2), Response-Header (Section 6.2), and + * Entity-Header (Section 7.1) fields, follow the same generic format as + * that given in Section 3.1 of RFC 822 [7]. Each header field consists + * of a name followed immediately by a colon (":"), a single space (SP) + * character, and the field value. Field names are case-insensitive. + * Header fields can be extended over multiple lines by preceding each + * extra line with at least one SP or HT, though this is not + * recommended. + */ + while (1) { + char *name_p; + char *colon_location; + int name_len; + + char *value_p; + int value_len; + + ret = + netFconn_read_line(t->conn, t->reader, req_line, + sizeof(req_line)); + + if (ret <= 1) + break; + + rqsize += ret; + + name_p = req_line; + + colon_location = index(name_p, ':'); + + if (colon_location == NULL) { + continue; + } + + *colon_location = 0; + + name_len = colon_location - name_p; + + value_p = colon_location + 1; + + /* We should only have to look for one space */ + if (*value_p == ' ') { + value_p++; + } + + if (value_p == NULL) { + continue; + } + + value_len = (req_line + ret) - value_p; + + strFtolower(name_p); + lstFset_badd(t->req_hdrs, name_p, name_len, value_p, value_len); + } + + return STATUS_PROCEED; +} + +/* + * read the conte-type from the request, and break out the boundry + * information. + */ +int httpFget_boundry(dynTstring * str, httpTtrans * t) +{ + const char *type, *bs, *be; + + type = lstFset_get(t->req_hdrs, "content-type"); + + if (type != NULL) { + if (strstr(type, "multipart/form-data") != NULL) { + if ((bs = strstr(type, "boundary=")) != NULL) { + bs += 9; + be = bs; + while (*be && !isspace(*be)) { + ++be; + } + dynFappend(str, "--", 2); + dynFappend(str, bs, be - bs); + return 1; + } + } + } + return 0; +} + +/* + * Trim a string of unescessary crap, from sPtr to ePtr + */ +static void httpFat_end(char **sPtr, char **ePtr) +{ + char *s, *e; + + s = *sPtr; + e = s; + while (*e && !isspace(*e)) { + ++e; + } + if (e > s && e[-1] == ';') { + --e; + } + if (*s == '"' && (e - s) > 1 && e[-1] == '"') { + ++s; + --e; + } + *sPtr = s; + *ePtr = e; +} + +/* + * Read additional POST data off of the connection. This would normally be + * called by httpFparse() in response to the method being post. If there is + * no content-type in the request, then this will simply return -1, otherwise + * it will try to read and process any available post data from the client. A + * -1 return indicates a bad response and should probably generate a + * malformed protocol error. + * + * After the post data is read, it will be t->vars:post_query in it's original + * encoded form. + */ + +int httpFread_post(httpTtrans * t) +{ + dynTstring *query; + char buf[1024]; + const char *clength; + ssize_t ret; + size_t ilength; + + query = dynFinit(); + + clength = lstFset_get(t->req_hdrs, "content-length"); + + if (clength == NULL) + return -1; + + ilength = atoi(clength); + + while (ilength > 0) { + if (ilength > sizeof(buf)) + ret = httpFread(t, buf, sizeof(buf)); + else { + ret = httpFread(t, buf, ilength); + } + + if (ret == 0) + break; + + if (ret < 0) { + dynFfree(query); + return -1; + } + dynFappend(query, buf, ret); + ilength -= ret; + } + + lstFset_badd(t->vars, "post_query", 10, dynFgetstr(query), + dynFgetlen(query)); + dynFfree(query); + + return ret; +} + +/* + * Parse a get string query into set + */ +int httpFparse_query(httpTtrans * t, lstTset * set) +{ + char *p, *k, *v; + char query_buf[1024]; + const char *query; + dynTstring *kds, *vds; + + query = lstFset_get(t->vars, "post_query"); + + if (query == NULL) + return 0; + + strncpy(query_buf, query, sizeof(query_buf)); + + p = query_buf; + + kds = dynFinit(); + vds = dynFinit(); + + while (p != NULL) { + k = p; + p = strchr(p, '&'); + if (p != NULL) { + *p++ = '\0'; + } + v = strchr(k, '='); + if (v != NULL) { + *v = '\0'; + } + utlFurl_decode(kds, k); + k = kds->str; + if (v != NULL) { + utlFurl_decode(vds, v + 1); + *v = '='; + v = vds->str; + } + lstFset_add(set, k, v); + } + + dynFfree(kds); + dynFfree(vds); + + return 1; +} + +/* + * Parse a multiquery between start and end into set + */ +static int httpFparse_multiquery(MECHA_UNUSED_ARGUMENT httpTtrans * t, + char *start, char *end, lstTset * set) +{ + dynTstring *kds, *vds; + char *s, *e, *ks, *ke, *fs, *fe, save, saveend; + + kds = dynFinit(); + vds = dynFinit(); + + /* + * Trim off the trailing \r\n and null terminate the input. + */ + + if (end > start && end[-1] == '\n') + --end; + if (end > start && end[-1] == '\r') + --end; + saveend = *end; + *end = '\0'; + + /* + * Scan non-blank lines for the content-disposition header. + */ + + ks = fs = NULL; + while ((e = strchr(start, '\n')) != NULL) { + s = start; + start = e + 1; + if (e > s && e[-1] == '\r') { + --e; + } + if (s == e) { + break; + } + save = *e; + *e = '\0'; + if (strncasecmp(s, "content-disposition", 19) == 0 + && (ks = strstr(s + 19, "name=")) != NULL) { + + /* + * Save the key name and filename. + */ + + ks += 5; + httpFat_end(&ks, &ke); + if ((fs = strstr(s + 19, "filename=")) != NULL) { + fs += 9; + httpFat_end(&fs, &fe); + } + } + *e = save; + } + + /* + * Save the key/value and file contents if found. + */ + + if (ks != NULL) { + dynFappend(kds, ks, ke - ks); + + if (fs == NULL) { + dynFappend(vds, start, end - start); + } else { + /* Handle File Content */ + } + + lstFset_add(set, kds->str, vds->str); + logFmsg(3, "kv: [%s] [%s]", kds->str, vds->str); + } + *end = saveend; + dynFfree(vds); + dynFfree(kds); + + return 0; +} + +const lstTset *httpFget_query(httpTtrans * t) +{ + const char *q_str; + dynTstring *tmp_query; + + if (t->query != NULL) + return t->query; + + q_str = lstFset_get(t->vars, "query"); + if (q_str == NULL) + return NULL; + + tmp_query = dynFinit(); + + utlFurl_decode(tmp_query, q_str); + + t->query = qryFlst_parse(tmp_query->str); + + dynFfree(tmp_query); + + return t->query; +} + +const lstTset *httpFget_post_query(httpTtrans * t) +{ + dynTstring *bound; + char *s, *e; + const char *form; + lstTset *set; + + form = lstFset_get(t->vars, "post_query"); + + if (form == NULL) + return NULL; + + set = lstFset_create("post_query"); + + bound = dynFinit(); + + if (!httpFget_boundry(bound, t)) { + httpFparse_query(t, set); + } else { + s = strstr(form, bound->str); + logFmsg(3, "caught 0x%x", s); + while (s != NULL) { + s += bound->strlen; + if (*s == '\r') + ++s; + if (*s == '\n') + ++s; + e = strstr(s, bound->str); + if (e != NULL) { + httpFparse_multiquery(t, s, e, set); + } + s = e; + } + } + + dynFfree(bound); + + return set; +} + +void httpFset_state(httpTtrans * t, int state) +{ + t->started = state; +} + +int httpFset_nph(httpTtrans * t) +{ + if (t->started == REQ_UNSTARTED) { + t->started = REQ_HEADERSENT; + + return (1); + } else { + return (0); + } +} + +int httpFread(httpTtrans * t, char *buf, size_t len) +{ + return netFconn_read(t->conn, t->reader, buf, len); +} + + +int httpFwrite(httpTtrans * t, const char *buf, size_t len) +{ + int ret; + + if (t->started == REQ_UNSTARTED) { + httpFstart_response(t); + } + + if (t->started == REQ_STARTED) { + t->started = REQ_HEADERSENT; + + ret = netFconn_write_two(t->conn, t->response->str, + t->response->strlen, buf, len); + + return ret; + } + + ret = netFconn_write(t->conn, buf, len); + + return ret; +} + +const char *httpFquery_val(httpTtrans * t, const char *name) +{ + const char *q_str; + dynTstring *tmp_query; + + if (t->query != NULL) + return lstFset_get(t->query, name); + + q_str = lstFset_get(t->vars, "query"); + if (q_str == NULL) + return NULL; + + tmp_query = dynFinit(); + + utlFurl_decode(tmp_query, q_str); + + t->query = qryFlst_parse(tmp_query->str); + + dynFfree(tmp_query); + + if (t->query == NULL) + return NULL; + + return lstFset_get(t->query, name); +} + +int httpFwritef(httpTtrans * t, const char *fmt, ...) +{ + va_list ap; + int ret1 = 0; + int ret2 = 0; + + if (t->started == REQ_UNSTARTED) { + httpFstart_response(t); + } + + if (t->started == REQ_STARTED) { + t->started = REQ_HEADERSENT; + + ret1 = + netFconn_write(t->conn, t->response->str, t->response->strlen); + + if (ret1 < 1) { + return (ret1); + } + } + + va_start(ap, fmt); + + ret2 = _netFconn_writef(t->conn, fmt, &ap); + + va_end(ap); + + if (ret2 < 1) { + return (ret2); + } + + return (ret1 + ret2); +} + + +int httpFdebug_page(httpTtrans * t, MECHA_UNUSED_ARGUMENT char *msg) +{ + int i = 0, ret; + char buf[256]; + const char *m1 = "

t->vars

\n"; + const char *m2 = "

t->req_hdrs

\n"; + const char *m3 = "

t->res_hdrs

\n"; + dynTstring outbuf; + char hostname[64]; + + lstFset_update(t->res_hdrs, "Content-Type", "text/html"); + + gethostname(hostname, 64); + + bzero(&outbuf, sizeof(dynTstring)); + + dynFsappend(&outbuf, "

"); + dynFsappend(&outbuf, hostname); + dynFsappend(&outbuf, "

"); + dynFsappend(&outbuf, m1); + + while (1) { + ret = lstFnth_find(t->vars, i); + if (ret == -1) + break; + snprintf(buf, sizeof(buf), "%s : %s
\n", + t->vars->fields[i].name, t->vars->fields[i].value); + dynFappend(&outbuf, buf, strlen(buf)); + + i++; + } + + i = 0; + dynFsappend(&outbuf, m2); + + while (1) { + ret = lstFnth_find(t->req_hdrs, i); + if (ret == -1) + break; + snprintf(buf, sizeof(buf), "%s : %s
\n", + t->req_hdrs->fields[i].name, + t->req_hdrs->fields[i].value); + dynFappend(&outbuf, buf, strlen(buf)); + i++; + } + + i = 0; + dynFsappend(&outbuf, m3); + + while (1) { + ret = lstFnth_find(t->res_hdrs, i); + if (ret == -1) + break; + snprintf(buf, sizeof(buf), "%s : %s
\n", + t->res_hdrs->fields[i].name, + t->res_hdrs->fields[i].value); + dynFappend(&outbuf, buf, strlen(buf)); + i++; + } + + httpFwrite(t, outbuf.str, strlen(outbuf.str)); + free(outbuf.str); + + return STATUS_EXIT; +} + +int httpFredirect(httpTtrans * t, const char *dest) +{ + assert(t != NULL); + assert(dest != NULL); + + tasFstat_counter_add("http_svc", 0, "httpFredirect", 1); + + lstFset_update(t->res_hdrs, "Location", dest); + + httpFset_status(t, HTTP_FOUND, NULL); + httpFstart_response(t); + + return STATUS_EXIT; +} + +/* + * httpFmaterial_compare checks to see if a is materially similar to b. 0 = + * not similar 1 = similar 2 = provisionally similar (POST data) + */ +int httpFmaterial_compare(const httpTtrans * a, const httpTtrans * b) +{ + const lstTfield *as, *bs; + + assert(a != NULL); + assert(b != NULL); + + as = lstFset_get_field(a->vars, "clf-request", 11); + bs = lstFset_get_field(b->vars, "clf-request", 11); + + if (as == NULL || bs == NULL) { + return (0); + } + + if (lstFfield_value_len(as) != lstFfield_value_len(bs)) { + return (0); + } + + if (memcmp(lstFfield_value(as), lstFfield_value(bs), + lstFfield_value_len(as)) != 0) { + return (0); + } + + /* + * If we got a content-length, there was POST, and we cannot compare the + * post data + */ + + as = lstFset_get_field(a->req_hdrs, "content-length", 14); + + if (as != NULL) { + return 2; + } + + return 1; +} diff --git a/lc-continuity/mk4/modhttp/http.h b/lc-continuity/mk4/modhttp/http.h new file mode 100644 index 0000000000000000000000000000000000000000..93b5997abe65d466da0beba022eb2cae69dbfbf8 --- /dev/null +++ b/lc-continuity/mk4/modhttp/http.h @@ -0,0 +1,102 @@ +/* $Header: /san01/cvs/ashpool/csrc/modhttp/Attic/http.h,v 1.18 2004/04/02 16:17:18 aleigh Exp $ */ + +/* Copyright (c) 1994, 2001 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH + * The copyright notice above does not evidence any + * actual or intended publication of such source code. + * + * Disclosure, copying, distribution, or transmission of + * this code without express permission is prohibited. + */ + +#ifndef HTTP_H +#define HTTP_H + +#include "continuity.h" +#include "mecha.h" + +#define HTTP_OK 200 +#define HTTP_CREATED 201 +#define HTTP_ACCEPTED 202 +#define HTTP_PARTIAL 203 +#define HTTP_NORESPONSE 204 +#define HTTP_MOVED 301 +#define HTTP_FOUND 302 +#define HTTP_METHOD 303 +#define HTTP_NOTMODIFIED 304 +#define HTTP_BADREQUEST 400 +#define HTTP_UNAUTHORIZED 401 +#define HTTP_PAYMENTREQUIRED 402 +#define HTTP_FORBIDDEN 403 +#define HTTP_NOTFOUND 404 +#define HTTP_ERROR 500 +#define HTTP_UNIMPLEMENTED 501 +#define HTTP_TIMEDOUT 502 /* unofficial */ + +#define REQ_UNSTARTED 0 +#define REQ_STARTED 1 +#define REQ_HEADERSENT 2 + +struct httpStrans { + int sd; /* Socket Descriptor */ + uint32_t cli_ipv4_addr; /* Remote IPv4 Address */ + netTreader *reader; /* Network Reader */ + + struct stat statb; /* A stat of the response file */ + + lstTset *req_hdrs; /* Client HTTP headers */ + lstTset *res_hdrs; /* Response HTTP headers */ + lstTset *vars; /* Working Variables */ + lstTset *query; /* Query Cache */ + + int res_code; /* Response Code */ + const char *res_reason; /* Response Message */ + + int started; /* Transaction status */ + int client_read; /* Client status */ + + dynTstring *response; /* HTTP Protocol Response */ + netTconn *conn; + + int has_statb; /* Indicate if statb has been filled in */ +}; +typedef struct httpStrans httpTtrans; + +int httpFcreate_dispatcher(int ipv4port, int ipv4ip); +int httpFthread_settrans(httpTtrans * t); + +/* Handlers */ +void httpFhandler(void *p, const lstTset *arg); +int httpFinit(void *p, const lstTset *opts); + +/* Public Functions */ +httpTtrans *httpFtrans_alloc(void); +void httpFtrans_free(httpTtrans * t); +httpTtrans *httpFthread_gettrans(void); +void httpFset_status(httpTtrans * t, int status, const char *reason); +void httpFstart_response(httpTtrans * t); +void httpFsend_response(httpTtrans * t); +int httpFsend_resp_headers(httpTtrans * t); +int httpFread (httpTtrans * t, char *buf, size_t len); +int httpFwrite(httpTtrans * t, const char *buf, size_t len); +int httpFwritef(httpTtrans *t, const char *fmt, ...); +int httpFredirect(httpTtrans *t, const char *dest); +const lstTset *httpFget_query(httpTtrans * t); +const lstTset *httpFget_post_query(httpTtrans * t); +const char *httpFquery_val(httpTtrans *t, const char *name); + +int httpFread_post(httpTtrans * t); +int httpFdebug_page (httpTtrans * t, char *msg); +int httpFlog_trans(httpTtrans * t, char *msg); +int httpFparse(httpTtrans * t); +int httpFget_boundry(dynTstring * str, httpTtrans * t); +int httpFparse_query(httpTtrans * t, lstTset *set); +int httpFerror_page (httpTtrans * t, const char *msg); +int httpFmaterial_compare(const httpTtrans *trans, const httpTtrans *b); + +void httpFset_state (httpTtrans *t, int state); + +int httpFset_nph (httpTtrans *t); + +#endif diff --git a/lc-continuity/mk4/modhttp/http.xml b/lc-continuity/mk4/modhttp/http.xml new file mode 100644 index 0000000000000000000000000000000000000000..eeee6352b9fdd75404df0148fe51ce3d4709ff97 --- /dev/null +++ b/lc-continuity/mk4/modhttp/http.xml @@ -0,0 +1,4 @@ + + http + httpFinit + diff --git a/lc-continuity/mk4/modimage/CVS/Entries b/lc-continuity/mk4/modimage/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..4a483c935d6482bf0bb6fa4dc3d2936f1bc16ab0 --- /dev/null +++ b/lc-continuity/mk4/modimage/CVS/Entries @@ -0,0 +1,18 @@ +/Makefile.in/1.3/Wed May 12 13:59:10 2004//Tmk4_mod6_rc2 +/cderror.h/1.1/Wed Oct 29 20:54:58 2003//Tmk4_mod6_rc2 +/cdjpeg.h/1.1/Wed Oct 29 20:54:58 2003//Tmk4_mod6_rc2 +/image.c/1.2/Thu Mar 18 15:04:15 2004//Tmk4_mod6_rc2 +/image.xml/1.1/Wed May 12 13:59:10 2004//Tmk4_mod6_rc2 +/jchuff.h/1.1/Wed Oct 29 20:54:58 2003//Tmk4_mod6_rc2 +/jconfig.h/1.1/Wed Oct 29 20:54:58 2003//Tmk4_mod6_rc2 +/jdct.h/1.1/Wed Oct 29 20:54:58 2003//Tmk4_mod6_rc2 +/jdhuff.h/1.1/Wed Oct 29 20:54:58 2003//Tmk4_mod6_rc2 +/jerror.h/1.1/Wed Oct 29 20:54:58 2003//Tmk4_mod6_rc2 +/jinclude.h/1.1/Wed Oct 29 20:54:58 2003//Tmk4_mod6_rc2 +/jmemsys.h/1.1/Wed Oct 29 20:54:58 2003//Tmk4_mod6_rc2 +/jmorecfg.h/1.1/Wed Oct 29 20:54:58 2003//Tmk4_mod6_rc2 +/jpegint.h/1.1/Wed Oct 29 20:54:58 2003//Tmk4_mod6_rc2 +/jpeglib.h/1.1/Wed Oct 29 20:54:58 2003//Tmk4_mod6_rc2 +/jversion.h/1.1/Wed Oct 29 20:54:58 2003//Tmk4_mod6_rc2 +/transupp.h/1.1/Wed Oct 29 20:54:58 2003//Tmk4_mod6_rc2 +D/jpeg-6b//// diff --git a/lc-continuity/mk4/modimage/CVS/Repository b/lc-continuity/mk4/modimage/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..b918a9e3e8388ebe22db9b08db55e81341f24b29 --- /dev/null +++ b/lc-continuity/mk4/modimage/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/modimage diff --git a/lc-continuity/mk4/modimage/CVS/Root b/lc-continuity/mk4/modimage/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/modimage/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/modimage/CVS/Tag b/lc-continuity/mk4/modimage/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/modimage/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/modimage/Makefile.in b/lc-continuity/mk4/modimage/Makefile.in new file mode 100644 index 0000000000000000000000000000000000000000..10c68aa94d94ae7cfeb6e97593728c0f703c491d --- /dev/null +++ b/lc-continuity/mk4/modimage/Makefile.in @@ -0,0 +1,28 @@ +# $Header: /san01/cvs/ashpool/csrc/modimage/Attic/Makefile.in,v 1.3 2004/05/12 13:59:10 aleigh Exp $ + +include ../continuity/lib/env.mk + +SRCS=image.c +OBJS=image.o + +CFLAGS=-I../continuity/include $(CONT_FLAGS) + +world: install + +jpeg-6b/libjpeg.a: + (cd jpeg-6b;./configure;make) + +image.so: jpeg-6b/libjpeg.a $(OBJS) + $(LD_SHARECMD) -o image.so $(OBJS) jpeg-6b/libjpeg.a +clean: + $(RM) $(OBJS) *~ image.so + +install: image.so + cp image.so ../continuity/lib + cp *.h ../continuity/include + cp image.xml ../continuity/lib + + +depend: + $(MAKEDEPEND) $(DEPFLAGS) -I ../continuity/include $(SRCS) + diff --git a/lc-continuity/mk4/modimage/cderror.h b/lc-continuity/mk4/modimage/cderror.h new file mode 100644 index 0000000000000000000000000000000000000000..70435e161c01773d458bb0d00af4446a9158d58a --- /dev/null +++ b/lc-continuity/mk4/modimage/cderror.h @@ -0,0 +1,132 @@ +/* + * cderror.h + * + * Copyright (C) 1994-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file defines the error and message codes for the cjpeg/djpeg + * applications. These strings are not needed as part of the JPEG library + * proper. + * Edit this file to add new codes, or to translate the message strings to + * some other language. + */ + +/* + * To define the enum list of message codes, include this file without + * defining macro JMESSAGE. To create a message string table, include it + * again with a suitable JMESSAGE definition (see jerror.c for an example). + */ +#ifndef JMESSAGE +#ifndef CDERROR_H +#define CDERROR_H +/* First time through, define the enum list */ +#define JMAKE_ENUM_LIST +#else +/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */ +#define JMESSAGE(code,string) +#endif /* CDERROR_H */ +#endif /* JMESSAGE */ + +#ifdef JMAKE_ENUM_LIST + +typedef enum { + +#define JMESSAGE(code,string) code , + +#endif /* JMAKE_ENUM_LIST */ + +JMESSAGE(JMSG_FIRSTADDONCODE=1000, NULL) /* Must be first entry! */ + +#ifdef BMP_SUPPORTED +JMESSAGE(JERR_BMP_BADCMAP, "Unsupported BMP colormap format") +JMESSAGE(JERR_BMP_BADDEPTH, "Only 8- and 24-bit BMP files are supported") +JMESSAGE(JERR_BMP_BADHEADER, "Invalid BMP file: bad header length") +JMESSAGE(JERR_BMP_BADPLANES, "Invalid BMP file: biPlanes not equal to 1") +JMESSAGE(JERR_BMP_COLORSPACE, "BMP output must be grayscale or RGB") +JMESSAGE(JERR_BMP_COMPRESSED, "Sorry, compressed BMPs not yet supported") +JMESSAGE(JERR_BMP_NOT, "Not a BMP file - does not start with BM") +JMESSAGE(JTRC_BMP, "%ux%u 24-bit BMP image") +JMESSAGE(JTRC_BMP_MAPPED, "%ux%u 8-bit colormapped BMP image") +JMESSAGE(JTRC_BMP_OS2, "%ux%u 24-bit OS2 BMP image") +JMESSAGE(JTRC_BMP_OS2_MAPPED, "%ux%u 8-bit colormapped OS2 BMP image") +#endif /* BMP_SUPPORTED */ + +#ifdef GIF_SUPPORTED +JMESSAGE(JERR_GIF_BUG, "GIF output got confused") +JMESSAGE(JERR_GIF_CODESIZE, "Bogus GIF codesize %d") +JMESSAGE(JERR_GIF_COLORSPACE, "GIF output must be grayscale or RGB") +JMESSAGE(JERR_GIF_IMAGENOTFOUND, "Too few images in GIF file") +JMESSAGE(JERR_GIF_NOT, "Not a GIF file") +JMESSAGE(JTRC_GIF, "%ux%ux%d GIF image") +JMESSAGE(JTRC_GIF_BADVERSION, + "Warning: unexpected GIF version number '%c%c%c'") +JMESSAGE(JTRC_GIF_EXTENSION, "Ignoring GIF extension block of type 0x%02x") +JMESSAGE(JTRC_GIF_NONSQUARE, "Caution: nonsquare pixels in input") +JMESSAGE(JWRN_GIF_BADDATA, "Corrupt data in GIF file") +JMESSAGE(JWRN_GIF_CHAR, "Bogus char 0x%02x in GIF file, ignoring") +JMESSAGE(JWRN_GIF_ENDCODE, "Premature end of GIF image") +JMESSAGE(JWRN_GIF_NOMOREDATA, "Ran out of GIF bits") +#endif /* GIF_SUPPORTED */ + +#ifdef PPM_SUPPORTED +JMESSAGE(JERR_PPM_COLORSPACE, "PPM output must be grayscale or RGB") +JMESSAGE(JERR_PPM_NONNUMERIC, "Nonnumeric data in PPM file") +JMESSAGE(JERR_PPM_NOT, "Not a PPM/PGM file") +JMESSAGE(JTRC_PGM, "%ux%u PGM image") +JMESSAGE(JTRC_PGM_TEXT, "%ux%u text PGM image") +JMESSAGE(JTRC_PPM, "%ux%u PPM image") +JMESSAGE(JTRC_PPM_TEXT, "%ux%u text PPM image") +#endif /* PPM_SUPPORTED */ + +#ifdef RLE_SUPPORTED +JMESSAGE(JERR_RLE_BADERROR, "Bogus error code from RLE library") +JMESSAGE(JERR_RLE_COLORSPACE, "RLE output must be grayscale or RGB") +JMESSAGE(JERR_RLE_DIMENSIONS, "Image dimensions (%ux%u) too large for RLE") +JMESSAGE(JERR_RLE_EMPTY, "Empty RLE file") +JMESSAGE(JERR_RLE_EOF, "Premature EOF in RLE header") +JMESSAGE(JERR_RLE_MEM, "Insufficient memory for RLE header") +JMESSAGE(JERR_RLE_NOT, "Not an RLE file") +JMESSAGE(JERR_RLE_TOOMANYCHANNELS, "Cannot handle %d output channels for RLE") +JMESSAGE(JERR_RLE_UNSUPPORTED, "Cannot handle this RLE setup") +JMESSAGE(JTRC_RLE, "%ux%u full-color RLE file") +JMESSAGE(JTRC_RLE_FULLMAP, "%ux%u full-color RLE file with map of length %d") +JMESSAGE(JTRC_RLE_GRAY, "%ux%u grayscale RLE file") +JMESSAGE(JTRC_RLE_MAPGRAY, "%ux%u grayscale RLE file with map of length %d") +JMESSAGE(JTRC_RLE_MAPPED, "%ux%u colormapped RLE file with map of length %d") +#endif /* RLE_SUPPORTED */ + +#ifdef TARGA_SUPPORTED +JMESSAGE(JERR_TGA_BADCMAP, "Unsupported Targa colormap format") +JMESSAGE(JERR_TGA_BADPARMS, "Invalid or unsupported Targa file") +JMESSAGE(JERR_TGA_COLORSPACE, "Targa output must be grayscale or RGB") +JMESSAGE(JTRC_TGA, "%ux%u RGB Targa image") +JMESSAGE(JTRC_TGA_GRAY, "%ux%u grayscale Targa image") +JMESSAGE(JTRC_TGA_MAPPED, "%ux%u colormapped Targa image") +#else +JMESSAGE(JERR_TGA_NOTCOMP, "Targa support was not compiled") +#endif /* TARGA_SUPPORTED */ + +JMESSAGE(JERR_BAD_CMAP_FILE, + "Color map file is invalid or of unsupported format") +JMESSAGE(JERR_TOO_MANY_COLORS, + "Output file format cannot handle %d colormap entries") +JMESSAGE(JERR_UNGETC_FAILED, "ungetc failed") +#ifdef TARGA_SUPPORTED +JMESSAGE(JERR_UNKNOWN_FORMAT, + "Unrecognized input file format --- perhaps you need -targa") +#else +JMESSAGE(JERR_UNKNOWN_FORMAT, "Unrecognized input file format") +#endif +JMESSAGE(JERR_UNSUPPORTED_FORMAT, "Unsupported output file format") + +#ifdef JMAKE_ENUM_LIST + + JMSG_LASTADDONCODE +} ADDON_MESSAGE_CODE; + +#undef JMAKE_ENUM_LIST +#endif /* JMAKE_ENUM_LIST */ + +/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */ +#undef JMESSAGE diff --git a/lc-continuity/mk4/modimage/cdjpeg.h b/lc-continuity/mk4/modimage/cdjpeg.h new file mode 100644 index 0000000000000000000000000000000000000000..2b387b6e5fa7eea99f03d3ce32248c7fe6d9b993 --- /dev/null +++ b/lc-continuity/mk4/modimage/cdjpeg.h @@ -0,0 +1,184 @@ +/* + * cdjpeg.h + * + * Copyright (C) 1994-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains common declarations for the sample applications + * cjpeg and djpeg. It is NOT used by the core JPEG library. + */ + +#define JPEG_CJPEG_DJPEG /* define proper options in jconfig.h */ +#define JPEG_INTERNAL_OPTIONS /* cjpeg.c,djpeg.c need to see xxx_SUPPORTED */ +#include "jinclude.h" +#include "jpeglib.h" +#include "jerror.h" /* get library error codes too */ +#include "cderror.h" /* get application-specific error codes */ + + +/* + * Object interface for cjpeg's source file decoding modules + */ + +typedef struct cjpeg_source_struct * cjpeg_source_ptr; + +struct cjpeg_source_struct { + JMETHOD(void, start_input, (j_compress_ptr cinfo, + cjpeg_source_ptr sinfo)); + JMETHOD(JDIMENSION, get_pixel_rows, (j_compress_ptr cinfo, + cjpeg_source_ptr sinfo)); + JMETHOD(void, finish_input, (j_compress_ptr cinfo, + cjpeg_source_ptr sinfo)); + + FILE *input_file; + + JSAMPARRAY buffer; + JDIMENSION buffer_height; +}; + + +/* + * Object interface for djpeg's output file encoding modules + */ + +typedef struct djpeg_dest_struct * djpeg_dest_ptr; + +struct djpeg_dest_struct { + /* start_output is called after jpeg_start_decompress finishes. + * The color map will be ready at this time, if one is needed. + */ + JMETHOD(void, start_output, (j_decompress_ptr cinfo, + djpeg_dest_ptr dinfo)); + /* Emit the specified number of pixel rows from the buffer. */ + JMETHOD(void, put_pixel_rows, (j_decompress_ptr cinfo, + djpeg_dest_ptr dinfo, + JDIMENSION rows_supplied)); + /* Finish up at the end of the image. */ + JMETHOD(void, finish_output, (j_decompress_ptr cinfo, + djpeg_dest_ptr dinfo)); + + /* Target file spec; filled in by djpeg.c after object is created. */ + FILE * output_file; + + /* Output pixel-row buffer. Created by module init or start_output. + * Width is cinfo->output_width * cinfo->output_components; + * height is buffer_height. + */ + JSAMPARRAY buffer; + JDIMENSION buffer_height; +}; + + +/* + * cjpeg/djpeg may need to perform extra passes to convert to or from + * the source/destination file format. The JPEG library does not know + * about these passes, but we'd like them to be counted by the progress + * monitor. We use an expanded progress monitor object to hold the + * additional pass count. + */ + +struct cdjpeg_progress_mgr { + struct jpeg_progress_mgr pub; /* fields known to JPEG library */ + int completed_extra_passes; /* extra passes completed */ + int total_extra_passes; /* total extra */ + /* last printed percentage stored here to avoid multiple printouts */ + int percent_done; +}; + +typedef struct cdjpeg_progress_mgr * cd_progress_ptr; + + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jinit_read_bmp jIRdBMP +#define jinit_write_bmp jIWrBMP +#define jinit_read_gif jIRdGIF +#define jinit_write_gif jIWrGIF +#define jinit_read_ppm jIRdPPM +#define jinit_write_ppm jIWrPPM +#define jinit_read_rle jIRdRLE +#define jinit_write_rle jIWrRLE +#define jinit_read_targa jIRdTarga +#define jinit_write_targa jIWrTarga +#define read_quant_tables RdQTables +#define read_scan_script RdScnScript +#define set_quant_slots SetQSlots +#define set_sample_factors SetSFacts +#define read_color_map RdCMap +#define enable_signal_catcher EnSigCatcher +#define start_progress_monitor StProgMon +#define end_progress_monitor EnProgMon +#define read_stdin RdStdin +#define write_stdout WrStdout +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + +/* Module selection routines for I/O modules. */ + +EXTERN(cjpeg_source_ptr) jinit_read_bmp JPP((j_compress_ptr cinfo)); +EXTERN(djpeg_dest_ptr) jinit_write_bmp JPP((j_decompress_ptr cinfo, + boolean is_os2)); +EXTERN(cjpeg_source_ptr) jinit_read_gif JPP((j_compress_ptr cinfo)); +EXTERN(djpeg_dest_ptr) jinit_write_gif JPP((j_decompress_ptr cinfo)); +EXTERN(cjpeg_source_ptr) jinit_read_ppm JPP((j_compress_ptr cinfo)); +EXTERN(djpeg_dest_ptr) jinit_write_ppm JPP((j_decompress_ptr cinfo)); +EXTERN(cjpeg_source_ptr) jinit_read_rle JPP((j_compress_ptr cinfo)); +EXTERN(djpeg_dest_ptr) jinit_write_rle JPP((j_decompress_ptr cinfo)); +EXTERN(cjpeg_source_ptr) jinit_read_targa JPP((j_compress_ptr cinfo)); +EXTERN(djpeg_dest_ptr) jinit_write_targa JPP((j_decompress_ptr cinfo)); + +/* cjpeg support routines (in rdswitch.c) */ + +EXTERN(boolean) read_quant_tables JPP((j_compress_ptr cinfo, char * filename, + int scale_factor, boolean force_baseline)); +EXTERN(boolean) read_scan_script JPP((j_compress_ptr cinfo, char * filename)); +EXTERN(boolean) set_quant_slots JPP((j_compress_ptr cinfo, char *arg)); +EXTERN(boolean) set_sample_factors JPP((j_compress_ptr cinfo, char *arg)); + +/* djpeg support routines (in rdcolmap.c) */ + +EXTERN(void) read_color_map JPP((j_decompress_ptr cinfo, FILE * infile)); + +/* common support routines (in cdjpeg.c) */ + +EXTERN(void) enable_signal_catcher JPP((j_common_ptr cinfo)); +EXTERN(void) start_progress_monitor JPP((j_common_ptr cinfo, + cd_progress_ptr progress)); +EXTERN(void) end_progress_monitor JPP((j_common_ptr cinfo)); +EXTERN(boolean) keymatch JPP((char * arg, const char * keyword, int minchars)); +EXTERN(FILE *) read_stdin JPP((void)); +EXTERN(FILE *) write_stdout JPP((void)); + +/* miscellaneous useful macros */ + +#ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */ +#define READ_BINARY "r" +#define WRITE_BINARY "w" +#else +#ifdef VMS /* VMS is very nonstandard */ +#define READ_BINARY "rb", "ctx=stm" +#define WRITE_BINARY "wb", "ctx=stm" +#else /* standard ANSI-compliant case */ +#define READ_BINARY "rb" +#define WRITE_BINARY "wb" +#endif +#endif + +#ifndef EXIT_FAILURE /* define exit() codes if not provided */ +#define EXIT_FAILURE 1 +#endif +#ifndef EXIT_SUCCESS +#ifdef VMS +#define EXIT_SUCCESS 1 /* VMS is very nonstandard */ +#else +#define EXIT_SUCCESS 0 +#endif +#endif +#ifndef EXIT_WARNING +#ifdef VMS +#define EXIT_WARNING 1 /* VMS is very nonstandard */ +#else +#define EXIT_WARNING 2 +#endif +#endif diff --git a/lc-continuity/mk4/modimage/image.c b/lc-continuity/mk4/modimage/image.c new file mode 100644 index 0000000000000000000000000000000000000000..18aee1061ba8c512b5b7712d403a1d20858df258 --- /dev/null +++ b/lc-continuity/mk4/modimage/image.c @@ -0,0 +1,29 @@ +#include +#include +#include "jpeg-6b/jpeglib.h" + +int imgFjpeg_size(char *filename, int *width, int *height) +{ + struct jpeg_decompress_struct cinfo; + struct jpeg_error_mgr jerr; + FILE *infile; + + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_decompress(&cinfo); + + if ((infile = fopen(filename, "rb")) == NULL) { + jpeg_destroy_decompress(&cinfo); + return -1; + } + jpeg_stdio_src(&cinfo, infile); + jpeg_read_header(&cinfo, TRUE); + + fclose(infile); + + *width = cinfo.image_width; + *height = cinfo.image_height; + + jpeg_destroy_decompress(&cinfo); + + return 0; +} diff --git a/lc-continuity/mk4/modimage/image.xml b/lc-continuity/mk4/modimage/image.xml new file mode 100644 index 0000000000000000000000000000000000000000..791a006454850719d89d9bada80e973354593513 --- /dev/null +++ b/lc-continuity/mk4/modimage/image.xml @@ -0,0 +1,3 @@ + + image + diff --git a/lc-continuity/mk4/modimage/jchuff.h b/lc-continuity/mk4/modimage/jchuff.h new file mode 100644 index 0000000000000000000000000000000000000000..a9599fc1e6f9613ca5b7ce02a3b734f0c89cba51 --- /dev/null +++ b/lc-continuity/mk4/modimage/jchuff.h @@ -0,0 +1,47 @@ +/* + * jchuff.h + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains declarations for Huffman entropy encoding routines + * that are shared between the sequential encoder (jchuff.c) and the + * progressive encoder (jcphuff.c). No other modules need to see these. + */ + +/* The legal range of a DCT coefficient is + * -1024 .. +1023 for 8-bit data; + * -16384 .. +16383 for 12-bit data. + * Hence the magnitude should always fit in 10 or 14 bits respectively. + */ + +#if BITS_IN_JSAMPLE == 8 +#define MAX_COEF_BITS 10 +#else +#define MAX_COEF_BITS 14 +#endif + +/* Derived data constructed for each Huffman table */ + +typedef struct { + unsigned int ehufco[256]; /* code for each symbol */ + char ehufsi[256]; /* length of code for each symbol */ + /* If no code has been allocated for a symbol S, ehufsi[S] contains 0 */ +} c_derived_tbl; + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_make_c_derived_tbl jMkCDerived +#define jpeg_gen_optimal_table jGenOptTbl +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + +/* Expand a Huffman table definition into the derived format */ +EXTERN(void) jpeg_make_c_derived_tbl + JPP((j_compress_ptr cinfo, boolean isDC, int tblno, + c_derived_tbl ** pdtbl)); + +/* Generate an optimal table definition given the specified counts */ +EXTERN(void) jpeg_gen_optimal_table + JPP((j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[])); diff --git a/lc-continuity/mk4/modimage/jconfig.h b/lc-continuity/mk4/modimage/jconfig.h new file mode 100644 index 0000000000000000000000000000000000000000..b01fe7bd7c0bbc70b7dd7e80aaa114bb90569871 --- /dev/null +++ b/lc-continuity/mk4/modimage/jconfig.h @@ -0,0 +1,45 @@ +/* jconfig.h. Generated automatically by configure. */ +/* jconfig.cfg --- source file edited by configure script */ +/* see jconfig.doc for explanations */ + +#define HAVE_PROTOTYPES +#define HAVE_UNSIGNED_CHAR +#define HAVE_UNSIGNED_SHORT +#undef void +#undef const +#undef CHAR_IS_UNSIGNED +#define HAVE_STDDEF_H +#define HAVE_STDLIB_H +#undef NEED_BSD_STRINGS +#undef NEED_SYS_TYPES_H +#undef NEED_FAR_POINTERS +#undef NEED_SHORT_EXTERNAL_NAMES +/* Define this if you get warnings about undefined structures. */ +#undef INCOMPLETE_TYPES_BROKEN + +#ifdef JPEG_INTERNALS + +#undef RIGHT_SHIFT_IS_UNSIGNED +#define INLINE +/* These are for configuring the JPEG memory manager. */ +#undef DEFAULT_MAX_MEM +#undef NO_MKTEMP + +#endif /* JPEG_INTERNALS */ + +#ifdef JPEG_CJPEG_DJPEG + +#define BMP_SUPPORTED /* BMP image file format */ +#define GIF_SUPPORTED /* GIF image file format */ +#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ +#undef RLE_SUPPORTED /* Utah RLE image file format */ +#define TARGA_SUPPORTED /* Targa image file format */ + +#undef TWO_FILE_COMMANDLINE +#undef NEED_SIGNAL_CATCHER +#undef DONT_USE_B_MODE + +/* Define this if you want percent-done progress reports from cjpeg/djpeg. */ +#undef PROGRESS_REPORT + +#endif /* JPEG_CJPEG_DJPEG */ diff --git a/lc-continuity/mk4/modimage/jdct.h b/lc-continuity/mk4/modimage/jdct.h new file mode 100644 index 0000000000000000000000000000000000000000..04192a266ae148072feecb5feff6bca796c2b71a --- /dev/null +++ b/lc-continuity/mk4/modimage/jdct.h @@ -0,0 +1,176 @@ +/* + * jdct.h + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This include file contains common declarations for the forward and + * inverse DCT modules. These declarations are private to the DCT managers + * (jcdctmgr.c, jddctmgr.c) and the individual DCT algorithms. + * The individual DCT algorithms are kept in separate files to ease + * machine-dependent tuning (e.g., assembly coding). + */ + + +/* + * A forward DCT routine is given a pointer to a work area of type DCTELEM[]; + * the DCT is to be performed in-place in that buffer. Type DCTELEM is int + * for 8-bit samples, INT32 for 12-bit samples. (NOTE: Floating-point DCT + * implementations use an array of type FAST_FLOAT, instead.) + * The DCT inputs are expected to be signed (range +-CENTERJSAMPLE). + * The DCT outputs are returned scaled up by a factor of 8; they therefore + * have a range of +-8K for 8-bit data, +-128K for 12-bit data. This + * convention improves accuracy in integer implementations and saves some + * work in floating-point ones. + * Quantization of the output coefficients is done by jcdctmgr.c. + */ + +#if BITS_IN_JSAMPLE == 8 +typedef int DCTELEM; /* 16 or 32 bits is fine */ +#else +typedef INT32 DCTELEM; /* must have 32 bits */ +#endif + +typedef JMETHOD(void, forward_DCT_method_ptr, (DCTELEM * data)); +typedef JMETHOD(void, float_DCT_method_ptr, (FAST_FLOAT * data)); + + +/* + * An inverse DCT routine is given a pointer to the input JBLOCK and a pointer + * to an output sample array. The routine must dequantize the input data as + * well as perform the IDCT; for dequantization, it uses the multiplier table + * pointed to by compptr->dct_table. The output data is to be placed into the + * sample array starting at a specified column. (Any row offset needed will + * be applied to the array pointer before it is passed to the IDCT code.) + * Note that the number of samples emitted by the IDCT routine is + * DCT_scaled_size * DCT_scaled_size. + */ + +/* typedef inverse_DCT_method_ptr is declared in jpegint.h */ + +/* + * Each IDCT routine has its own ideas about the best dct_table element type. + */ + +typedef MULTIPLIER ISLOW_MULT_TYPE; /* short or int, whichever is faster */ +#if BITS_IN_JSAMPLE == 8 +typedef MULTIPLIER IFAST_MULT_TYPE; /* 16 bits is OK, use short if faster */ +#define IFAST_SCALE_BITS 2 /* fractional bits in scale factors */ +#else +typedef INT32 IFAST_MULT_TYPE; /* need 32 bits for scaled quantizers */ +#define IFAST_SCALE_BITS 13 /* fractional bits in scale factors */ +#endif +typedef FAST_FLOAT FLOAT_MULT_TYPE; /* preferred floating type */ + + +/* + * Each IDCT routine is responsible for range-limiting its results and + * converting them to unsigned form (0..MAXJSAMPLE). The raw outputs could + * be quite far out of range if the input data is corrupt, so a bulletproof + * range-limiting step is required. We use a mask-and-table-lookup method + * to do the combined operations quickly. See the comments with + * prepare_range_limit_table (in jdmaster.c) for more info. + */ + +#define IDCT_range_limit(cinfo) ((cinfo)->sample_range_limit + CENTERJSAMPLE) + +#define RANGE_MASK (MAXJSAMPLE * 4 + 3) /* 2 bits wider than legal samples */ + + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_fdct_islow jFDislow +#define jpeg_fdct_ifast jFDifast +#define jpeg_fdct_float jFDfloat +#define jpeg_idct_islow jRDislow +#define jpeg_idct_ifast jRDifast +#define jpeg_idct_float jRDfloat +#define jpeg_idct_4x4 jRD4x4 +#define jpeg_idct_2x2 jRD2x2 +#define jpeg_idct_1x1 jRD1x1 +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + +/* Extern declarations for the forward and inverse DCT routines. */ + +EXTERN(void) jpeg_fdct_islow JPP((DCTELEM * data)); +EXTERN(void) jpeg_fdct_ifast JPP((DCTELEM * data)); +EXTERN(void) jpeg_fdct_float JPP((FAST_FLOAT * data)); + +EXTERN(void) jpeg_idct_islow + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_ifast + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_float + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_4x4 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_2x2 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_1x1 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); + + +/* + * Macros for handling fixed-point arithmetic; these are used by many + * but not all of the DCT/IDCT modules. + * + * All values are expected to be of type INT32. + * Fractional constants are scaled left by CONST_BITS bits. + * CONST_BITS is defined within each module using these macros, + * and may differ from one module to the next. + */ + +#define ONE ((INT32) 1) +#define CONST_SCALE (ONE << CONST_BITS) + +/* Convert a positive real constant to an integer scaled by CONST_SCALE. + * Caution: some C compilers fail to reduce "FIX(constant)" at compile time, + * thus causing a lot of useless floating-point operations at run time. + */ + +#define FIX(x) ((INT32) ((x) * CONST_SCALE + 0.5)) + +/* Descale and correctly round an INT32 value that's scaled by N bits. + * We assume RIGHT_SHIFT rounds towards minus infinity, so adding + * the fudge factor is correct for either sign of X. + */ + +#define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n) + +/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. + * This macro is used only when the two inputs will actually be no more than + * 16 bits wide, so that a 16x16->32 bit multiply can be used instead of a + * full 32x32 multiply. This provides a useful speedup on many machines. + * Unfortunately there is no way to specify a 16x16->32 multiply portably + * in C, but some C compilers will do the right thing if you provide the + * correct combination of casts. + */ + +#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */ +#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT16) (const))) +#endif +#ifdef SHORTxLCONST_32 /* known to work with Microsoft C 6.0 */ +#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT32) (const))) +#endif + +#ifndef MULTIPLY16C16 /* default definition */ +#define MULTIPLY16C16(var,const) ((var) * (const)) +#endif + +/* Same except both inputs are variables. */ + +#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */ +#define MULTIPLY16V16(var1,var2) (((INT16) (var1)) * ((INT16) (var2))) +#endif + +#ifndef MULTIPLY16V16 /* default definition */ +#define MULTIPLY16V16(var1,var2) ((var1) * (var2)) +#endif diff --git a/lc-continuity/mk4/modimage/jdhuff.h b/lc-continuity/mk4/modimage/jdhuff.h new file mode 100644 index 0000000000000000000000000000000000000000..ae19b6cafd7e81f94499d92876a6cf88bcafda86 --- /dev/null +++ b/lc-continuity/mk4/modimage/jdhuff.h @@ -0,0 +1,201 @@ +/* + * jdhuff.h + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains declarations for Huffman entropy decoding routines + * that are shared between the sequential decoder (jdhuff.c) and the + * progressive decoder (jdphuff.c). No other modules need to see these. + */ + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_make_d_derived_tbl jMkDDerived +#define jpeg_fill_bit_buffer jFilBitBuf +#define jpeg_huff_decode jHufDecode +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* Derived data constructed for each Huffman table */ + +#define HUFF_LOOKAHEAD 8 /* # of bits of lookahead */ + +typedef struct { + /* Basic tables: (element [0] of each array is unused) */ + INT32 maxcode[18]; /* largest code of length k (-1 if none) */ + /* (maxcode[17] is a sentinel to ensure jpeg_huff_decode terminates) */ + INT32 valoffset[17]; /* huffval[] offset for codes of length k */ + /* valoffset[k] = huffval[] index of 1st symbol of code length k, less + * the smallest code of length k; so given a code of length k, the + * corresponding symbol is huffval[code + valoffset[k]] + */ + + /* Link to public Huffman table (needed only in jpeg_huff_decode) */ + JHUFF_TBL *pub; + + /* Lookahead tables: indexed by the next HUFF_LOOKAHEAD bits of + * the input data stream. If the next Huffman code is no more + * than HUFF_LOOKAHEAD bits long, we can obtain its length and + * the corresponding symbol directly from these tables. + */ + int look_nbits[1< 32 bits on your machine, and shifting/masking longs is + * reasonably fast, making bit_buf_type be long and setting BIT_BUF_SIZE + * appropriately should be a win. Unfortunately we can't define the size + * with something like #define BIT_BUF_SIZE (sizeof(bit_buf_type)*8) + * because not all machines measure sizeof in 8-bit bytes. + */ + +typedef struct { /* Bitreading state saved across MCUs */ + bit_buf_type get_buffer; /* current bit-extraction buffer */ + int bits_left; /* # of unused bits in it */ +} bitread_perm_state; + +typedef struct { /* Bitreading working state within an MCU */ + /* Current data source location */ + /* We need a copy, rather than munging the original, in case of suspension */ + const JOCTET * next_input_byte; /* => next byte to read from source */ + size_t bytes_in_buffer; /* # of bytes remaining in source buffer */ + /* Bit input buffer --- note these values are kept in register variables, + * not in this struct, inside the inner loops. + */ + bit_buf_type get_buffer; /* current bit-extraction buffer */ + int bits_left; /* # of unused bits in it */ + /* Pointer needed by jpeg_fill_bit_buffer. */ + j_decompress_ptr cinfo; /* back link to decompress master record */ +} bitread_working_state; + +/* Macros to declare and load/save bitread local variables. */ +#define BITREAD_STATE_VARS \ + register bit_buf_type get_buffer; \ + register int bits_left; \ + bitread_working_state br_state + +#define BITREAD_LOAD_STATE(cinfop,permstate) \ + br_state.cinfo = cinfop; \ + br_state.next_input_byte = cinfop->src->next_input_byte; \ + br_state.bytes_in_buffer = cinfop->src->bytes_in_buffer; \ + get_buffer = permstate.get_buffer; \ + bits_left = permstate.bits_left; + +#define BITREAD_SAVE_STATE(cinfop,permstate) \ + cinfop->src->next_input_byte = br_state.next_input_byte; \ + cinfop->src->bytes_in_buffer = br_state.bytes_in_buffer; \ + permstate.get_buffer = get_buffer; \ + permstate.bits_left = bits_left + +/* + * These macros provide the in-line portion of bit fetching. + * Use CHECK_BIT_BUFFER to ensure there are N bits in get_buffer + * before using GET_BITS, PEEK_BITS, or DROP_BITS. + * The variables get_buffer and bits_left are assumed to be locals, + * but the state struct might not be (jpeg_huff_decode needs this). + * CHECK_BIT_BUFFER(state,n,action); + * Ensure there are N bits in get_buffer; if suspend, take action. + * val = GET_BITS(n); + * Fetch next N bits. + * val = PEEK_BITS(n); + * Fetch next N bits without removing them from the buffer. + * DROP_BITS(n); + * Discard next N bits. + * The value N should be a simple variable, not an expression, because it + * is evaluated multiple times. + */ + +#define CHECK_BIT_BUFFER(state,nbits,action) \ + { if (bits_left < (nbits)) { \ + if (! jpeg_fill_bit_buffer(&(state),get_buffer,bits_left,nbits)) \ + { action; } \ + get_buffer = (state).get_buffer; bits_left = (state).bits_left; } } + +#define GET_BITS(nbits) \ + (((int) (get_buffer >> (bits_left -= (nbits)))) & ((1<<(nbits))-1)) + +#define PEEK_BITS(nbits) \ + (((int) (get_buffer >> (bits_left - (nbits)))) & ((1<<(nbits))-1)) + +#define DROP_BITS(nbits) \ + (bits_left -= (nbits)) + +/* Load up the bit buffer to a depth of at least nbits */ +EXTERN(boolean) jpeg_fill_bit_buffer + JPP((bitread_working_state * state, register bit_buf_type get_buffer, + register int bits_left, int nbits)); + + +/* + * Code for extracting next Huffman-coded symbol from input bit stream. + * Again, this is time-critical and we make the main paths be macros. + * + * We use a lookahead table to process codes of up to HUFF_LOOKAHEAD bits + * without looping. Usually, more than 95% of the Huffman codes will be 8 + * or fewer bits long. The few overlength codes are handled with a loop, + * which need not be inline code. + * + * Notes about the HUFF_DECODE macro: + * 1. Near the end of the data segment, we may fail to get enough bits + * for a lookahead. In that case, we do it the hard way. + * 2. If the lookahead table contains no entry, the next code must be + * more than HUFF_LOOKAHEAD bits long. + * 3. jpeg_huff_decode returns -1 if forced to suspend. + */ + +#define HUFF_DECODE(result,state,htbl,failaction,slowlabel) \ +{ register int nb, look; \ + if (bits_left < HUFF_LOOKAHEAD) { \ + if (! jpeg_fill_bit_buffer(&state,get_buffer,bits_left, 0)) {failaction;} \ + get_buffer = state.get_buffer; bits_left = state.bits_left; \ + if (bits_left < HUFF_LOOKAHEAD) { \ + nb = 1; goto slowlabel; \ + } \ + } \ + look = PEEK_BITS(HUFF_LOOKAHEAD); \ + if ((nb = htbl->look_nbits[look]) != 0) { \ + DROP_BITS(nb); \ + result = htbl->look_sym[look]; \ + } else { \ + nb = HUFF_LOOKAHEAD+1; \ +slowlabel: \ + if ((result=jpeg_huff_decode(&state,get_buffer,bits_left,htbl,nb)) < 0) \ + { failaction; } \ + get_buffer = state.get_buffer; bits_left = state.bits_left; \ + } \ +} + +/* Out-of-line case for Huffman code fetching */ +EXTERN(int) jpeg_huff_decode + JPP((bitread_working_state * state, register bit_buf_type get_buffer, + register int bits_left, d_derived_tbl * htbl, int min_bits)); diff --git a/lc-continuity/mk4/modimage/jerror.h b/lc-continuity/mk4/modimage/jerror.h new file mode 100644 index 0000000000000000000000000000000000000000..fc2fffeac297bcee557400beefb7b6ce790e79a7 --- /dev/null +++ b/lc-continuity/mk4/modimage/jerror.h @@ -0,0 +1,291 @@ +/* + * jerror.h + * + * Copyright (C) 1994-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file defines the error and message codes for the JPEG library. + * Edit this file to add new codes, or to translate the message strings to + * some other language. + * A set of error-reporting macros are defined too. Some applications using + * the JPEG library may wish to include this file to get the error codes + * and/or the macros. + */ + +/* + * To define the enum list of message codes, include this file without + * defining macro JMESSAGE. To create a message string table, include it + * again with a suitable JMESSAGE definition (see jerror.c for an example). + */ +#ifndef JMESSAGE +#ifndef JERROR_H +/* First time through, define the enum list */ +#define JMAKE_ENUM_LIST +#else +/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */ +#define JMESSAGE(code,string) +#endif /* JERROR_H */ +#endif /* JMESSAGE */ + +#ifdef JMAKE_ENUM_LIST + +typedef enum { + +#define JMESSAGE(code,string) code , + +#endif /* JMAKE_ENUM_LIST */ + +JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */ + +/* For maintenance convenience, list is alphabetical by message code name */ +JMESSAGE(JERR_ARITH_NOTIMPL, + "Sorry, there are legal restrictions on arithmetic coding") +JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix") +JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix") +JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode") +JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS") +JMESSAGE(JERR_BAD_DCT_COEF, "DCT coefficient out of range") +JMESSAGE(JERR_BAD_DCTSIZE, "IDCT output block size %d not supported") +JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition") +JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace") +JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace") +JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length") +JMESSAGE(JERR_BAD_LIB_VERSION, + "Wrong JPEG library version: library is %d, caller expects %d") +JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan") +JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d") +JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d") +JMESSAGE(JERR_BAD_PROGRESSION, + "Invalid progressive parameters Ss=%d Se=%d Ah=%d Al=%d") +JMESSAGE(JERR_BAD_PROG_SCRIPT, + "Invalid progressive parameters at scan script entry %d") +JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors") +JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d") +JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d") +JMESSAGE(JERR_BAD_STRUCT_SIZE, + "JPEG parameter struct mismatch: library thinks size is %u, caller expects %u") +JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access") +JMESSAGE(JERR_BUFFER_SIZE, "Buffer passed to JPEG library is too small") +JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here") +JMESSAGE(JERR_CCIR601_NOTIMPL, "CCIR601 sampling not implemented yet") +JMESSAGE(JERR_COMPONENT_COUNT, "Too many color components: %d, max %d") +JMESSAGE(JERR_CONVERSION_NOTIMPL, "Unsupported color conversion request") +JMESSAGE(JERR_DAC_INDEX, "Bogus DAC index %d") +JMESSAGE(JERR_DAC_VALUE, "Bogus DAC value 0x%x") +JMESSAGE(JERR_DHT_INDEX, "Bogus DHT index %d") +JMESSAGE(JERR_DQT_INDEX, "Bogus DQT index %d") +JMESSAGE(JERR_EMPTY_IMAGE, "Empty JPEG image (DNL not supported)") +JMESSAGE(JERR_EMS_READ, "Read from EMS failed") +JMESSAGE(JERR_EMS_WRITE, "Write to EMS failed") +JMESSAGE(JERR_EOI_EXPECTED, "Didn't expect more than one scan") +JMESSAGE(JERR_FILE_READ, "Input file read error") +JMESSAGE(JERR_FILE_WRITE, "Output file write error --- out of disk space?") +JMESSAGE(JERR_FRACT_SAMPLE_NOTIMPL, "Fractional sampling not implemented yet") +JMESSAGE(JERR_HUFF_CLEN_OVERFLOW, "Huffman code size table overflow") +JMESSAGE(JERR_HUFF_MISSING_CODE, "Missing Huffman code table entry") +JMESSAGE(JERR_IMAGE_TOO_BIG, "Maximum supported image dimension is %u pixels") +JMESSAGE(JERR_INPUT_EMPTY, "Empty input file") +JMESSAGE(JERR_INPUT_EOF, "Premature end of input file") +JMESSAGE(JERR_MISMATCHED_QUANT_TABLE, + "Cannot transcode due to multiple use of quantization table %d") +JMESSAGE(JERR_MISSING_DATA, "Scan script does not transmit all data") +JMESSAGE(JERR_MODE_CHANGE, "Invalid color quantization mode change") +JMESSAGE(JERR_NOTIMPL, "Not implemented yet") +JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time") +JMESSAGE(JERR_NO_BACKING_STORE, "Backing store not supported") +JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined") +JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image") +JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined") +JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x") +JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)") +JMESSAGE(JERR_QUANT_COMPONENTS, + "Cannot quantize more than %d color components") +JMESSAGE(JERR_QUANT_FEW_COLORS, "Cannot quantize to fewer than %d colors") +JMESSAGE(JERR_QUANT_MANY_COLORS, "Cannot quantize to more than %d colors") +JMESSAGE(JERR_SOF_DUPLICATE, "Invalid JPEG file structure: two SOF markers") +JMESSAGE(JERR_SOF_NO_SOS, "Invalid JPEG file structure: missing SOS marker") +JMESSAGE(JERR_SOF_UNSUPPORTED, "Unsupported JPEG process: SOF type 0x%02x") +JMESSAGE(JERR_SOI_DUPLICATE, "Invalid JPEG file structure: two SOI markers") +JMESSAGE(JERR_SOS_NO_SOF, "Invalid JPEG file structure: SOS before SOF") +JMESSAGE(JERR_TFILE_CREATE, "Failed to create temporary file %s") +JMESSAGE(JERR_TFILE_READ, "Read failed on temporary file") +JMESSAGE(JERR_TFILE_SEEK, "Seek failed on temporary file") +JMESSAGE(JERR_TFILE_WRITE, + "Write failed on temporary file --- out of disk space?") +JMESSAGE(JERR_TOO_LITTLE_DATA, "Application transferred too few scanlines") +JMESSAGE(JERR_UNKNOWN_MARKER, "Unsupported marker type 0x%02x") +JMESSAGE(JERR_VIRTUAL_BUG, "Virtual array controller messed up") +JMESSAGE(JERR_WIDTH_OVERFLOW, "Image too wide for this implementation") +JMESSAGE(JERR_XMS_READ, "Read from XMS failed") +JMESSAGE(JERR_XMS_WRITE, "Write to XMS failed") +JMESSAGE(JMSG_COPYRIGHT, JCOPYRIGHT) +JMESSAGE(JMSG_VERSION, JVERSION) +JMESSAGE(JTRC_16BIT_TABLES, + "Caution: quantization tables are too coarse for baseline JPEG") +JMESSAGE(JTRC_ADOBE, + "Adobe APP14 marker: version %d, flags 0x%04x 0x%04x, transform %d") +JMESSAGE(JTRC_APP0, "Unknown APP0 marker (not JFIF), length %u") +JMESSAGE(JTRC_APP14, "Unknown APP14 marker (not Adobe), length %u") +JMESSAGE(JTRC_DAC, "Define Arithmetic Table 0x%02x: 0x%02x") +JMESSAGE(JTRC_DHT, "Define Huffman Table 0x%02x") +JMESSAGE(JTRC_DQT, "Define Quantization Table %d precision %d") +JMESSAGE(JTRC_DRI, "Define Restart Interval %u") +JMESSAGE(JTRC_EMS_CLOSE, "Freed EMS handle %u") +JMESSAGE(JTRC_EMS_OPEN, "Obtained EMS handle %u") +JMESSAGE(JTRC_EOI, "End Of Image") +JMESSAGE(JTRC_HUFFBITS, " %3d %3d %3d %3d %3d %3d %3d %3d") +JMESSAGE(JTRC_JFIF, "JFIF APP0 marker: version %d.%02d, density %dx%d %d") +JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE, + "Warning: thumbnail image size does not match data length %u") +JMESSAGE(JTRC_JFIF_EXTENSION, + "JFIF extension marker: type 0x%02x, length %u") +JMESSAGE(JTRC_JFIF_THUMBNAIL, " with %d x %d thumbnail image") +JMESSAGE(JTRC_MISC_MARKER, "Miscellaneous marker 0x%02x, length %u") +JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x") +JMESSAGE(JTRC_QUANTVALS, " %4u %4u %4u %4u %4u %4u %4u %4u") +JMESSAGE(JTRC_QUANT_3_NCOLORS, "Quantizing to %d = %d*%d*%d colors") +JMESSAGE(JTRC_QUANT_NCOLORS, "Quantizing to %d colors") +JMESSAGE(JTRC_QUANT_SELECTED, "Selected %d colors for quantization") +JMESSAGE(JTRC_RECOVERY_ACTION, "At marker 0x%02x, recovery action %d") +JMESSAGE(JTRC_RST, "RST%d") +JMESSAGE(JTRC_SMOOTH_NOTIMPL, + "Smoothing not supported with nonstandard sampling ratios") +JMESSAGE(JTRC_SOF, "Start Of Frame 0x%02x: width=%u, height=%u, components=%d") +JMESSAGE(JTRC_SOF_COMPONENT, " Component %d: %dhx%dv q=%d") +JMESSAGE(JTRC_SOI, "Start of Image") +JMESSAGE(JTRC_SOS, "Start Of Scan: %d components") +JMESSAGE(JTRC_SOS_COMPONENT, " Component %d: dc=%d ac=%d") +JMESSAGE(JTRC_SOS_PARAMS, " Ss=%d, Se=%d, Ah=%d, Al=%d") +JMESSAGE(JTRC_TFILE_CLOSE, "Closed temporary file %s") +JMESSAGE(JTRC_TFILE_OPEN, "Opened temporary file %s") +JMESSAGE(JTRC_THUMB_JPEG, + "JFIF extension marker: JPEG-compressed thumbnail image, length %u") +JMESSAGE(JTRC_THUMB_PALETTE, + "JFIF extension marker: palette thumbnail image, length %u") +JMESSAGE(JTRC_THUMB_RGB, + "JFIF extension marker: RGB thumbnail image, length %u") +JMESSAGE(JTRC_UNKNOWN_IDS, + "Unrecognized component IDs %d %d %d, assuming YCbCr") +JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u") +JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u") +JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d") +JMESSAGE(JWRN_BOGUS_PROGRESSION, + "Inconsistent progression sequence for component %d coefficient %d") +JMESSAGE(JWRN_EXTRANEOUS_DATA, + "Corrupt JPEG data: %u extraneous bytes before marker 0x%02x") +JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment") +JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code") +JMESSAGE(JWRN_JFIF_MAJOR, "Warning: unknown JFIF revision number %d.%02d") +JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file") +JMESSAGE(JWRN_MUST_RESYNC, + "Corrupt JPEG data: found marker 0x%02x instead of RST%d") +JMESSAGE(JWRN_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG") +JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines") + +#ifdef JMAKE_ENUM_LIST + + JMSG_LASTMSGCODE +} J_MESSAGE_CODE; + +#undef JMAKE_ENUM_LIST +#endif /* JMAKE_ENUM_LIST */ + +/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */ +#undef JMESSAGE + + +#ifndef JERROR_H +#define JERROR_H + +/* Macros to simplify using the error and trace message stuff */ +/* The first parameter is either type of cinfo pointer */ + +/* Fatal errors (print message and exit) */ +#define ERREXIT(cinfo,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT1(cinfo,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT2(cinfo,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT3(cinfo,code,p1,p2,p3) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT4(cinfo,code,p1,p2,p3,p4) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (cinfo)->err->msg_parm.i[3] = (p4), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXITS(cinfo,code,str) \ + ((cinfo)->err->msg_code = (code), \ + strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) + +#define MAKESTMT(stuff) do { stuff } while (0) + +/* Nonfatal errors (we can keep going, but the data is probably corrupt) */ +#define WARNMS(cinfo,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) +#define WARNMS1(cinfo,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) +#define WARNMS2(cinfo,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) + +/* Informational/debugging messages */ +#define TRACEMS(cinfo,lvl,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS1(cinfo,lvl,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS2(cinfo,lvl,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS3(cinfo,lvl,code,p1,p2,p3) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS4(cinfo,lvl,code,p1,p2,p3,p4) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS5(cinfo,lvl,code,p1,p2,p3,p4,p5) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + _mp[4] = (p5); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS8(cinfo,lvl,code,p1,p2,p3,p4,p5,p6,p7,p8) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + _mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMSS(cinfo,lvl,code,str) \ + ((cinfo)->err->msg_code = (code), \ + strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) + +#endif /* JERROR_H */ diff --git a/lc-continuity/mk4/modimage/jinclude.h b/lc-continuity/mk4/modimage/jinclude.h new file mode 100644 index 0000000000000000000000000000000000000000..0a4f15146aeb2070601838439e169509f6fe5b7d --- /dev/null +++ b/lc-continuity/mk4/modimage/jinclude.h @@ -0,0 +1,91 @@ +/* + * jinclude.h + * + * Copyright (C) 1991-1994, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file exists to provide a single place to fix any problems with + * including the wrong system include files. (Common problems are taken + * care of by the standard jconfig symbols, but on really weird systems + * you may have to edit this file.) + * + * NOTE: this file is NOT intended to be included by applications using the + * JPEG library. Most applications need only include jpeglib.h. + */ + + +/* Include auto-config file to find out which system include files we need. */ + +#include "jconfig.h" /* auto configuration options */ +#define JCONFIG_INCLUDED /* so that jpeglib.h doesn't do it again */ + +/* + * We need the NULL macro and size_t typedef. + * On an ANSI-conforming system it is sufficient to include . + * Otherwise, we get them from or ; we may have to + * pull in as well. + * Note that the core JPEG library does not require ; + * only the default error handler and data source/destination modules do. + * But we must pull it in because of the references to FILE in jpeglib.h. + * You can remove those references if you want to compile without . + */ + +#ifdef HAVE_STDDEF_H +#include +#endif + +#ifdef HAVE_STDLIB_H +#include +#endif + +#ifdef NEED_SYS_TYPES_H +#include +#endif + +#include + +/* + * We need memory copying and zeroing functions, plus strncpy(). + * ANSI and System V implementations declare these in . + * BSD doesn't have the mem() functions, but it does have bcopy()/bzero(). + * Some systems may declare memset and memcpy in . + * + * NOTE: we assume the size parameters to these functions are of type size_t. + * Change the casts in these macros if not! + */ + +#ifdef NEED_BSD_STRINGS + +#include +#define MEMZERO(target,size) bzero((void *)(target), (size_t)(size)) +#define MEMCOPY(dest,src,size) bcopy((const void *)(src), (void *)(dest), (size_t)(size)) + +#else /* not BSD, assume ANSI/SysV string lib */ + +#include +#define MEMZERO(target,size) memset((void *)(target), 0, (size_t)(size)) +#define MEMCOPY(dest,src,size) memcpy((void *)(dest), (const void *)(src), (size_t)(size)) + +#endif + +/* + * In ANSI C, and indeed any rational implementation, size_t is also the + * type returned by sizeof(). However, it seems there are some irrational + * implementations out there, in which sizeof() returns an int even though + * size_t is defined as long or unsigned long. To ensure consistent results + * we always use this SIZEOF() macro in place of using sizeof() directly. + */ + +#define SIZEOF(object) ((size_t) sizeof(object)) + +/* + * The modules that use fread() and fwrite() always invoke them through + * these macros. On some systems you may need to twiddle the argument casts. + * CAUTION: argument order is different from underlying functions! + */ + +#define JFREAD(file,buf,sizeofbuf) \ + ((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) +#define JFWRITE(file,buf,sizeofbuf) \ + ((size_t) fwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) diff --git a/lc-continuity/mk4/modimage/jmemsys.h b/lc-continuity/mk4/modimage/jmemsys.h new file mode 100644 index 0000000000000000000000000000000000000000..6c3c6d348f2cf68149087f1906196a470136237e --- /dev/null +++ b/lc-continuity/mk4/modimage/jmemsys.h @@ -0,0 +1,198 @@ +/* + * jmemsys.h + * + * Copyright (C) 1992-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This include file defines the interface between the system-independent + * and system-dependent portions of the JPEG memory manager. No other + * modules need include it. (The system-independent portion is jmemmgr.c; + * there are several different versions of the system-dependent portion.) + * + * This file works as-is for the system-dependent memory managers supplied + * in the IJG distribution. You may need to modify it if you write a + * custom memory manager. If system-dependent changes are needed in + * this file, the best method is to #ifdef them based on a configuration + * symbol supplied in jconfig.h, as we have done with USE_MSDOS_MEMMGR + * and USE_MAC_MEMMGR. + */ + + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_get_small jGetSmall +#define jpeg_free_small jFreeSmall +#define jpeg_get_large jGetLarge +#define jpeg_free_large jFreeLarge +#define jpeg_mem_available jMemAvail +#define jpeg_open_backing_store jOpenBackStore +#define jpeg_mem_init jMemInit +#define jpeg_mem_term jMemTerm +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* + * These two functions are used to allocate and release small chunks of + * memory. (Typically the total amount requested through jpeg_get_small is + * no more than 20K or so; this will be requested in chunks of a few K each.) + * Behavior should be the same as for the standard library functions malloc + * and free; in particular, jpeg_get_small must return NULL on failure. + * On most systems, these ARE malloc and free. jpeg_free_small is passed the + * size of the object being freed, just in case it's needed. + * On an 80x86 machine using small-data memory model, these manage near heap. + */ + +EXTERN(void *) jpeg_get_small JPP((j_common_ptr cinfo, size_t sizeofobject)); +EXTERN(void) jpeg_free_small JPP((j_common_ptr cinfo, void * object, + size_t sizeofobject)); + +/* + * These two functions are used to allocate and release large chunks of + * memory (up to the total free space designated by jpeg_mem_available). + * The interface is the same as above, except that on an 80x86 machine, + * far pointers are used. On most other machines these are identical to + * the jpeg_get/free_small routines; but we keep them separate anyway, + * in case a different allocation strategy is desirable for large chunks. + */ + +EXTERN(void FAR *) jpeg_get_large JPP((j_common_ptr cinfo, + size_t sizeofobject)); +EXTERN(void) jpeg_free_large JPP((j_common_ptr cinfo, void FAR * object, + size_t sizeofobject)); + +/* + * The macro MAX_ALLOC_CHUNK designates the maximum number of bytes that may + * be requested in a single call to jpeg_get_large (and jpeg_get_small for that + * matter, but that case should never come into play). This macro is needed + * to model the 64Kb-segment-size limit of far addressing on 80x86 machines. + * On those machines, we expect that jconfig.h will provide a proper value. + * On machines with 32-bit flat address spaces, any large constant may be used. + * + * NB: jmemmgr.c expects that MAX_ALLOC_CHUNK will be representable as type + * size_t and will be a multiple of sizeof(align_type). + */ + +#ifndef MAX_ALLOC_CHUNK /* may be overridden in jconfig.h */ +#define MAX_ALLOC_CHUNK 1000000000L +#endif + +/* + * This routine computes the total space still available for allocation by + * jpeg_get_large. If more space than this is needed, backing store will be + * used. NOTE: any memory already allocated must not be counted. + * + * There is a minimum space requirement, corresponding to the minimum + * feasible buffer sizes; jmemmgr.c will request that much space even if + * jpeg_mem_available returns zero. The maximum space needed, enough to hold + * all working storage in memory, is also passed in case it is useful. + * Finally, the total space already allocated is passed. If no better + * method is available, cinfo->mem->max_memory_to_use - already_allocated + * is often a suitable calculation. + * + * It is OK for jpeg_mem_available to underestimate the space available + * (that'll just lead to more backing-store access than is really necessary). + * However, an overestimate will lead to failure. Hence it's wise to subtract + * a slop factor from the true available space. 5% should be enough. + * + * On machines with lots of virtual memory, any large constant may be returned. + * Conversely, zero may be returned to always use the minimum amount of memory. + */ + +EXTERN(long) jpeg_mem_available JPP((j_common_ptr cinfo, + long min_bytes_needed, + long max_bytes_needed, + long already_allocated)); + + +/* + * This structure holds whatever state is needed to access a single + * backing-store object. The read/write/close method pointers are called + * by jmemmgr.c to manipulate the backing-store object; all other fields + * are private to the system-dependent backing store routines. + */ + +#define TEMP_NAME_LENGTH 64 /* max length of a temporary file's name */ + + +#ifdef USE_MSDOS_MEMMGR /* DOS-specific junk */ + +typedef unsigned short XMSH; /* type of extended-memory handles */ +typedef unsigned short EMSH; /* type of expanded-memory handles */ + +typedef union { + short file_handle; /* DOS file handle if it's a temp file */ + XMSH xms_handle; /* handle if it's a chunk of XMS */ + EMSH ems_handle; /* handle if it's a chunk of EMS */ +} handle_union; + +#endif /* USE_MSDOS_MEMMGR */ + +#ifdef USE_MAC_MEMMGR /* Mac-specific junk */ +#include +#endif /* USE_MAC_MEMMGR */ + + +typedef struct backing_store_struct * backing_store_ptr; + +typedef struct backing_store_struct { + /* Methods for reading/writing/closing this backing-store object */ + JMETHOD(void, read_backing_store, (j_common_ptr cinfo, + backing_store_ptr info, + void FAR * buffer_address, + long file_offset, long byte_count)); + JMETHOD(void, write_backing_store, (j_common_ptr cinfo, + backing_store_ptr info, + void FAR * buffer_address, + long file_offset, long byte_count)); + JMETHOD(void, close_backing_store, (j_common_ptr cinfo, + backing_store_ptr info)); + + /* Private fields for system-dependent backing-store management */ +#ifdef USE_MSDOS_MEMMGR + /* For the MS-DOS manager (jmemdos.c), we need: */ + handle_union handle; /* reference to backing-store storage object */ + char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */ +#else +#ifdef USE_MAC_MEMMGR + /* For the Mac manager (jmemmac.c), we need: */ + short temp_file; /* file reference number to temp file */ + FSSpec tempSpec; /* the FSSpec for the temp file */ + char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */ +#else + /* For a typical implementation with temp files, we need: */ + FILE * temp_file; /* stdio reference to temp file */ + char temp_name[TEMP_NAME_LENGTH]; /* name of temp file */ +#endif +#endif +} backing_store_info; + + +/* + * Initial opening of a backing-store object. This must fill in the + * read/write/close pointers in the object. The read/write routines + * may take an error exit if the specified maximum file size is exceeded. + * (If jpeg_mem_available always returns a large value, this routine can + * just take an error exit.) + */ + +EXTERN(void) jpeg_open_backing_store JPP((j_common_ptr cinfo, + backing_store_ptr info, + long total_bytes_needed)); + + +/* + * These routines take care of any system-dependent initialization and + * cleanup required. jpeg_mem_init will be called before anything is + * allocated (and, therefore, nothing in cinfo is of use except the error + * manager pointer). It should return a suitable default value for + * max_memory_to_use; this may subsequently be overridden by the surrounding + * application. (Note that max_memory_to_use is only important if + * jpeg_mem_available chooses to consult it ... no one else will.) + * jpeg_mem_term may assume that all requested memory has been freed and that + * all opened backing-store objects have been closed. + */ + +EXTERN(long) jpeg_mem_init JPP((j_common_ptr cinfo)); +EXTERN(void) jpeg_mem_term JPP((j_common_ptr cinfo)); diff --git a/lc-continuity/mk4/modimage/jmorecfg.h b/lc-continuity/mk4/modimage/jmorecfg.h new file mode 100644 index 0000000000000000000000000000000000000000..54a7d1c447e4ed862caf5a905b0275efcf3629ef --- /dev/null +++ b/lc-continuity/mk4/modimage/jmorecfg.h @@ -0,0 +1,363 @@ +/* + * jmorecfg.h + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains additional configuration options that customize the + * JPEG software for special applications or support machine-dependent + * optimizations. Most users will not need to touch this file. + */ + + +/* + * Define BITS_IN_JSAMPLE as either + * 8 for 8-bit sample values (the usual setting) + * 12 for 12-bit sample values + * Only 8 and 12 are legal data precisions for lossy JPEG according to the + * JPEG standard, and the IJG code does not support anything else! + * We do not support run-time selection of data precision, sorry. + */ + +#define BITS_IN_JSAMPLE 8 /* use 8 or 12 */ + + +/* + * Maximum number of components (color channels) allowed in JPEG image. + * To meet the letter of the JPEG spec, set this to 255. However, darn + * few applications need more than 4 channels (maybe 5 for CMYK + alpha + * mask). We recommend 10 as a reasonable compromise; use 4 if you are + * really short on memory. (Each allowed component costs a hundred or so + * bytes of storage, whether actually used in an image or not.) + */ + +#define MAX_COMPONENTS 10 /* maximum number of image components */ + + +/* + * Basic data types. + * You may need to change these if you have a machine with unusual data + * type sizes; for example, "char" not 8 bits, "short" not 16 bits, + * or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits, + * but it had better be at least 16. + */ + +/* Representation of a single sample (pixel element value). + * We frequently allocate large arrays of these, so it's important to keep + * them small. But if you have memory to burn and access to char or short + * arrays is very slow on your hardware, you might want to change these. + */ + +#if BITS_IN_JSAMPLE == 8 +/* JSAMPLE should be the smallest type that will hold the values 0..255. + * You can use a signed char by having GETJSAMPLE mask it with 0xFF. + */ + +#ifdef HAVE_UNSIGNED_CHAR + +typedef unsigned char JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#else /* not HAVE_UNSIGNED_CHAR */ + +typedef char JSAMPLE; +#ifdef CHAR_IS_UNSIGNED +#define GETJSAMPLE(value) ((int) (value)) +#else +#define GETJSAMPLE(value) ((int) (value) & 0xFF) +#endif /* CHAR_IS_UNSIGNED */ + +#endif /* HAVE_UNSIGNED_CHAR */ + +#define MAXJSAMPLE 255 +#define CENTERJSAMPLE 128 + +#endif /* BITS_IN_JSAMPLE == 8 */ + + +#if BITS_IN_JSAMPLE == 12 +/* JSAMPLE should be the smallest type that will hold the values 0..4095. + * On nearly all machines "short" will do nicely. + */ + +typedef short JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#define MAXJSAMPLE 4095 +#define CENTERJSAMPLE 2048 + +#endif /* BITS_IN_JSAMPLE == 12 */ + + +/* Representation of a DCT frequency coefficient. + * This should be a signed value of at least 16 bits; "short" is usually OK. + * Again, we allocate large arrays of these, but you can change to int + * if you have memory to burn and "short" is really slow. + */ + +typedef short JCOEF; + + +/* Compressed datastreams are represented as arrays of JOCTET. + * These must be EXACTLY 8 bits wide, at least once they are written to + * external storage. Note that when using the stdio data source/destination + * managers, this is also the data type passed to fread/fwrite. + */ + +#ifdef HAVE_UNSIGNED_CHAR + +typedef unsigned char JOCTET; +#define GETJOCTET(value) (value) + +#else /* not HAVE_UNSIGNED_CHAR */ + +typedef char JOCTET; +#ifdef CHAR_IS_UNSIGNED +#define GETJOCTET(value) (value) +#else +#define GETJOCTET(value) ((value) & 0xFF) +#endif /* CHAR_IS_UNSIGNED */ + +#endif /* HAVE_UNSIGNED_CHAR */ + + +/* These typedefs are used for various table entries and so forth. + * They must be at least as wide as specified; but making them too big + * won't cost a huge amount of memory, so we don't provide special + * extraction code like we did for JSAMPLE. (In other words, these + * typedefs live at a different point on the speed/space tradeoff curve.) + */ + +/* UINT8 must hold at least the values 0..255. */ + +#ifdef HAVE_UNSIGNED_CHAR +typedef unsigned char UINT8; +#else /* not HAVE_UNSIGNED_CHAR */ +#ifdef CHAR_IS_UNSIGNED +typedef char UINT8; +#else /* not CHAR_IS_UNSIGNED */ +typedef short UINT8; +#endif /* CHAR_IS_UNSIGNED */ +#endif /* HAVE_UNSIGNED_CHAR */ + +/* UINT16 must hold at least the values 0..65535. */ + +#ifdef HAVE_UNSIGNED_SHORT +typedef unsigned short UINT16; +#else /* not HAVE_UNSIGNED_SHORT */ +typedef unsigned int UINT16; +#endif /* HAVE_UNSIGNED_SHORT */ + +/* INT16 must hold at least the values -32768..32767. */ + +#ifndef XMD_H /* X11/xmd.h correctly defines INT16 */ +typedef short INT16; +#endif + +/* INT32 must hold at least signed 32-bit values. */ + +#ifndef XMD_H /* X11/xmd.h correctly defines INT32 */ +typedef long INT32; +#endif + +/* Datatype used for image dimensions. The JPEG standard only supports + * images up to 64K*64K due to 16-bit fields in SOF markers. Therefore + * "unsigned int" is sufficient on all machines. However, if you need to + * handle larger images and you don't mind deviating from the spec, you + * can change this datatype. + */ + +typedef unsigned int JDIMENSION; + +#define JPEG_MAX_DIMENSION 65500L /* a tad under 64K to prevent overflows */ + + +/* These macros are used in all function definitions and extern declarations. + * You could modify them if you need to change function linkage conventions; + * in particular, you'll need to do that to make the library a Windows DLL. + * Another application is to make all functions global for use with debuggers + * or code profilers that require it. + */ + +/* a function called through method pointers: */ +#define METHODDEF(type) static type +/* a function used only in its module: */ +#define LOCAL(type) static type +/* a function referenced thru EXTERNs: */ +#define GLOBAL(type) type +/* a reference to a GLOBAL function: */ +#define EXTERN(type) extern type + + +/* This macro is used to declare a "method", that is, a function pointer. + * We want to supply prototype parameters if the compiler can cope. + * Note that the arglist parameter must be parenthesized! + * Again, you can customize this if you need special linkage keywords. + */ + +#ifdef HAVE_PROTOTYPES +#define JMETHOD(type,methodname,arglist) type (*methodname) arglist +#else +#define JMETHOD(type,methodname,arglist) type (*methodname) () +#endif + + +/* Here is the pseudo-keyword for declaring pointers that must be "far" + * on 80x86 machines. Most of the specialized coding for 80x86 is handled + * by just saying "FAR *" where such a pointer is needed. In a few places + * explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol. + */ + +#ifdef NEED_FAR_POINTERS +#define FAR far +#else +#define FAR +#endif + + +/* + * On a few systems, type boolean and/or its values FALSE, TRUE may appear + * in standard header files. Or you may have conflicts with application- + * specific header files that you want to include together with these files. + * Defining HAVE_BOOLEAN before including jpeglib.h should make it work. + */ + +#ifndef HAVE_BOOLEAN +typedef int boolean; +#endif +#ifndef FALSE /* in case these macros already exist */ +#define FALSE 0 /* values of boolean */ +#endif +#ifndef TRUE +#define TRUE 1 +#endif + + +/* + * The remaining options affect code selection within the JPEG library, + * but they don't need to be visible to most applications using the library. + * To minimize application namespace pollution, the symbols won't be + * defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined. + */ + +#ifdef JPEG_INTERNALS +#define JPEG_INTERNAL_OPTIONS +#endif + +#ifdef JPEG_INTERNAL_OPTIONS + + +/* + * These defines indicate whether to include various optional functions. + * Undefining some of these symbols will produce a smaller but less capable + * library. Note that you can leave certain source files out of the + * compilation/linking process if you've #undef'd the corresponding symbols. + * (You may HAVE to do that if your compiler doesn't like null source files.) + */ + +/* Arithmetic coding is unsupported for legal reasons. Complaints to IBM. */ + +/* Capability options common to encoder and decoder: */ + +#define DCT_ISLOW_SUPPORTED /* slow but accurate integer algorithm */ +#define DCT_IFAST_SUPPORTED /* faster, less accurate integer method */ +#define DCT_FLOAT_SUPPORTED /* floating-point: accurate, fast on fast HW */ + +/* Encoder capability options: */ + +#undef C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ +#define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ +#define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ +#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */ +/* Note: if you selected 12-bit data precision, it is dangerous to turn off + * ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit + * precision, so jchuff.c normally uses entropy optimization to compute + * usable tables for higher precision. If you don't want to do optimization, + * you'll have to supply different default Huffman tables. + * The exact same statements apply for progressive JPEG: the default tables + * don't work for progressive mode. (This may get fixed, however.) + */ +#define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */ + +/* Decoder capability options: */ + +#undef D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ +#define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ +#define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ +#define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */ +#define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */ +#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? */ +#undef UPSAMPLE_SCALING_SUPPORTED /* Output rescaling at upsample stage? */ +#define UPSAMPLE_MERGING_SUPPORTED /* Fast path for sloppy upsampling? */ +#define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */ +#define QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */ + +/* more capability options later, no doubt */ + + +/* + * Ordering of RGB data in scanlines passed to or from the application. + * If your application wants to deal with data in the order B,G,R, just + * change these macros. You can also deal with formats such as R,G,B,X + * (one extra byte per pixel) by changing RGB_PIXELSIZE. Note that changing + * the offsets will also change the order in which colormap data is organized. + * RESTRICTIONS: + * 1. The sample applications cjpeg,djpeg do NOT support modified RGB formats. + * 2. These macros only affect RGB<=>YCbCr color conversion, so they are not + * useful if you are using JPEG color spaces other than YCbCr or grayscale. + * 3. The color quantizer modules will not behave desirably if RGB_PIXELSIZE + * is not 3 (they don't understand about dummy color components!). So you + * can't use color quantization if you change that value. + */ + +#define RGB_RED 0 /* Offset of Red in an RGB scanline element */ +#define RGB_GREEN 1 /* Offset of Green */ +#define RGB_BLUE 2 /* Offset of Blue */ +#define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */ + + +/* Definitions for speed-related optimizations. */ + + +/* If your compiler supports inline functions, define INLINE + * as the inline keyword; otherwise define it as empty. + */ + +#ifndef INLINE +#ifdef __GNUC__ /* for instance, GNU C knows about inline */ +#define INLINE __inline__ +#endif +#ifndef INLINE +#define INLINE /* default is to define it as empty */ +#endif +#endif + + +/* On some machines (notably 68000 series) "int" is 32 bits, but multiplying + * two 16-bit shorts is faster than multiplying two ints. Define MULTIPLIER + * as short on such a machine. MULTIPLIER must be at least 16 bits wide. + */ + +#ifndef MULTIPLIER +#define MULTIPLIER int /* type for fastest integer multiply */ +#endif + + +/* FAST_FLOAT should be either float or double, whichever is done faster + * by your compiler. (Note that this type is only used in the floating point + * DCT routines, so it only matters if you've defined DCT_FLOAT_SUPPORTED.) + * Typically, float is faster in ANSI C compilers, while double is faster in + * pre-ANSI compilers (because they insist on converting to double anyway). + * The code below therefore chooses float if we have ANSI-style prototypes. + */ + +#ifndef FAST_FLOAT +#ifdef HAVE_PROTOTYPES +#define FAST_FLOAT float +#else +#define FAST_FLOAT double +#endif +#endif + +#endif /* JPEG_INTERNAL_OPTIONS */ diff --git a/lc-continuity/mk4/modimage/jpeg-6b/.cvsignore b/lc-continuity/mk4/modimage/jpeg-6b/.cvsignore new file mode 100644 index 0000000000000000000000000000000000000000..eb0845d164e81293c4d84f7d61e1bbe0aa965195 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/.cvsignore @@ -0,0 +1,9 @@ +config.log +jconfig.h +config.status +Makefile +cjpeg +djpeg +jpegtran +rdjpgcom +wrjpgcom diff --git a/lc-continuity/mk4/modimage/jpeg-6b/CVS/Entries b/lc-continuity/mk4/modimage/jpeg-6b/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..5c287a9a1eb5ac84950d5657d9599aa7e6e9f4c5 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/CVS/Entries @@ -0,0 +1,141 @@ +/.cvsignore/1.1/Thu Mar 11 01:11:48 2004//Tmk4_mod6_rc2 +/README/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/ansi2knr.1/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/ansi2knr.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/cderror.h/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/cdjpeg.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/cdjpeg.h/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/change.log/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/cjpeg.1/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/cjpeg.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/ckconfig.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/coderules.doc/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/config.guess/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/config.sub/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/configure/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/djpeg.1/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/djpeg.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/example.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/filelist.doc/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/install-sh/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/install.doc/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jcapimin.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jcapistd.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jccoefct.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jccolor.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jcdctmgr.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jchuff.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jchuff.h/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jcinit.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jcmainct.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jcmarker.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jcmaster.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jcomapi.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jconfig.bcc/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jconfig.cfg/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jconfig.dj/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jconfig.doc/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jconfig.mac/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jconfig.manx/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jconfig.mc6/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jconfig.sas/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jconfig.st/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jconfig.vc/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jconfig.vms/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jconfig.wat/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jcparam.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jcphuff.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jcprepct.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jcsample.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jctrans.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jdapimin.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jdapistd.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jdatadst.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jdatasrc.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jdcoefct.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jdcolor.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jdct.h/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jddctmgr.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jdhuff.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jdhuff.h/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jdinput.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jdmainct.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jdmarker.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jdmaster.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jdmerge.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jdphuff.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jdpostct.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jdsample.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jdtrans.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jerror.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jerror.h/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jfdctflt.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jfdctfst.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jfdctint.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jidctflt.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jidctfst.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jidctint.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jidctred.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jinclude.h/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jmemansi.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jmemdos.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jmemdosa.asm/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jmemmac.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jmemmgr.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jmemname.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jmemnobs.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jmemsys.h/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jmorecfg.h/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jpegint.h/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jpeglib.h/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jpegtran.1/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jpegtran.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jquant1.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jquant2.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jutils.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/jversion.h/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/libjpeg.doc/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/ltconfig/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/ltmain.sh/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/makcjpeg.st/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/makdjpeg.st/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/makeapps.ds/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/makefile.ansi/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/makefile.bcc/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/makefile.cfg/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/makefile.dj/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/makefile.manx/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/makefile.mc6/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/makefile.mms/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/makefile.sas/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/makefile.unix/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/makefile.vc/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/makefile.vms/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/makefile.wat/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/makelib.ds/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/makeproj.mac/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/makljpeg.st/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/maktjpeg.st/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/makvms.opt/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/rdbmp.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/rdcolmap.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/rdgif.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/rdjpgcom.1/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/rdjpgcom.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/rdppm.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/rdrle.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/rdswitch.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/rdtarga.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/structure.doc/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/transupp.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/transupp.h/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/usage.doc/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/wizard.doc/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/wrbmp.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/wrgif.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/wrjpgcom.1/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/wrjpgcom.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/wrppm.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/wrrle.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +/wrtarga.c/1.1.1.1/Wed Oct 29 20:52:41 2003//Tmk4_mod6_rc2 +D diff --git a/lc-continuity/mk4/modimage/jpeg-6b/CVS/Repository b/lc-continuity/mk4/modimage/jpeg-6b/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..40b4abf294e29b3cf6f7f8e3d24c8c606452d32e --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/modimage/jpeg-6b diff --git a/lc-continuity/mk4/modimage/jpeg-6b/CVS/Root b/lc-continuity/mk4/modimage/jpeg-6b/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/modimage/jpeg-6b/CVS/Tag b/lc-continuity/mk4/modimage/jpeg-6b/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/modimage/jpeg-6b/README b/lc-continuity/mk4/modimage/jpeg-6b/README new file mode 100644 index 0000000000000000000000000000000000000000..86cc20669d6123ee2999fd0c8f6c21641825fda6 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/README @@ -0,0 +1,385 @@ +The Independent JPEG Group's JPEG software +========================================== + +README for release 6b of 27-Mar-1998 +==================================== + +This distribution contains the sixth public release of the Independent JPEG +Group's free JPEG software. You are welcome to redistribute this software and +to use it for any purpose, subject to the conditions under LEGAL ISSUES, below. + +Serious users of this software (particularly those incorporating it into +larger programs) should contact IJG at jpeg-info@uunet.uu.net to be added to +our electronic mailing list. Mailing list members are notified of updates +and have a chance to participate in technical discussions, etc. + +This software is the work of Tom Lane, Philip Gladstone, Jim Boucher, +Lee Crocker, Julian Minguillon, Luis Ortiz, George Phillips, Davide Rossi, +Guido Vollbeding, Ge' Weijers, and other members of the Independent JPEG +Group. + +IJG is not affiliated with the official ISO JPEG standards committee. + + +DOCUMENTATION ROADMAP +===================== + +This file contains the following sections: + +OVERVIEW General description of JPEG and the IJG software. +LEGAL ISSUES Copyright, lack of warranty, terms of distribution. +REFERENCES Where to learn more about JPEG. +ARCHIVE LOCATIONS Where to find newer versions of this software. +RELATED SOFTWARE Other stuff you should get. +FILE FORMAT WARS Software *not* to get. +TO DO Plans for future IJG releases. + +Other documentation files in the distribution are: + +User documentation: + install.doc How to configure and install the IJG software. + usage.doc Usage instructions for cjpeg, djpeg, jpegtran, + rdjpgcom, and wrjpgcom. + *.1 Unix-style man pages for programs (same info as usage.doc). + wizard.doc Advanced usage instructions for JPEG wizards only. + change.log Version-to-version change highlights. +Programmer and internal documentation: + libjpeg.doc How to use the JPEG library in your own programs. + example.c Sample code for calling the JPEG library. + structure.doc Overview of the JPEG library's internal structure. + filelist.doc Road map of IJG files. + coderules.doc Coding style rules --- please read if you contribute code. + +Please read at least the files install.doc and usage.doc. Useful information +can also be found in the JPEG FAQ (Frequently Asked Questions) article. See +ARCHIVE LOCATIONS below to find out where to obtain the FAQ article. + +If you want to understand how the JPEG code works, we suggest reading one or +more of the REFERENCES, then looking at the documentation files (in roughly +the order listed) before diving into the code. + + +OVERVIEW +======== + +This package contains C software to implement JPEG image compression and +decompression. JPEG (pronounced "jay-peg") is a standardized compression +method for full-color and gray-scale images. JPEG is intended for compressing +"real-world" scenes; line drawings, cartoons and other non-realistic images +are not its strong suit. JPEG is lossy, meaning that the output image is not +exactly identical to the input image. Hence you must not use JPEG if you +have to have identical output bits. However, on typical photographic images, +very good compression levels can be obtained with no visible change, and +remarkably high compression levels are possible if you can tolerate a +low-quality image. For more details, see the references, or just experiment +with various compression settings. + +This software implements JPEG baseline, extended-sequential, and progressive +compression processes. Provision is made for supporting all variants of these +processes, although some uncommon parameter settings aren't implemented yet. +For legal reasons, we are not distributing code for the arithmetic-coding +variants of JPEG; see LEGAL ISSUES. We have made no provision for supporting +the hierarchical or lossless processes defined in the standard. + +We provide a set of library routines for reading and writing JPEG image files, +plus two sample applications "cjpeg" and "djpeg", which use the library to +perform conversion between JPEG and some other popular image file formats. +The library is intended to be reused in other applications. + +In order to support file conversion and viewing software, we have included +considerable functionality beyond the bare JPEG coding/decoding capability; +for example, the color quantization modules are not strictly part of JPEG +decoding, but they are essential for output to colormapped file formats or +colormapped displays. These extra functions can be compiled out of the +library if not required for a particular application. We have also included +"jpegtran", a utility for lossless transcoding between different JPEG +processes, and "rdjpgcom" and "wrjpgcom", two simple applications for +inserting and extracting textual comments in JFIF files. + +The emphasis in designing this software has been on achieving portability and +flexibility, while also making it fast enough to be useful. In particular, +the software is not intended to be read as a tutorial on JPEG. (See the +REFERENCES section for introductory material.) Rather, it is intended to +be reliable, portable, industrial-strength code. We do not claim to have +achieved that goal in every aspect of the software, but we strive for it. + +We welcome the use of this software as a component of commercial products. +No royalty is required, but we do ask for an acknowledgement in product +documentation, as described under LEGAL ISSUES. + + +LEGAL ISSUES +============ + +In plain English: + +1. We don't promise that this software works. (But if you find any bugs, + please let us know!) +2. You can use this software for whatever you want. You don't have to pay us. +3. You may not pretend that you wrote this software. If you use it in a + program, you must acknowledge somewhere in your documentation that + you've used the IJG code. + +In legalese: + +The authors make NO WARRANTY or representation, either express or implied, +with respect to this software, its quality, accuracy, merchantability, or +fitness for a particular purpose. This software is provided "AS IS", and you, +its user, assume the entire risk as to its quality and accuracy. + +This software is copyright (C) 1991-1998, Thomas G. Lane. +All Rights Reserved except as specified below. + +Permission is hereby granted to use, copy, modify, and distribute this +software (or portions thereof) for any purpose, without fee, subject to these +conditions: +(1) If any part of the source code for this software is distributed, then this +README file must be included, with this copyright and no-warranty notice +unaltered; and any additions, deletions, or changes to the original files +must be clearly indicated in accompanying documentation. +(2) If only executable code is distributed, then the accompanying +documentation must state that "this software is based in part on the work of +the Independent JPEG Group". +(3) Permission for use of this software is granted only if the user accepts +full responsibility for any undesirable consequences; the authors accept +NO LIABILITY for damages of any kind. + +These conditions apply to any software derived from or based on the IJG code, +not just to the unmodified library. If you use our work, you ought to +acknowledge us. + +Permission is NOT granted for the use of any IJG author's name or company name +in advertising or publicity relating to this software or products derived from +it. This software may be referred to only as "the Independent JPEG Group's +software". + +We specifically permit and encourage the use of this software as the basis of +commercial products, provided that all warranty or liability claims are +assumed by the product vendor. + + +ansi2knr.c is included in this distribution by permission of L. Peter Deutsch, +sole proprietor of its copyright holder, Aladdin Enterprises of Menlo Park, CA. +ansi2knr.c is NOT covered by the above copyright and conditions, but instead +by the usual distribution terms of the Free Software Foundation; principally, +that you must include source code if you redistribute it. (See the file +ansi2knr.c for full details.) However, since ansi2knr.c is not needed as part +of any program generated from the IJG code, this does not limit you more than +the foregoing paragraphs do. + +The Unix configuration script "configure" was produced with GNU Autoconf. +It is copyright by the Free Software Foundation but is freely distributable. +The same holds for its supporting scripts (config.guess, config.sub, +ltconfig, ltmain.sh). Another support script, install-sh, is copyright +by M.I.T. but is also freely distributable. + +It appears that the arithmetic coding option of the JPEG spec is covered by +patents owned by IBM, AT&T, and Mitsubishi. Hence arithmetic coding cannot +legally be used without obtaining one or more licenses. For this reason, +support for arithmetic coding has been removed from the free JPEG software. +(Since arithmetic coding provides only a marginal gain over the unpatented +Huffman mode, it is unlikely that very many implementations will support it.) +So far as we are aware, there are no patent restrictions on the remaining +code. + +The IJG distribution formerly included code to read and write GIF files. +To avoid entanglement with the Unisys LZW patent, GIF reading support has +been removed altogether, and the GIF writer has been simplified to produce +"uncompressed GIFs". This technique does not use the LZW algorithm; the +resulting GIF files are larger than usual, but are readable by all standard +GIF decoders. + +We are required to state that + "The Graphics Interchange Format(c) is the Copyright property of + CompuServe Incorporated. GIF(sm) is a Service Mark property of + CompuServe Incorporated." + + +REFERENCES +========== + +We highly recommend reading one or more of these references before trying to +understand the innards of the JPEG software. + +The best short technical introduction to the JPEG compression algorithm is + Wallace, Gregory K. "The JPEG Still Picture Compression Standard", + Communications of the ACM, April 1991 (vol. 34 no. 4), pp. 30-44. +(Adjacent articles in that issue discuss MPEG motion picture compression, +applications of JPEG, and related topics.) If you don't have the CACM issue +handy, a PostScript file containing a revised version of Wallace's article is +available at ftp://ftp.uu.net/graphics/jpeg/wallace.ps.gz. The file (actually +a preprint for an article that appeared in IEEE Trans. Consumer Electronics) +omits the sample images that appeared in CACM, but it includes corrections +and some added material. Note: the Wallace article is copyright ACM and IEEE, +and it may not be used for commercial purposes. + +A somewhat less technical, more leisurely introduction to JPEG can be found in +"The Data Compression Book" by Mark Nelson and Jean-loup Gailly, published by +M&T Books (New York), 2nd ed. 1996, ISBN 1-55851-434-1. This book provides +good explanations and example C code for a multitude of compression methods +including JPEG. It is an excellent source if you are comfortable reading C +code but don't know much about data compression in general. The book's JPEG +sample code is far from industrial-strength, but when you are ready to look +at a full implementation, you've got one here... + +The best full description of JPEG is the textbook "JPEG Still Image Data +Compression Standard" by William B. Pennebaker and Joan L. Mitchell, published +by Van Nostrand Reinhold, 1993, ISBN 0-442-01272-1. Price US$59.95, 638 pp. +The book includes the complete text of the ISO JPEG standards (DIS 10918-1 +and draft DIS 10918-2). This is by far the most complete exposition of JPEG +in existence, and we highly recommend it. + +The JPEG standard itself is not available electronically; you must order a +paper copy through ISO or ITU. (Unless you feel a need to own a certified +official copy, we recommend buying the Pennebaker and Mitchell book instead; +it's much cheaper and includes a great deal of useful explanatory material.) +In the USA, copies of the standard may be ordered from ANSI Sales at (212) +642-4900, or from Global Engineering Documents at (800) 854-7179. (ANSI +doesn't take credit card orders, but Global does.) It's not cheap: as of +1992, ANSI was charging $95 for Part 1 and $47 for Part 2, plus 7% +shipping/handling. The standard is divided into two parts, Part 1 being the +actual specification, while Part 2 covers compliance testing methods. Part 1 +is titled "Digital Compression and Coding of Continuous-tone Still Images, +Part 1: Requirements and guidelines" and has document numbers ISO/IEC IS +10918-1, ITU-T T.81. Part 2 is titled "Digital Compression and Coding of +Continuous-tone Still Images, Part 2: Compliance testing" and has document +numbers ISO/IEC IS 10918-2, ITU-T T.83. + +Some extensions to the original JPEG standard are defined in JPEG Part 3, +a newer ISO standard numbered ISO/IEC IS 10918-3 and ITU-T T.84. IJG +currently does not support any Part 3 extensions. + +The JPEG standard does not specify all details of an interchangeable file +format. For the omitted details we follow the "JFIF" conventions, revision +1.02. A copy of the JFIF spec is available from: + Literature Department + C-Cube Microsystems, Inc. + 1778 McCarthy Blvd. + Milpitas, CA 95035 + phone (408) 944-6300, fax (408) 944-6314 +A PostScript version of this document is available by FTP at +ftp://ftp.uu.net/graphics/jpeg/jfif.ps.gz. There is also a plain text +version at ftp://ftp.uu.net/graphics/jpeg/jfif.txt.gz, but it is missing +the figures. + +The TIFF 6.0 file format specification can be obtained by FTP from +ftp://ftp.sgi.com/graphics/tiff/TIFF6.ps.gz. The JPEG incorporation scheme +found in the TIFF 6.0 spec of 3-June-92 has a number of serious problems. +IJG does not recommend use of the TIFF 6.0 design (TIFF Compression tag 6). +Instead, we recommend the JPEG design proposed by TIFF Technical Note #2 +(Compression tag 7). Copies of this Note can be obtained from ftp.sgi.com or +from ftp://ftp.uu.net/graphics/jpeg/. It is expected that the next revision +of the TIFF spec will replace the 6.0 JPEG design with the Note's design. +Although IJG's own code does not support TIFF/JPEG, the free libtiff library +uses our library to implement TIFF/JPEG per the Note. libtiff is available +from ftp://ftp.sgi.com/graphics/tiff/. + + +ARCHIVE LOCATIONS +================= + +The "official" archive site for this software is ftp.uu.net (Internet +address 192.48.96.9). The most recent released version can always be found +there in directory graphics/jpeg. This particular version will be archived +as ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6b.tar.gz. If you don't have +direct Internet access, UUNET's archives are also available via UUCP; contact +help@uunet.uu.net for information on retrieving files that way. + +Numerous Internet sites maintain copies of the UUNET files. However, only +ftp.uu.net is guaranteed to have the latest official version. + +You can also obtain this software in DOS-compatible "zip" archive format from +the SimTel archives (ftp://ftp.simtel.net/pub/simtelnet/msdos/graphics/), or +on CompuServe in the Graphics Support forum (GO CIS:GRAPHSUP), library 12 +"JPEG Tools". Again, these versions may sometimes lag behind the ftp.uu.net +release. + +The JPEG FAQ (Frequently Asked Questions) article is a useful source of +general information about JPEG. It is updated constantly and therefore is +not included in this distribution. The FAQ is posted every two weeks to +Usenet newsgroups comp.graphics.misc, news.answers, and other groups. +It is available on the World Wide Web at http://www.faqs.org/faqs/jpeg-faq/ +and other news.answers archive sites, including the official news.answers +archive at rtfm.mit.edu: ftp://rtfm.mit.edu/pub/usenet/news.answers/jpeg-faq/. +If you don't have Web or FTP access, send e-mail to mail-server@rtfm.mit.edu +with body + send usenet/news.answers/jpeg-faq/part1 + send usenet/news.answers/jpeg-faq/part2 + + +RELATED SOFTWARE +================ + +Numerous viewing and image manipulation programs now support JPEG. (Quite a +few of them use this library to do so.) The JPEG FAQ described above lists +some of the more popular free and shareware viewers, and tells where to +obtain them on Internet. + +If you are on a Unix machine, we highly recommend Jef Poskanzer's free +PBMPLUS software, which provides many useful operations on PPM-format image +files. In particular, it can convert PPM images to and from a wide range of +other formats, thus making cjpeg/djpeg considerably more useful. The latest +version is distributed by the NetPBM group, and is available from numerous +sites, notably ftp://wuarchive.wustl.edu/graphics/graphics/packages/NetPBM/. +Unfortunately PBMPLUS/NETPBM is not nearly as portable as the IJG software is; +you are likely to have difficulty making it work on any non-Unix machine. + +A different free JPEG implementation, written by the PVRG group at Stanford, +is available from ftp://havefun.stanford.edu/pub/jpeg/. This program +is designed for research and experimentation rather than production use; +it is slower, harder to use, and less portable than the IJG code, but it +is easier to read and modify. Also, the PVRG code supports lossless JPEG, +which we do not. (On the other hand, it doesn't do progressive JPEG.) + + +FILE FORMAT WARS +================ + +Some JPEG programs produce files that are not compatible with our library. +The root of the problem is that the ISO JPEG committee failed to specify a +concrete file format. Some vendors "filled in the blanks" on their own, +creating proprietary formats that no one else could read. (For example, none +of the early commercial JPEG implementations for the Macintosh were able to +exchange compressed files.) + +The file format we have adopted is called JFIF (see REFERENCES). This format +has been agreed to by a number of major commercial JPEG vendors, and it has +become the de facto standard. JFIF is a minimal or "low end" representation. +We recommend the use of TIFF/JPEG (TIFF revision 6.0 as modified by TIFF +Technical Note #2) for "high end" applications that need to record a lot of +additional data about an image. TIFF/JPEG is fairly new and not yet widely +supported, unfortunately. + +The upcoming JPEG Part 3 standard defines a file format called SPIFF. +SPIFF is interoperable with JFIF, in the sense that most JFIF decoders should +be able to read the most common variant of SPIFF. SPIFF has some technical +advantages over JFIF, but its major claim to fame is simply that it is an +official standard rather than an informal one. At this point it is unclear +whether SPIFF will supersede JFIF or whether JFIF will remain the de-facto +standard. IJG intends to support SPIFF once the standard is frozen, but we +have not decided whether it should become our default output format or not. +(In any case, our decoder will remain capable of reading JFIF indefinitely.) + +Various proprietary file formats incorporating JPEG compression also exist. +We have little or no sympathy for the existence of these formats. Indeed, +one of the original reasons for developing this free software was to help +force convergence on common, open format standards for JPEG files. Don't +use a proprietary file format! + + +TO DO +===== + +The major thrust for v7 will probably be improvement of visual quality. +The current method for scaling the quantization tables is known not to be +very good at low Q values. We also intend to investigate block boundary +smoothing, "poor man's variable quantization", and other means of improving +quality-vs-file-size performance without sacrificing compatibility. + +In future versions, we are considering supporting some of the upcoming JPEG +Part 3 extensions --- principally, variable quantization and the SPIFF file +format. + +As always, speeding things up is of great interest. + +Please send bug reports, offers of help, etc. to jpeg-info@uunet.uu.net. diff --git a/lc-continuity/mk4/modimage/jpeg-6b/ansi2knr.1 b/lc-continuity/mk4/modimage/jpeg-6b/ansi2knr.1 new file mode 100644 index 0000000000000000000000000000000000000000..f9ee5a631c2ee870819fefe6c1c701eb426d1508 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/ansi2knr.1 @@ -0,0 +1,36 @@ +.TH ANSI2KNR 1 "19 Jan 1996" +.SH NAME +ansi2knr \- convert ANSI C to Kernighan & Ritchie C +.SH SYNOPSIS +.I ansi2knr +[--varargs] input_file [output_file] +.SH DESCRIPTION +If no output_file is supplied, output goes to stdout. +.br +There are no error messages. +.sp +.I ansi2knr +recognizes function definitions by seeing a non-keyword identifier at the left +margin, followed by a left parenthesis, with a right parenthesis as the last +character on the line, and with a left brace as the first token on the +following line (ignoring possible intervening comments). It will recognize a +multi-line header provided that no intervening line ends with a left or right +brace or a semicolon. These algorithms ignore whitespace and comments, except +that the function name must be the first thing on the line. +.sp +The following constructs will confuse it: +.br + - Any other construct that starts at the left margin and follows the +above syntax (such as a macro or function call). +.br + - Some macros that tinker with the syntax of the function header. +.sp +The --varargs switch is obsolete, and is recognized only for +backwards compatibility. The present version of +.I ansi2knr +will always attempt to convert a ... argument to va_alist and va_dcl. +.SH AUTHOR +L. Peter Deutsch wrote the original ansi2knr and +continues to maintain the current version; most of the code in the current +version is his work. ansi2knr also includes contributions by Francois +Pinard and Jim Avera . diff --git a/lc-continuity/mk4/modimage/jpeg-6b/ansi2knr.c b/lc-continuity/mk4/modimage/jpeg-6b/ansi2knr.c new file mode 100644 index 0000000000000000000000000000000000000000..4e05fc2d321aff643f0885bb12b1a7a3eb16608b --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/ansi2knr.c @@ -0,0 +1,693 @@ +/* ansi2knr.c */ +/* Convert ANSI C function definitions to K&R ("traditional C") syntax */ + +/* +ansi2knr is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY. No author or distributor accepts responsibility to anyone for the +consequences of using it or for whether it serves any particular purpose or +works at all, unless he says so in writing. Refer to the GNU General Public +License (the "GPL") for full details. + +Everyone is granted permission to copy, modify and redistribute ansi2knr, +but only under the conditions described in the GPL. A copy of this license +is supposed to have been given to you along with ansi2knr so you can know +your rights and responsibilities. It should be in a file named COPYLEFT. +[In the IJG distribution, the GPL appears below, not in a separate file.] +Among other things, the copyright notice and this notice must be preserved +on all copies. + +We explicitly state here what we believe is already implied by the GPL: if +the ansi2knr program is distributed as a separate set of sources and a +separate executable file which are aggregated on a storage medium together +with another program, this in itself does not bring the other program under +the GPL, nor does the mere fact that such a program or the procedures for +constructing it invoke the ansi2knr executable bring any other part of the +program under the GPL. +*/ + +/* +---------- Here is the GNU GPL file COPYLEFT, referred to above ---------- +----- These terms do NOT apply to the JPEG software itself; see README ------ + + GHOSTSCRIPT GENERAL PUBLIC LICENSE + (Clarified 11 Feb 1988) + + Copyright (C) 1988 Richard M. Stallman + Everyone is permitted to copy and distribute verbatim copies of this + license, but changing it is not allowed. You can also use this wording + to make the terms for other programs. + + The license agreements of most software companies keep you at the +mercy of those companies. By contrast, our general public license is +intended to give everyone the right to share Ghostscript. To make sure +that you get the rights we want you to have, we need to make +restrictions that forbid anyone to deny you these rights or to ask you +to surrender the rights. Hence this license agreement. + + Specifically, we want to make sure that you have the right to give +away copies of Ghostscript, that you receive source code or else can get +it if you want it, that you can change Ghostscript or use pieces of it +in new free programs, and that you know you can do these things. + + To make sure that everyone has such rights, we have to forbid you to +deprive anyone else of these rights. For example, if you distribute +copies of Ghostscript, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must tell them their rights. + + Also, for our own protection, we must make certain that everyone finds +out that there is no warranty for Ghostscript. If Ghostscript is +modified by someone else and passed on, we want its recipients to know +that what they have is not what we distributed, so that any problems +introduced by others will not reflect on our reputation. + + Therefore we (Richard M. Stallman and the Free Software Foundation, +Inc.) make the following terms which say what you must do to be allowed +to distribute or change Ghostscript. + + + COPYING POLICIES + + 1. You may copy and distribute verbatim copies of Ghostscript source +code as you receive it, in any medium, provided that you conspicuously +and appropriately publish on each copy a valid copyright and license +notice "Copyright (C) 1989 Aladdin Enterprises. All rights reserved. +Distributed by Free Software Foundation, Inc." (or with whatever year is +appropriate); keep intact the notices on all files that refer to this +License Agreement and to the absence of any warranty; and give any other +recipients of the Ghostscript program a copy of this License Agreement +along with the program. You may charge a distribution fee for the +physical act of transferring a copy. + + 2. You may modify your copy or copies of Ghostscript or any portion of +it, and copy and distribute such modifications under the terms of +Paragraph 1 above, provided that you also do the following: + + a) cause the modified files to carry prominent notices stating + that you changed the files and the date of any change; and + + b) cause the whole of any work that you distribute or publish, + that in whole or in part contains or is a derivative of Ghostscript + or any part thereof, to be licensed at no charge to all third + parties on terms identical to those contained in this License + Agreement (except that you may choose to grant more extensive + warranty protection to some or all third parties, at your option). + + c) You may charge a distribution fee for the physical act of + transferring a copy, and you may at your option offer warranty + protection in exchange for a fee. + +Mere aggregation of another unrelated program with this program (or its +derivative) on a volume of a storage or distribution medium does not bring +the other program under the scope of these terms. + + 3. You may copy and distribute Ghostscript (or a portion or derivative +of it, under Paragraph 2) in object code or executable form under the +terms of Paragraphs 1 and 2 above provided that you also do one of the +following: + + a) accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of + Paragraphs 1 and 2 above; or, + + b) accompany it with a written offer, valid for at least three + years, to give any third party free (except for a nominal + shipping charge) a complete machine-readable copy of the + corresponding source code, to be distributed under the terms of + Paragraphs 1 and 2 above; or, + + c) accompany it with the information you received as to where the + corresponding source code may be obtained. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form alone.) + +For an executable file, complete source code means all the source code for +all modules it contains; but, as a special exception, it need not include +source code for modules which are standard libraries that accompany the +operating system on which the executable file runs. + + 4. You may not copy, sublicense, distribute or transfer Ghostscript +except as expressly provided under this License Agreement. Any attempt +otherwise to copy, sublicense, distribute or transfer Ghostscript is +void and your rights to use the program under this License agreement +shall be automatically terminated. However, parties who have received +computer software programs from you with this License Agreement will not +have their licenses terminated so long as such parties remain in full +compliance. + + 5. If you wish to incorporate parts of Ghostscript into other free +programs whose distribution conditions are different, write to the Free +Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not +yet worked out a simple rule that can be stated here, but we will often +permit this. We will be guided by the two goals of preserving the free +status of all derivatives of our free software and of promoting the +sharing and reuse of software. + +Your comments and suggestions about our licensing policies and our +software are welcome! Please contact the Free Software Foundation, +Inc., 675 Mass Ave, Cambridge, MA 02139, or call (617) 876-3296. + + NO WARRANTY + + BECAUSE GHOSTSCRIPT IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY +NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT +WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC, RICHARD +M. STALLMAN, ALADDIN ENTERPRISES, L. PETER DEUTSCH, AND/OR OTHER PARTIES +PROVIDE GHOSTSCRIPT "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER +EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE +ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF GHOSTSCRIPT IS WITH +YOU. SHOULD GHOSTSCRIPT PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL +NECESSARY SERVICING, REPAIR OR CORRECTION. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M. +STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., L. PETER DEUTSCH, ALADDIN +ENTERPRISES, AND/OR ANY OTHER PARTY WHO MAY MODIFY AND REDISTRIBUTE +GHOSTSCRIPT AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING +ANY LOST PROFITS, LOST MONIES, OR OTHER SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE +(INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED +INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A FAILURE OF THE +PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) GHOSTSCRIPT, EVEN IF YOU +HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR ANY CLAIM +BY ANY OTHER PARTY. + +-------------------- End of file COPYLEFT ------------------------------ +*/ + +/* + * Usage: + ansi2knr input_file [output_file] + * If no output_file is supplied, output goes to stdout. + * There are no error messages. + * + * ansi2knr recognizes function definitions by seeing a non-keyword + * identifier at the left margin, followed by a left parenthesis, + * with a right parenthesis as the last character on the line, + * and with a left brace as the first token on the following line + * (ignoring possible intervening comments). + * It will recognize a multi-line header provided that no intervening + * line ends with a left or right brace or a semicolon. + * These algorithms ignore whitespace and comments, except that + * the function name must be the first thing on the line. + * The following constructs will confuse it: + * - Any other construct that starts at the left margin and + * follows the above syntax (such as a macro or function call). + * - Some macros that tinker with the syntax of the function header. + */ + +/* + * The original and principal author of ansi2knr is L. Peter Deutsch + * . Other authors are noted in the change history + * that follows (in reverse chronological order): + lpd 96-01-21 added code to cope with not HAVE_CONFIG_H and with + compilers that don't understand void, as suggested by + Tom Lane + lpd 96-01-15 changed to require that the first non-comment token + on the line following a function header be a left brace, + to reduce sensitivity to macros, as suggested by Tom Lane + + lpd 95-06-22 removed #ifndefs whose sole purpose was to define + undefined preprocessor symbols as 0; changed all #ifdefs + for configuration symbols to #ifs + lpd 95-04-05 changed copyright notice to make it clear that + including ansi2knr in a program does not bring the entire + program under the GPL + lpd 94-12-18 added conditionals for systems where ctype macros + don't handle 8-bit characters properly, suggested by + Francois Pinard ; + removed --varargs switch (this is now the default) + lpd 94-10-10 removed CONFIG_BROKETS conditional + lpd 94-07-16 added some conditionals to help GNU `configure', + suggested by Francois Pinard ; + properly erase prototype args in function parameters, + contributed by Jim Avera ; + correct error in writeblanks (it shouldn't erase EOLs) + lpd 89-xx-xx original version + */ + +/* Most of the conditionals here are to make ansi2knr work with */ +/* or without the GNU configure machinery. */ + +#if HAVE_CONFIG_H +# include +#endif + +#include +#include + +#if HAVE_CONFIG_H + +/* + For properly autoconfiguring ansi2knr, use AC_CONFIG_HEADER(config.h). + This will define HAVE_CONFIG_H and so, activate the following lines. + */ + +# if STDC_HEADERS || HAVE_STRING_H +# include +# else +# include +# endif + +#else /* not HAVE_CONFIG_H */ + +/* Otherwise do it the hard way */ + +# ifdef BSD +# include +# else +# ifdef VMS + extern int strlen(), strncmp(); +# else +# include +# endif +# endif + +#endif /* not HAVE_CONFIG_H */ + +#if STDC_HEADERS +# include +#else +/* + malloc and free should be declared in stdlib.h, + but if you've got a K&R compiler, they probably aren't. + */ +# ifdef MSDOS +# include +# else +# ifdef VMS + extern char *malloc(); + extern void free(); +# else + extern char *malloc(); + extern int free(); +# endif +# endif + +#endif + +/* + * The ctype macros don't always handle 8-bit characters correctly. + * Compensate for this here. + */ +#ifdef isascii +# undef HAVE_ISASCII /* just in case */ +# define HAVE_ISASCII 1 +#else +#endif +#if STDC_HEADERS || !HAVE_ISASCII +# define is_ascii(c) 1 +#else +# define is_ascii(c) isascii(c) +#endif + +#define is_space(c) (is_ascii(c) && isspace(c)) +#define is_alpha(c) (is_ascii(c) && isalpha(c)) +#define is_alnum(c) (is_ascii(c) && isalnum(c)) + +/* Scanning macros */ +#define isidchar(ch) (is_alnum(ch) || (ch) == '_') +#define isidfirstchar(ch) (is_alpha(ch) || (ch) == '_') + +/* Forward references */ +char *skipspace(); +int writeblanks(); +int test1(); +int convert1(); + +/* The main program */ +int +main(argc, argv) + int argc; + char *argv[]; +{ FILE *in, *out; +#define bufsize 5000 /* arbitrary size */ + char *buf; + char *line; + char *more; + /* + * In previous versions, ansi2knr recognized a --varargs switch. + * If this switch was supplied, ansi2knr would attempt to convert + * a ... argument to va_alist and va_dcl; if this switch was not + * supplied, ansi2knr would simply drop any such arguments. + * Now, ansi2knr always does this conversion, and we only + * check for this switch for backward compatibility. + */ + int convert_varargs = 1; + + if ( argc > 1 && argv[1][0] == '-' ) + { if ( !strcmp(argv[1], "--varargs") ) + { convert_varargs = 1; + argc--; + argv++; + } + else + { fprintf(stderr, "Unrecognized switch: %s\n", argv[1]); + exit(1); + } + } + switch ( argc ) + { + default: + printf("Usage: ansi2knr input_file [output_file]\n"); + exit(0); + case 2: + out = stdout; + break; + case 3: + out = fopen(argv[2], "w"); + if ( out == NULL ) + { fprintf(stderr, "Cannot open output file %s\n", argv[2]); + exit(1); + } + } + in = fopen(argv[1], "r"); + if ( in == NULL ) + { fprintf(stderr, "Cannot open input file %s\n", argv[1]); + exit(1); + } + fprintf(out, "#line 1 \"%s\"\n", argv[1]); + buf = malloc(bufsize); + line = buf; + while ( fgets(line, (unsigned)(buf + bufsize - line), in) != NULL ) + { +test: line += strlen(line); + switch ( test1(buf) ) + { + case 2: /* a function header */ + convert1(buf, out, 1, convert_varargs); + break; + case 1: /* a function */ + /* Check for a { at the start of the next line. */ + more = ++line; +f: if ( line >= buf + (bufsize - 1) ) /* overflow check */ + goto wl; + if ( fgets(line, (unsigned)(buf + bufsize - line), in) == NULL ) + goto wl; + switch ( *skipspace(more, 1) ) + { + case '{': + /* Definitely a function header. */ + convert1(buf, out, 0, convert_varargs); + fputs(more, out); + break; + case 0: + /* The next line was blank or a comment: */ + /* keep scanning for a non-comment. */ + line += strlen(line); + goto f; + default: + /* buf isn't a function header, but */ + /* more might be. */ + fputs(buf, out); + strcpy(buf, more); + line = buf; + goto test; + } + break; + case -1: /* maybe the start of a function */ + if ( line != buf + (bufsize - 1) ) /* overflow check */ + continue; + /* falls through */ + default: /* not a function */ +wl: fputs(buf, out); + break; + } + line = buf; + } + if ( line != buf ) + fputs(buf, out); + free(buf); + fclose(out); + fclose(in); + return 0; +} + +/* Skip over space and comments, in either direction. */ +char * +skipspace(p, dir) + register char *p; + register int dir; /* 1 for forward, -1 for backward */ +{ for ( ; ; ) + { while ( is_space(*p) ) + p += dir; + if ( !(*p == '/' && p[dir] == '*') ) + break; + p += dir; p += dir; + while ( !(*p == '*' && p[dir] == '/') ) + { if ( *p == 0 ) + return p; /* multi-line comment?? */ + p += dir; + } + p += dir; p += dir; + } + return p; +} + +/* + * Write blanks over part of a string. + * Don't overwrite end-of-line characters. + */ +int +writeblanks(start, end) + char *start; + char *end; +{ char *p; + for ( p = start; p < end; p++ ) + if ( *p != '\r' && *p != '\n' ) + *p = ' '; + return 0; +} + +/* + * Test whether the string in buf is a function definition. + * The string may contain and/or end with a newline. + * Return as follows: + * 0 - definitely not a function definition; + * 1 - definitely a function definition; + * 2 - definitely a function prototype (NOT USED); + * -1 - may be the beginning of a function definition, + * append another line and look again. + * The reason we don't attempt to convert function prototypes is that + * Ghostscript's declaration-generating macros look too much like + * prototypes, and confuse the algorithms. + */ +int +test1(buf) + char *buf; +{ register char *p = buf; + char *bend; + char *endfn; + int contin; + + if ( !isidfirstchar(*p) ) + return 0; /* no name at left margin */ + bend = skipspace(buf + strlen(buf) - 1, -1); + switch ( *bend ) + { + case ';': contin = 0 /*2*/; break; + case ')': contin = 1; break; + case '{': return 0; /* not a function */ + case '}': return 0; /* not a function */ + default: contin = -1; + } + while ( isidchar(*p) ) + p++; + endfn = p; + p = skipspace(p, 1); + if ( *p++ != '(' ) + return 0; /* not a function */ + p = skipspace(p, 1); + if ( *p == ')' ) + return 0; /* no parameters */ + /* Check that the apparent function name isn't a keyword. */ + /* We only need to check for keywords that could be followed */ + /* by a left parenthesis (which, unfortunately, is most of them). */ + { static char *words[] = + { "asm", "auto", "case", "char", "const", "double", + "extern", "float", "for", "if", "int", "long", + "register", "return", "short", "signed", "sizeof", + "static", "switch", "typedef", "unsigned", + "void", "volatile", "while", 0 + }; + char **key = words; + char *kp; + int len = endfn - buf; + + while ( (kp = *key) != 0 ) + { if ( strlen(kp) == len && !strncmp(kp, buf, len) ) + return 0; /* name is a keyword */ + key++; + } + } + return contin; +} + +/* Convert a recognized function definition or header to K&R syntax. */ +int +convert1(buf, out, header, convert_varargs) + char *buf; + FILE *out; + int header; /* Boolean */ + int convert_varargs; /* Boolean */ +{ char *endfn; + register char *p; + char **breaks; + unsigned num_breaks = 2; /* for testing */ + char **btop; + char **bp; + char **ap; + char *vararg = 0; + + /* Pre-ANSI implementations don't agree on whether strchr */ + /* is called strchr or index, so we open-code it here. */ + for ( endfn = buf; *(endfn++) != '('; ) + ; +top: p = endfn; + breaks = (char **)malloc(sizeof(char *) * num_breaks * 2); + if ( breaks == 0 ) + { /* Couldn't allocate break table, give up */ + fprintf(stderr, "Unable to allocate break table!\n"); + fputs(buf, out); + return -1; + } + btop = breaks + num_breaks * 2 - 2; + bp = breaks; + /* Parse the argument list */ + do + { int level = 0; + char *lp = NULL; + char *rp; + char *end = NULL; + + if ( bp >= btop ) + { /* Filled up break table. */ + /* Allocate a bigger one and start over. */ + free((char *)breaks); + num_breaks <<= 1; + goto top; + } + *bp++ = p; + /* Find the end of the argument */ + for ( ; end == NULL; p++ ) + { switch(*p) + { + case ',': + if ( !level ) end = p; + break; + case '(': + if ( !level ) lp = p; + level++; + break; + case ')': + if ( --level < 0 ) end = p; + else rp = p; + break; + case '/': + p = skipspace(p, 1) - 1; + break; + default: + ; + } + } + /* Erase any embedded prototype parameters. */ + if ( lp ) + writeblanks(lp + 1, rp); + p--; /* back up over terminator */ + /* Find the name being declared. */ + /* This is complicated because of procedure and */ + /* array modifiers. */ + for ( ; ; ) + { p = skipspace(p - 1, -1); + switch ( *p ) + { + case ']': /* skip array dimension(s) */ + case ')': /* skip procedure args OR name */ + { int level = 1; + while ( level ) + switch ( *--p ) + { + case ']': case ')': level++; break; + case '[': case '(': level--; break; + case '/': p = skipspace(p, -1) + 1; break; + default: ; + } + } + if ( *p == '(' && *skipspace(p + 1, 1) == '*' ) + { /* We found the name being declared */ + while ( !isidfirstchar(*p) ) + p = skipspace(p, 1) + 1; + goto found; + } + break; + default: + goto found; + } + } +found: if ( *p == '.' && p[-1] == '.' && p[-2] == '.' ) + { if ( convert_varargs ) + { *bp++ = "va_alist"; + vararg = p-2; + } + else + { p++; + if ( bp == breaks + 1 ) /* sole argument */ + writeblanks(breaks[0], p); + else + writeblanks(bp[-1] - 1, p); + bp--; + } + } + else + { while ( isidchar(*p) ) p--; + *bp++ = p+1; + } + p = end; + } + while ( *p++ == ',' ); + *bp = p; + /* Make a special check for 'void' arglist */ + if ( bp == breaks+2 ) + { p = skipspace(breaks[0], 1); + if ( !strncmp(p, "void", 4) ) + { p = skipspace(p+4, 1); + if ( p == breaks[2] - 1 ) + { bp = breaks; /* yup, pretend arglist is empty */ + writeblanks(breaks[0], p + 1); + } + } + } + /* Put out the function name and left parenthesis. */ + p = buf; + while ( p != endfn ) putc(*p, out), p++; + /* Put out the declaration. */ + if ( header ) + { fputs(");", out); + for ( p = breaks[0]; *p; p++ ) + if ( *p == '\r' || *p == '\n' ) + putc(*p, out); + } + else + { for ( ap = breaks+1; ap < bp; ap += 2 ) + { p = *ap; + while ( isidchar(*p) ) + putc(*p, out), p++; + if ( ap < bp - 1 ) + fputs(", ", out); + } + fputs(") ", out); + /* Put out the argument declarations */ + for ( ap = breaks+2; ap <= bp; ap += 2 ) + (*ap)[-1] = ';'; + if ( vararg != 0 ) + { *vararg = 0; + fputs(breaks[0], out); /* any prior args */ + fputs("va_dcl", out); /* the final arg */ + fputs(bp[0], out); + } + else + fputs(breaks[0], out); + } + free((char *)breaks); + return 0; +} diff --git a/lc-continuity/mk4/modimage/jpeg-6b/cderror.h b/lc-continuity/mk4/modimage/jpeg-6b/cderror.h new file mode 100644 index 0000000000000000000000000000000000000000..70435e161c01773d458bb0d00af4446a9158d58a --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/cderror.h @@ -0,0 +1,132 @@ +/* + * cderror.h + * + * Copyright (C) 1994-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file defines the error and message codes for the cjpeg/djpeg + * applications. These strings are not needed as part of the JPEG library + * proper. + * Edit this file to add new codes, or to translate the message strings to + * some other language. + */ + +/* + * To define the enum list of message codes, include this file without + * defining macro JMESSAGE. To create a message string table, include it + * again with a suitable JMESSAGE definition (see jerror.c for an example). + */ +#ifndef JMESSAGE +#ifndef CDERROR_H +#define CDERROR_H +/* First time through, define the enum list */ +#define JMAKE_ENUM_LIST +#else +/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */ +#define JMESSAGE(code,string) +#endif /* CDERROR_H */ +#endif /* JMESSAGE */ + +#ifdef JMAKE_ENUM_LIST + +typedef enum { + +#define JMESSAGE(code,string) code , + +#endif /* JMAKE_ENUM_LIST */ + +JMESSAGE(JMSG_FIRSTADDONCODE=1000, NULL) /* Must be first entry! */ + +#ifdef BMP_SUPPORTED +JMESSAGE(JERR_BMP_BADCMAP, "Unsupported BMP colormap format") +JMESSAGE(JERR_BMP_BADDEPTH, "Only 8- and 24-bit BMP files are supported") +JMESSAGE(JERR_BMP_BADHEADER, "Invalid BMP file: bad header length") +JMESSAGE(JERR_BMP_BADPLANES, "Invalid BMP file: biPlanes not equal to 1") +JMESSAGE(JERR_BMP_COLORSPACE, "BMP output must be grayscale or RGB") +JMESSAGE(JERR_BMP_COMPRESSED, "Sorry, compressed BMPs not yet supported") +JMESSAGE(JERR_BMP_NOT, "Not a BMP file - does not start with BM") +JMESSAGE(JTRC_BMP, "%ux%u 24-bit BMP image") +JMESSAGE(JTRC_BMP_MAPPED, "%ux%u 8-bit colormapped BMP image") +JMESSAGE(JTRC_BMP_OS2, "%ux%u 24-bit OS2 BMP image") +JMESSAGE(JTRC_BMP_OS2_MAPPED, "%ux%u 8-bit colormapped OS2 BMP image") +#endif /* BMP_SUPPORTED */ + +#ifdef GIF_SUPPORTED +JMESSAGE(JERR_GIF_BUG, "GIF output got confused") +JMESSAGE(JERR_GIF_CODESIZE, "Bogus GIF codesize %d") +JMESSAGE(JERR_GIF_COLORSPACE, "GIF output must be grayscale or RGB") +JMESSAGE(JERR_GIF_IMAGENOTFOUND, "Too few images in GIF file") +JMESSAGE(JERR_GIF_NOT, "Not a GIF file") +JMESSAGE(JTRC_GIF, "%ux%ux%d GIF image") +JMESSAGE(JTRC_GIF_BADVERSION, + "Warning: unexpected GIF version number '%c%c%c'") +JMESSAGE(JTRC_GIF_EXTENSION, "Ignoring GIF extension block of type 0x%02x") +JMESSAGE(JTRC_GIF_NONSQUARE, "Caution: nonsquare pixels in input") +JMESSAGE(JWRN_GIF_BADDATA, "Corrupt data in GIF file") +JMESSAGE(JWRN_GIF_CHAR, "Bogus char 0x%02x in GIF file, ignoring") +JMESSAGE(JWRN_GIF_ENDCODE, "Premature end of GIF image") +JMESSAGE(JWRN_GIF_NOMOREDATA, "Ran out of GIF bits") +#endif /* GIF_SUPPORTED */ + +#ifdef PPM_SUPPORTED +JMESSAGE(JERR_PPM_COLORSPACE, "PPM output must be grayscale or RGB") +JMESSAGE(JERR_PPM_NONNUMERIC, "Nonnumeric data in PPM file") +JMESSAGE(JERR_PPM_NOT, "Not a PPM/PGM file") +JMESSAGE(JTRC_PGM, "%ux%u PGM image") +JMESSAGE(JTRC_PGM_TEXT, "%ux%u text PGM image") +JMESSAGE(JTRC_PPM, "%ux%u PPM image") +JMESSAGE(JTRC_PPM_TEXT, "%ux%u text PPM image") +#endif /* PPM_SUPPORTED */ + +#ifdef RLE_SUPPORTED +JMESSAGE(JERR_RLE_BADERROR, "Bogus error code from RLE library") +JMESSAGE(JERR_RLE_COLORSPACE, "RLE output must be grayscale or RGB") +JMESSAGE(JERR_RLE_DIMENSIONS, "Image dimensions (%ux%u) too large for RLE") +JMESSAGE(JERR_RLE_EMPTY, "Empty RLE file") +JMESSAGE(JERR_RLE_EOF, "Premature EOF in RLE header") +JMESSAGE(JERR_RLE_MEM, "Insufficient memory for RLE header") +JMESSAGE(JERR_RLE_NOT, "Not an RLE file") +JMESSAGE(JERR_RLE_TOOMANYCHANNELS, "Cannot handle %d output channels for RLE") +JMESSAGE(JERR_RLE_UNSUPPORTED, "Cannot handle this RLE setup") +JMESSAGE(JTRC_RLE, "%ux%u full-color RLE file") +JMESSAGE(JTRC_RLE_FULLMAP, "%ux%u full-color RLE file with map of length %d") +JMESSAGE(JTRC_RLE_GRAY, "%ux%u grayscale RLE file") +JMESSAGE(JTRC_RLE_MAPGRAY, "%ux%u grayscale RLE file with map of length %d") +JMESSAGE(JTRC_RLE_MAPPED, "%ux%u colormapped RLE file with map of length %d") +#endif /* RLE_SUPPORTED */ + +#ifdef TARGA_SUPPORTED +JMESSAGE(JERR_TGA_BADCMAP, "Unsupported Targa colormap format") +JMESSAGE(JERR_TGA_BADPARMS, "Invalid or unsupported Targa file") +JMESSAGE(JERR_TGA_COLORSPACE, "Targa output must be grayscale or RGB") +JMESSAGE(JTRC_TGA, "%ux%u RGB Targa image") +JMESSAGE(JTRC_TGA_GRAY, "%ux%u grayscale Targa image") +JMESSAGE(JTRC_TGA_MAPPED, "%ux%u colormapped Targa image") +#else +JMESSAGE(JERR_TGA_NOTCOMP, "Targa support was not compiled") +#endif /* TARGA_SUPPORTED */ + +JMESSAGE(JERR_BAD_CMAP_FILE, + "Color map file is invalid or of unsupported format") +JMESSAGE(JERR_TOO_MANY_COLORS, + "Output file format cannot handle %d colormap entries") +JMESSAGE(JERR_UNGETC_FAILED, "ungetc failed") +#ifdef TARGA_SUPPORTED +JMESSAGE(JERR_UNKNOWN_FORMAT, + "Unrecognized input file format --- perhaps you need -targa") +#else +JMESSAGE(JERR_UNKNOWN_FORMAT, "Unrecognized input file format") +#endif +JMESSAGE(JERR_UNSUPPORTED_FORMAT, "Unsupported output file format") + +#ifdef JMAKE_ENUM_LIST + + JMSG_LASTADDONCODE +} ADDON_MESSAGE_CODE; + +#undef JMAKE_ENUM_LIST +#endif /* JMAKE_ENUM_LIST */ + +/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */ +#undef JMESSAGE diff --git a/lc-continuity/mk4/modimage/jpeg-6b/cdjpeg.c b/lc-continuity/mk4/modimage/jpeg-6b/cdjpeg.c new file mode 100644 index 0000000000000000000000000000000000000000..b6250ff97cba735082d46c5706b9a90595af2319 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/cdjpeg.c @@ -0,0 +1,181 @@ +/* + * cdjpeg.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains common support routines used by the IJG application + * programs (cjpeg, djpeg, jpegtran). + */ + +#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ +#include /* to declare isupper(), tolower() */ +#ifdef NEED_SIGNAL_CATCHER +#include /* to declare signal() */ +#endif +#ifdef USE_SETMODE +#include /* to declare setmode()'s parameter macros */ +/* If you have setmode() but not , just delete this line: */ +#include /* to declare setmode() */ +#endif + + +/* + * Signal catcher to ensure that temporary files are removed before aborting. + * NB: for Amiga Manx C this is actually a global routine named _abort(); + * we put "#define signal_catcher _abort" in jconfig.h. Talk about bogus... + */ + +#ifdef NEED_SIGNAL_CATCHER + +static j_common_ptr sig_cinfo; + +void /* must be global for Manx C */ +signal_catcher (int signum) +{ + if (sig_cinfo != NULL) { + if (sig_cinfo->err != NULL) /* turn off trace output */ + sig_cinfo->err->trace_level = 0; + jpeg_destroy(sig_cinfo); /* clean up memory allocation & temp files */ + } + exit(EXIT_FAILURE); +} + + +GLOBAL(void) +enable_signal_catcher (j_common_ptr cinfo) +{ + sig_cinfo = cinfo; +#ifdef SIGINT /* not all systems have SIGINT */ + signal(SIGINT, signal_catcher); +#endif +#ifdef SIGTERM /* not all systems have SIGTERM */ + signal(SIGTERM, signal_catcher); +#endif +} + +#endif + + +/* + * Optional progress monitor: display a percent-done figure on stderr. + */ + +#ifdef PROGRESS_REPORT + +METHODDEF(void) +progress_monitor (j_common_ptr cinfo) +{ + cd_progress_ptr prog = (cd_progress_ptr) cinfo->progress; + int total_passes = prog->pub.total_passes + prog->total_extra_passes; + int percent_done = (int) (prog->pub.pass_counter*100L/prog->pub.pass_limit); + + if (percent_done != prog->percent_done) { + prog->percent_done = percent_done; + if (total_passes > 1) { + fprintf(stderr, "\rPass %d/%d: %3d%% ", + prog->pub.completed_passes + prog->completed_extra_passes + 1, + total_passes, percent_done); + } else { + fprintf(stderr, "\r %3d%% ", percent_done); + } + fflush(stderr); + } +} + + +GLOBAL(void) +start_progress_monitor (j_common_ptr cinfo, cd_progress_ptr progress) +{ + /* Enable progress display, unless trace output is on */ + if (cinfo->err->trace_level == 0) { + progress->pub.progress_monitor = progress_monitor; + progress->completed_extra_passes = 0; + progress->total_extra_passes = 0; + progress->percent_done = -1; + cinfo->progress = &progress->pub; + } +} + + +GLOBAL(void) +end_progress_monitor (j_common_ptr cinfo) +{ + /* Clear away progress display */ + if (cinfo->err->trace_level == 0) { + fprintf(stderr, "\r \r"); + fflush(stderr); + } +} + +#endif + + +/* + * Case-insensitive matching of possibly-abbreviated keyword switches. + * keyword is the constant keyword (must be lower case already), + * minchars is length of minimum legal abbreviation. + */ + +GLOBAL(boolean) +keymatch (char * arg, const char * keyword, int minchars) +{ + register int ca, ck; + register int nmatched = 0; + + while ((ca = *arg++) != '\0') { + if ((ck = *keyword++) == '\0') + return FALSE; /* arg longer than keyword, no good */ + if (isupper(ca)) /* force arg to lcase (assume ck is already) */ + ca = tolower(ca); + if (ca != ck) + return FALSE; /* no good */ + nmatched++; /* count matched characters */ + } + /* reached end of argument; fail if it's too short for unique abbrev */ + if (nmatched < minchars) + return FALSE; + return TRUE; /* A-OK */ +} + + +/* + * Routines to establish binary I/O mode for stdin and stdout. + * Non-Unix systems often require some hacking to get out of text mode. + */ + +GLOBAL(FILE *) +read_stdin (void) +{ + FILE * input_file = stdin; + +#ifdef USE_SETMODE /* need to hack file mode? */ + setmode(fileno(stdin), O_BINARY); +#endif +#ifdef USE_FDOPEN /* need to re-open in binary mode? */ + if ((input_file = fdopen(fileno(stdin), READ_BINARY)) == NULL) { + fprintf(stderr, "Cannot reopen stdin\n"); + exit(EXIT_FAILURE); + } +#endif + return input_file; +} + + +GLOBAL(FILE *) +write_stdout (void) +{ + FILE * output_file = stdout; + +#ifdef USE_SETMODE /* need to hack file mode? */ + setmode(fileno(stdout), O_BINARY); +#endif +#ifdef USE_FDOPEN /* need to re-open in binary mode? */ + if ((output_file = fdopen(fileno(stdout), WRITE_BINARY)) == NULL) { + fprintf(stderr, "Cannot reopen stdout\n"); + exit(EXIT_FAILURE); + } +#endif + return output_file; +} diff --git a/lc-continuity/mk4/modimage/jpeg-6b/cdjpeg.h b/lc-continuity/mk4/modimage/jpeg-6b/cdjpeg.h new file mode 100644 index 0000000000000000000000000000000000000000..2b387b6e5fa7eea99f03d3ce32248c7fe6d9b993 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/cdjpeg.h @@ -0,0 +1,184 @@ +/* + * cdjpeg.h + * + * Copyright (C) 1994-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains common declarations for the sample applications + * cjpeg and djpeg. It is NOT used by the core JPEG library. + */ + +#define JPEG_CJPEG_DJPEG /* define proper options in jconfig.h */ +#define JPEG_INTERNAL_OPTIONS /* cjpeg.c,djpeg.c need to see xxx_SUPPORTED */ +#include "jinclude.h" +#include "jpeglib.h" +#include "jerror.h" /* get library error codes too */ +#include "cderror.h" /* get application-specific error codes */ + + +/* + * Object interface for cjpeg's source file decoding modules + */ + +typedef struct cjpeg_source_struct * cjpeg_source_ptr; + +struct cjpeg_source_struct { + JMETHOD(void, start_input, (j_compress_ptr cinfo, + cjpeg_source_ptr sinfo)); + JMETHOD(JDIMENSION, get_pixel_rows, (j_compress_ptr cinfo, + cjpeg_source_ptr sinfo)); + JMETHOD(void, finish_input, (j_compress_ptr cinfo, + cjpeg_source_ptr sinfo)); + + FILE *input_file; + + JSAMPARRAY buffer; + JDIMENSION buffer_height; +}; + + +/* + * Object interface for djpeg's output file encoding modules + */ + +typedef struct djpeg_dest_struct * djpeg_dest_ptr; + +struct djpeg_dest_struct { + /* start_output is called after jpeg_start_decompress finishes. + * The color map will be ready at this time, if one is needed. + */ + JMETHOD(void, start_output, (j_decompress_ptr cinfo, + djpeg_dest_ptr dinfo)); + /* Emit the specified number of pixel rows from the buffer. */ + JMETHOD(void, put_pixel_rows, (j_decompress_ptr cinfo, + djpeg_dest_ptr dinfo, + JDIMENSION rows_supplied)); + /* Finish up at the end of the image. */ + JMETHOD(void, finish_output, (j_decompress_ptr cinfo, + djpeg_dest_ptr dinfo)); + + /* Target file spec; filled in by djpeg.c after object is created. */ + FILE * output_file; + + /* Output pixel-row buffer. Created by module init or start_output. + * Width is cinfo->output_width * cinfo->output_components; + * height is buffer_height. + */ + JSAMPARRAY buffer; + JDIMENSION buffer_height; +}; + + +/* + * cjpeg/djpeg may need to perform extra passes to convert to or from + * the source/destination file format. The JPEG library does not know + * about these passes, but we'd like them to be counted by the progress + * monitor. We use an expanded progress monitor object to hold the + * additional pass count. + */ + +struct cdjpeg_progress_mgr { + struct jpeg_progress_mgr pub; /* fields known to JPEG library */ + int completed_extra_passes; /* extra passes completed */ + int total_extra_passes; /* total extra */ + /* last printed percentage stored here to avoid multiple printouts */ + int percent_done; +}; + +typedef struct cdjpeg_progress_mgr * cd_progress_ptr; + + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jinit_read_bmp jIRdBMP +#define jinit_write_bmp jIWrBMP +#define jinit_read_gif jIRdGIF +#define jinit_write_gif jIWrGIF +#define jinit_read_ppm jIRdPPM +#define jinit_write_ppm jIWrPPM +#define jinit_read_rle jIRdRLE +#define jinit_write_rle jIWrRLE +#define jinit_read_targa jIRdTarga +#define jinit_write_targa jIWrTarga +#define read_quant_tables RdQTables +#define read_scan_script RdScnScript +#define set_quant_slots SetQSlots +#define set_sample_factors SetSFacts +#define read_color_map RdCMap +#define enable_signal_catcher EnSigCatcher +#define start_progress_monitor StProgMon +#define end_progress_monitor EnProgMon +#define read_stdin RdStdin +#define write_stdout WrStdout +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + +/* Module selection routines for I/O modules. */ + +EXTERN(cjpeg_source_ptr) jinit_read_bmp JPP((j_compress_ptr cinfo)); +EXTERN(djpeg_dest_ptr) jinit_write_bmp JPP((j_decompress_ptr cinfo, + boolean is_os2)); +EXTERN(cjpeg_source_ptr) jinit_read_gif JPP((j_compress_ptr cinfo)); +EXTERN(djpeg_dest_ptr) jinit_write_gif JPP((j_decompress_ptr cinfo)); +EXTERN(cjpeg_source_ptr) jinit_read_ppm JPP((j_compress_ptr cinfo)); +EXTERN(djpeg_dest_ptr) jinit_write_ppm JPP((j_decompress_ptr cinfo)); +EXTERN(cjpeg_source_ptr) jinit_read_rle JPP((j_compress_ptr cinfo)); +EXTERN(djpeg_dest_ptr) jinit_write_rle JPP((j_decompress_ptr cinfo)); +EXTERN(cjpeg_source_ptr) jinit_read_targa JPP((j_compress_ptr cinfo)); +EXTERN(djpeg_dest_ptr) jinit_write_targa JPP((j_decompress_ptr cinfo)); + +/* cjpeg support routines (in rdswitch.c) */ + +EXTERN(boolean) read_quant_tables JPP((j_compress_ptr cinfo, char * filename, + int scale_factor, boolean force_baseline)); +EXTERN(boolean) read_scan_script JPP((j_compress_ptr cinfo, char * filename)); +EXTERN(boolean) set_quant_slots JPP((j_compress_ptr cinfo, char *arg)); +EXTERN(boolean) set_sample_factors JPP((j_compress_ptr cinfo, char *arg)); + +/* djpeg support routines (in rdcolmap.c) */ + +EXTERN(void) read_color_map JPP((j_decompress_ptr cinfo, FILE * infile)); + +/* common support routines (in cdjpeg.c) */ + +EXTERN(void) enable_signal_catcher JPP((j_common_ptr cinfo)); +EXTERN(void) start_progress_monitor JPP((j_common_ptr cinfo, + cd_progress_ptr progress)); +EXTERN(void) end_progress_monitor JPP((j_common_ptr cinfo)); +EXTERN(boolean) keymatch JPP((char * arg, const char * keyword, int minchars)); +EXTERN(FILE *) read_stdin JPP((void)); +EXTERN(FILE *) write_stdout JPP((void)); + +/* miscellaneous useful macros */ + +#ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */ +#define READ_BINARY "r" +#define WRITE_BINARY "w" +#else +#ifdef VMS /* VMS is very nonstandard */ +#define READ_BINARY "rb", "ctx=stm" +#define WRITE_BINARY "wb", "ctx=stm" +#else /* standard ANSI-compliant case */ +#define READ_BINARY "rb" +#define WRITE_BINARY "wb" +#endif +#endif + +#ifndef EXIT_FAILURE /* define exit() codes if not provided */ +#define EXIT_FAILURE 1 +#endif +#ifndef EXIT_SUCCESS +#ifdef VMS +#define EXIT_SUCCESS 1 /* VMS is very nonstandard */ +#else +#define EXIT_SUCCESS 0 +#endif +#endif +#ifndef EXIT_WARNING +#ifdef VMS +#define EXIT_WARNING 1 /* VMS is very nonstandard */ +#else +#define EXIT_WARNING 2 +#endif +#endif diff --git a/lc-continuity/mk4/modimage/jpeg-6b/change.log b/lc-continuity/mk4/modimage/jpeg-6b/change.log new file mode 100644 index 0000000000000000000000000000000000000000..74102c0db5aa2bf3dae6f3f54673b1a257004aee --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/change.log @@ -0,0 +1,217 @@ +CHANGE LOG for Independent JPEG Group's JPEG software + + +Version 6b 27-Mar-1998 +----------------------- + +jpegtran has new features for lossless image transformations (rotation +and flipping) as well as "lossless" reduction to grayscale. + +jpegtran now copies comments by default; it has a -copy switch to enable +copying all APPn blocks as well, or to suppress comments. (Formerly it +always suppressed comments and APPn blocks.) jpegtran now also preserves +JFIF version and resolution information. + +New decompressor library feature: COM and APPn markers found in the input +file can be saved in memory for later use by the application. (Before, +you had to code this up yourself with a custom marker processor.) + +There is an unused field "void * client_data" now in compress and decompress +parameter structs; this may be useful in some applications. + +JFIF version number information is now saved by the decoder and accepted by +the encoder. jpegtran uses this to copy the source file's version number, +to ensure "jpegtran -copy all" won't create bogus files that contain JFXX +extensions but claim to be version 1.01. Applications that generate their +own JFXX extension markers also (finally) have a supported way to cause the +encoder to emit JFIF version number 1.02. + +djpeg's trace mode reports JFIF 1.02 thumbnail images as such, rather +than as unknown APP0 markers. + +In -verbose mode, djpeg and rdjpgcom will try to print the contents of +APP12 markers as text. Some digital cameras store useful text information +in APP12 markers. + +Handling of truncated data streams is more robust: blocks beyond the one in +which the error occurs will be output as uniform gray, or left unchanged +if decoding a progressive JPEG. The appearance no longer depends on the +Huffman tables being used. + +Huffman tables are checked for validity much more carefully than before. + +To avoid the Unisys LZW patent, djpeg's GIF output capability has been +changed to produce "uncompressed GIFs", and cjpeg's GIF input capability +has been removed altogether. We're not happy about it either, but there +seems to be no good alternative. + +The configure script now supports building libjpeg as a shared library +on many flavors of Unix (all the ones that GNU libtool knows how to +build shared libraries for). Use "./configure --enable-shared" to +try this out. + +New jconfig file and makefiles for Microsoft Visual C++ and Developer Studio. +Also, a jconfig file and a build script for Metrowerks CodeWarrior +on Apple Macintosh. makefile.dj has been updated for DJGPP v2, and there +are miscellaneous other minor improvements in the makefiles. + +jmemmac.c now knows how to create temporary files following Mac System 7 +conventions. + +djpeg's -map switch is now able to read raw-format PPM files reliably. + +cjpeg -progressive -restart no longer generates any unnecessary DRI markers. + +Multiple calls to jpeg_simple_progression for a single JPEG object +no longer leak memory. + + +Version 6a 7-Feb-96 +-------------------- + +Library initialization sequence modified to detect version mismatches +and struct field packing mismatches between library and calling application. +This change requires applications to be recompiled, but does not require +any application source code change. + +All routine declarations changed to the style "GLOBAL(type) name ...", +that is, GLOBAL, LOCAL, METHODDEF, EXTERN are now macros taking the +routine's return type as an argument. This makes it possible to add +Microsoft-style linkage keywords to all the routines by changing just +these macros. Note that any application code that was using these macros +will have to be changed. + +DCT coefficient quantization tables are now stored in normal array order +rather than zigzag order. Application code that calls jpeg_add_quant_table, +or otherwise manipulates quantization tables directly, will need to be +changed. If you need to make such code work with either older or newer +versions of the library, a test like "#if JPEG_LIB_VERSION >= 61" is +recommended. + +djpeg's trace capability now dumps DQT tables in natural order, not zigzag +order. This allows the trace output to be made into a "-qtables" file +more easily. + +New system-dependent memory manager module for use on Apple Macintosh. + +Fix bug in cjpeg's -smooth option: last one or two scanlines would be +duplicates of the prior line unless the image height mod 16 was 1 or 2. + +Repair minor problems in VMS, BCC, MC6 makefiles. + +New configure script based on latest GNU Autoconf. + +Correct the list of include files needed by MetroWerks C for ccommand(). + +Numerous small documentation updates. + + +Version 6 2-Aug-95 +------------------- + +Progressive JPEG support: library can read and write full progressive JPEG +files. A "buffered image" mode supports incremental decoding for on-the-fly +display of progressive images. Simply recompiling an existing IJG-v5-based +decoder with v6 should allow it to read progressive files, though of course +without any special progressive display. + +New "jpegtran" application performs lossless transcoding between different +JPEG formats; primarily, it can be used to convert baseline to progressive +JPEG and vice versa. In support of jpegtran, the library now allows lossless +reading and writing of JPEG files as DCT coefficient arrays. This ability +may be of use in other applications. + +Notes for programmers: +* We changed jpeg_start_decompress() to be able to suspend; this makes all +decoding modes available to suspending-input applications. However, +existing applications that use suspending input will need to be changed +to check the return value from jpeg_start_decompress(). You don't need to +do anything if you don't use a suspending data source. +* We changed the interface to the virtual array routines: access_virt_array +routines now take a count of the number of rows to access this time. The +last parameter to request_virt_array routines is now interpreted as the +maximum number of rows that may be accessed at once, but not necessarily +the height of every access. + + +Version 5b 15-Mar-95 +--------------------- + +Correct bugs with grayscale images having v_samp_factor > 1. + +jpeg_write_raw_data() now supports output suspension. + +Correct bugs in "configure" script for case of compiling in +a directory other than the one containing the source files. + +Repair bug in jquant1.c: sometimes didn't use as many colors as it could. + +Borland C makefile and jconfig file work under either MS-DOS or OS/2. + +Miscellaneous improvements to documentation. + + +Version 5a 7-Dec-94 +-------------------- + +Changed color conversion roundoff behavior so that grayscale values are +represented exactly. (This causes test image files to change.) + +Make ordered dither use 16x16 instead of 4x4 pattern for a small quality +improvement. + +New configure script based on latest GNU Autoconf. +Fix configure script to handle CFLAGS correctly. +Rename *.auto files to *.cfg, so that configure script still works if +file names have been truncated for DOS. + +Fix bug in rdbmp.c: didn't allow for extra data between header and image. + +Modify rdppm.c/wrppm.c to handle 2-byte raw PPM/PGM formats for 12-bit data. + +Fix several bugs in rdrle.c. + +NEED_SHORT_EXTERNAL_NAMES option was broken. + +Revise jerror.h/jerror.c for more flexibility in message table. + +Repair oversight in jmemname.c NO_MKTEMP case: file could be there +but unreadable. + + +Version 5 24-Sep-94 +-------------------- + +Version 5 represents a nearly complete redesign and rewrite of the IJG +software. Major user-visible changes include: + * Automatic configuration simplifies installation for most Unix systems. + * A range of speed vs. image quality tradeoffs are supported. + This includes resizing of an image during decompression: scaling down + by a factor of 1/2, 1/4, or 1/8 is handled very efficiently. + * New programs rdjpgcom and wrjpgcom allow insertion and extraction + of text comments in a JPEG file. + +The application programmer's interface to the library has changed completely. +Notable improvements include: + * We have eliminated the use of callback routines for handling the + uncompressed image data. The application now sees the library as a + set of routines that it calls to read or write image data on a + scanline-by-scanline basis. + * The application image data is represented in a conventional interleaved- + pixel format, rather than as a separate array for each color channel. + This can save a copying step in many programs. + * The handling of compressed data has been cleaned up: the application can + supply routines to source or sink the compressed data. It is possible to + suspend processing on source/sink buffer overrun, although this is not + supported in all operating modes. + * All static state has been eliminated from the library, so that multiple + instances of compression or decompression can be active concurrently. + * JPEG abbreviated datastream formats are supported, ie, quantization and + Huffman tables can be stored separately from the image data. + * And not only that, but the documentation of the library has improved + considerably! + + +The last widely used release before the version 5 rewrite was version 4A of +18-Feb-93. Change logs before that point have been discarded, since they +are not of much interest after the rewrite. diff --git a/lc-continuity/mk4/modimage/jpeg-6b/cjpeg.1 b/lc-continuity/mk4/modimage/jpeg-6b/cjpeg.1 new file mode 100644 index 0000000000000000000000000000000000000000..d175a961c6a9c0f3f0884f20bf29b7ad165ad31b --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/cjpeg.1 @@ -0,0 +1,292 @@ +.TH CJPEG 1 "20 March 1998" +.SH NAME +cjpeg \- compress an image file to a JPEG file +.SH SYNOPSIS +.B cjpeg +[ +.I options +] +[ +.I filename +] +.LP +.SH DESCRIPTION +.LP +.B cjpeg +compresses the named image file, or the standard input if no file is +named, and produces a JPEG/JFIF file on the standard output. +The currently supported input file formats are: PPM (PBMPLUS color +format), PGM (PBMPLUS gray-scale format), BMP, Targa, and RLE (Utah Raster +Toolkit format). (RLE is supported only if the URT library is available.) +.SH OPTIONS +All switch names may be abbreviated; for example, +.B \-grayscale +may be written +.B \-gray +or +.BR \-gr . +Most of the "basic" switches can be abbreviated to as little as one letter. +Upper and lower case are equivalent (thus +.B \-BMP +is the same as +.BR \-bmp ). +British spellings are also accepted (e.g., +.BR \-greyscale ), +though for brevity these are not mentioned below. +.PP +The basic switches are: +.TP +.BI \-quality " N" +Scale quantization tables to adjust image quality. Quality is 0 (worst) to +100 (best); default is 75. (See below for more info.) +.TP +.B \-grayscale +Create monochrome JPEG file from color input. Be sure to use this switch when +compressing a grayscale BMP file, because +.B cjpeg +isn't bright enough to notice whether a BMP file uses only shades of gray. +By saying +.BR \-grayscale , +you'll get a smaller JPEG file that takes less time to process. +.TP +.B \-optimize +Perform optimization of entropy encoding parameters. Without this, default +encoding parameters are used. +.B \-optimize +usually makes the JPEG file a little smaller, but +.B cjpeg +runs somewhat slower and needs much more memory. Image quality and speed of +decompression are unaffected by +.BR \-optimize . +.TP +.B \-progressive +Create progressive JPEG file (see below). +.TP +.B \-targa +Input file is Targa format. Targa files that contain an "identification" +field will not be automatically recognized by +.BR cjpeg ; +for such files you must specify +.B \-targa +to make +.B cjpeg +treat the input as Targa format. +For most Targa files, you won't need this switch. +.PP +The +.B \-quality +switch lets you trade off compressed file size against quality of the +reconstructed image: the higher the quality setting, the larger the JPEG file, +and the closer the output image will be to the original input. Normally you +want to use the lowest quality setting (smallest file) that decompresses into +something visually indistinguishable from the original image. For this +purpose the quality setting should be between 50 and 95; the default of 75 is +often about right. If you see defects at +.B \-quality +75, then go up 5 or 10 counts at a time until you are happy with the output +image. (The optimal setting will vary from one image to another.) +.PP +.B \-quality +100 will generate a quantization table of all 1's, minimizing loss in the +quantization step (but there is still information loss in subsampling, as well +as roundoff error). This setting is mainly of interest for experimental +purposes. Quality values above about 95 are +.B not +recommended for normal use; the compressed file size goes up dramatically for +hardly any gain in output image quality. +.PP +In the other direction, quality values below 50 will produce very small files +of low image quality. Settings around 5 to 10 might be useful in preparing an +index of a large image library, for example. Try +.B \-quality +2 (or so) for some amusing Cubist effects. (Note: quality +values below about 25 generate 2-byte quantization tables, which are +considered optional in the JPEG standard. +.B cjpeg +emits a warning message when you give such a quality value, because some +other JPEG programs may be unable to decode the resulting file. Use +.B \-baseline +if you need to ensure compatibility at low quality values.) +.PP +The +.B \-progressive +switch creates a "progressive JPEG" file. In this type of JPEG file, the data +is stored in multiple scans of increasing quality. If the file is being +transmitted over a slow communications link, the decoder can use the first +scan to display a low-quality image very quickly, and can then improve the +display with each subsequent scan. The final image is exactly equivalent to a +standard JPEG file of the same quality setting, and the total file size is +about the same --- often a little smaller. +.B Caution: +progressive JPEG is not yet widely implemented, so many decoders will be +unable to view a progressive JPEG file at all. +.PP +Switches for advanced users: +.TP +.B \-dct int +Use integer DCT method (default). +.TP +.B \-dct fast +Use fast integer DCT (less accurate). +.TP +.B \-dct float +Use floating-point DCT method. +The float method is very slightly more accurate than the int method, but is +much slower unless your machine has very fast floating-point hardware. Also +note that results of the floating-point method may vary slightly across +machines, while the integer methods should give the same results everywhere. +The fast integer method is much less accurate than the other two. +.TP +.BI \-restart " N" +Emit a JPEG restart marker every N MCU rows, or every N MCU blocks if "B" is +attached to the number. +.B \-restart 0 +(the default) means no restart markers. +.TP +.BI \-smooth " N" +Smooth the input image to eliminate dithering noise. N, ranging from 1 to +100, indicates the strength of smoothing. 0 (the default) means no smoothing. +.TP +.BI \-maxmemory " N" +Set limit for amount of memory to use in processing large images. Value is +in thousands of bytes, or millions of bytes if "M" is attached to the +number. For example, +.B \-max 4m +selects 4000000 bytes. If more space is needed, temporary files will be used. +.TP +.BI \-outfile " name" +Send output image to the named file, not to standard output. +.TP +.B \-verbose +Enable debug printout. More +.BR \-v 's +give more output. Also, version information is printed at startup. +.TP +.B \-debug +Same as +.BR \-verbose . +.PP +The +.B \-restart +option inserts extra markers that allow a JPEG decoder to resynchronize after +a transmission error. Without restart markers, any damage to a compressed +file will usually ruin the image from the point of the error to the end of the +image; with restart markers, the damage is usually confined to the portion of +the image up to the next restart marker. Of course, the restart markers +occupy extra space. We recommend +.B \-restart 1 +for images that will be transmitted across unreliable networks such as Usenet. +.PP +The +.B \-smooth +option filters the input to eliminate fine-scale noise. This is often useful +when converting dithered images to JPEG: a moderate smoothing factor of 10 to +50 gets rid of dithering patterns in the input file, resulting in a smaller +JPEG file and a better-looking image. Too large a smoothing factor will +visibly blur the image, however. +.PP +Switches for wizards: +.TP +.B \-baseline +Force baseline-compatible quantization tables to be generated. This clamps +quantization values to 8 bits even at low quality settings. (This switch is +poorly named, since it does not ensure that the output is actually baseline +JPEG. For example, you can use +.B \-baseline +and +.B \-progressive +together.) +.TP +.BI \-qtables " file" +Use the quantization tables given in the specified text file. +.TP +.BI \-qslots " N[,...]" +Select which quantization table to use for each color component. +.TP +.BI \-sample " HxV[,...]" +Set JPEG sampling factors for each color component. +.TP +.BI \-scans " file" +Use the scan script given in the specified text file. +.PP +The "wizard" switches are intended for experimentation with JPEG. If you +don't know what you are doing, \fBdon't use them\fR. These switches are +documented further in the file wizard.doc. +.SH EXAMPLES +.LP +This example compresses the PPM file foo.ppm with a quality factor of +60 and saves the output as foo.jpg: +.IP +.B cjpeg \-quality +.I 60 foo.ppm +.B > +.I foo.jpg +.SH HINTS +Color GIF files are not the ideal input for JPEG; JPEG is really intended for +compressing full-color (24-bit) images. In particular, don't try to convert +cartoons, line drawings, and other images that have only a few distinct +colors. GIF works great on these, JPEG does not. If you want to convert a +GIF to JPEG, you should experiment with +.BR cjpeg 's +.B \-quality +and +.B \-smooth +options to get a satisfactory conversion. +.B \-smooth 10 +or so is often helpful. +.PP +Avoid running an image through a series of JPEG compression/decompression +cycles. Image quality loss will accumulate; after ten or so cycles the image +may be noticeably worse than it was after one cycle. It's best to use a +lossless format while manipulating an image, then convert to JPEG format when +you are ready to file the image away. +.PP +The +.B \-optimize +option to +.B cjpeg +is worth using when you are making a "final" version for posting or archiving. +It's also a win when you are using low quality settings to make very small +JPEG files; the percentage improvement is often a lot more than it is on +larger files. (At present, +.B \-optimize +mode is always selected when generating progressive JPEG files.) +.SH ENVIRONMENT +.TP +.B JPEGMEM +If this environment variable is set, its value is the default memory limit. +The value is specified as described for the +.B \-maxmemory +switch. +.B JPEGMEM +overrides the default value specified when the program was compiled, and +itself is overridden by an explicit +.BR \-maxmemory . +.SH SEE ALSO +.BR djpeg (1), +.BR jpegtran (1), +.BR rdjpgcom (1), +.BR wrjpgcom (1) +.br +.BR ppm (5), +.BR pgm (5) +.br +Wallace, Gregory K. "The JPEG Still Picture Compression Standard", +Communications of the ACM, April 1991 (vol. 34, no. 4), pp. 30-44. +.SH AUTHOR +Independent JPEG Group +.SH BUGS +Arithmetic coding is not supported for legal reasons. +.PP +GIF input files are no longer supported, to avoid the Unisys LZW patent. +Use a Unisys-licensed program if you need to read a GIF file. (Conversion +of GIF files to JPEG is usually a bad idea anyway.) +.PP +Not all variants of BMP and Targa file formats are supported. +.PP +The +.B \-targa +switch is not a bug, it's a feature. (It would be a bug if the Targa format +designers had not been clueless.) +.PP +Still not as fast as we'd like. diff --git a/lc-continuity/mk4/modimage/jpeg-6b/cjpeg.c b/lc-continuity/mk4/modimage/jpeg-6b/cjpeg.c new file mode 100644 index 0000000000000000000000000000000000000000..f2a929f0c9fa5c3f9b50b839604711cf4ca1074f --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/cjpeg.c @@ -0,0 +1,606 @@ +/* + * cjpeg.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a command-line user interface for the JPEG compressor. + * It should work on any system with Unix- or MS-DOS-style command lines. + * + * Two different command line styles are permitted, depending on the + * compile-time switch TWO_FILE_COMMANDLINE: + * cjpeg [options] inputfile outputfile + * cjpeg [options] [inputfile] + * In the second style, output is always to standard output, which you'd + * normally redirect to a file or pipe to some other program. Input is + * either from a named file or from standard input (typically redirected). + * The second style is convenient on Unix but is unhelpful on systems that + * don't support pipes. Also, you MUST use the first style if your system + * doesn't do binary I/O to stdin/stdout. + * To simplify script writing, the "-outfile" switch is provided. The syntax + * cjpeg [options] -outfile outputfile inputfile + * works regardless of which command line style is used. + */ + +#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ +#include "jversion.h" /* for version message */ + +#ifdef USE_CCOMMAND /* command-line reader for Macintosh */ +#ifdef __MWERKS__ +#include /* Metrowerks needs this */ +#include /* ... and this */ +#endif +#ifdef THINK_C +#include /* Think declares it here */ +#endif +#endif + + +/* Create the add-on message string table. */ + +#define JMESSAGE(code,string) string , + +static const char * const cdjpeg_message_table[] = { +#include "cderror.h" + NULL +}; + + +/* + * This routine determines what format the input file is, + * and selects the appropriate input-reading module. + * + * To determine which family of input formats the file belongs to, + * we may look only at the first byte of the file, since C does not + * guarantee that more than one character can be pushed back with ungetc. + * Looking at additional bytes would require one of these approaches: + * 1) assume we can fseek() the input file (fails for piped input); + * 2) assume we can push back more than one character (works in + * some C implementations, but unportable); + * 3) provide our own buffering (breaks input readers that want to use + * stdio directly, such as the RLE library); + * or 4) don't put back the data, and modify the input_init methods to assume + * they start reading after the start of file (also breaks RLE library). + * #1 is attractive for MS-DOS but is untenable on Unix. + * + * The most portable solution for file types that can't be identified by their + * first byte is to make the user tell us what they are. This is also the + * only approach for "raw" file types that contain only arbitrary values. + * We presently apply this method for Targa files. Most of the time Targa + * files start with 0x00, so we recognize that case. Potentially, however, + * a Targa file could start with any byte value (byte 0 is the length of the + * seldom-used ID field), so we provide a switch to force Targa input mode. + */ + +static boolean is_targa; /* records user -targa switch */ + + +LOCAL(cjpeg_source_ptr) +select_file_type (j_compress_ptr cinfo, FILE * infile) +{ + int c; + + if (is_targa) { +#ifdef TARGA_SUPPORTED + return jinit_read_targa(cinfo); +#else + ERREXIT(cinfo, JERR_TGA_NOTCOMP); +#endif + } + + if ((c = getc(infile)) == EOF) + ERREXIT(cinfo, JERR_INPUT_EMPTY); + if (ungetc(c, infile) == EOF) + ERREXIT(cinfo, JERR_UNGETC_FAILED); + + switch (c) { +#ifdef BMP_SUPPORTED + case 'B': + return jinit_read_bmp(cinfo); +#endif +#ifdef GIF_SUPPORTED + case 'G': + return jinit_read_gif(cinfo); +#endif +#ifdef PPM_SUPPORTED + case 'P': + return jinit_read_ppm(cinfo); +#endif +#ifdef RLE_SUPPORTED + case 'R': + return jinit_read_rle(cinfo); +#endif +#ifdef TARGA_SUPPORTED + case 0x00: + return jinit_read_targa(cinfo); +#endif + default: + ERREXIT(cinfo, JERR_UNKNOWN_FORMAT); + break; + } + + return NULL; /* suppress compiler warnings */ +} + + +/* + * Argument-parsing code. + * The switch parser is designed to be useful with DOS-style command line + * syntax, ie, intermixed switches and file names, where only the switches + * to the left of a given file name affect processing of that file. + * The main program in this file doesn't actually use this capability... + */ + + +static const char * progname; /* program name for error messages */ +static char * outfilename; /* for -outfile switch */ + + +LOCAL(void) +usage (void) +/* complain about bad command line */ +{ + fprintf(stderr, "usage: %s [switches] ", progname); +#ifdef TWO_FILE_COMMANDLINE + fprintf(stderr, "inputfile outputfile\n"); +#else + fprintf(stderr, "[inputfile]\n"); +#endif + + fprintf(stderr, "Switches (names may be abbreviated):\n"); + fprintf(stderr, " -quality N Compression quality (0..100; 5-95 is useful range)\n"); + fprintf(stderr, " -grayscale Create monochrome JPEG file\n"); +#ifdef ENTROPY_OPT_SUPPORTED + fprintf(stderr, " -optimize Optimize Huffman table (smaller file, but slow compression)\n"); +#endif +#ifdef C_PROGRESSIVE_SUPPORTED + fprintf(stderr, " -progressive Create progressive JPEG file\n"); +#endif +#ifdef TARGA_SUPPORTED + fprintf(stderr, " -targa Input file is Targa format (usually not needed)\n"); +#endif + fprintf(stderr, "Switches for advanced users:\n"); +#ifdef DCT_ISLOW_SUPPORTED + fprintf(stderr, " -dct int Use integer DCT method%s\n", + (JDCT_DEFAULT == JDCT_ISLOW ? " (default)" : "")); +#endif +#ifdef DCT_IFAST_SUPPORTED + fprintf(stderr, " -dct fast Use fast integer DCT (less accurate)%s\n", + (JDCT_DEFAULT == JDCT_IFAST ? " (default)" : "")); +#endif +#ifdef DCT_FLOAT_SUPPORTED + fprintf(stderr, " -dct float Use floating-point DCT method%s\n", + (JDCT_DEFAULT == JDCT_FLOAT ? " (default)" : "")); +#endif + fprintf(stderr, " -restart N Set restart interval in rows, or in blocks with B\n"); +#ifdef INPUT_SMOOTHING_SUPPORTED + fprintf(stderr, " -smooth N Smooth dithered input (N=1..100 is strength)\n"); +#endif + fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n"); + fprintf(stderr, " -outfile name Specify name for output file\n"); + fprintf(stderr, " -verbose or -debug Emit debug output\n"); + fprintf(stderr, "Switches for wizards:\n"); +#ifdef C_ARITH_CODING_SUPPORTED + fprintf(stderr, " -arithmetic Use arithmetic coding\n"); +#endif + fprintf(stderr, " -baseline Force baseline quantization tables\n"); + fprintf(stderr, " -qtables file Use quantization tables given in file\n"); + fprintf(stderr, " -qslots N[,...] Set component quantization tables\n"); + fprintf(stderr, " -sample HxV[,...] Set component sampling factors\n"); +#ifdef C_MULTISCAN_FILES_SUPPORTED + fprintf(stderr, " -scans file Create multi-scan JPEG per script file\n"); +#endif + exit(EXIT_FAILURE); +} + + +LOCAL(int) +parse_switches (j_compress_ptr cinfo, int argc, char **argv, + int last_file_arg_seen, boolean for_real) +/* Parse optional switches. + * Returns argv[] index of first file-name argument (== argc if none). + * Any file names with indexes <= last_file_arg_seen are ignored; + * they have presumably been processed in a previous iteration. + * (Pass 0 for last_file_arg_seen on the first or only iteration.) + * for_real is FALSE on the first (dummy) pass; we may skip any expensive + * processing. + */ +{ + int argn; + char * arg; + int quality; /* -quality parameter */ + int q_scale_factor; /* scaling percentage for -qtables */ + boolean force_baseline; + boolean simple_progressive; + char * qtablefile = NULL; /* saves -qtables filename if any */ + char * qslotsarg = NULL; /* saves -qslots parm if any */ + char * samplearg = NULL; /* saves -sample parm if any */ + char * scansarg = NULL; /* saves -scans parm if any */ + + /* Set up default JPEG parameters. */ + /* Note that default -quality level need not, and does not, + * match the default scaling for an explicit -qtables argument. + */ + quality = 75; /* default -quality value */ + q_scale_factor = 100; /* default to no scaling for -qtables */ + force_baseline = FALSE; /* by default, allow 16-bit quantizers */ + simple_progressive = FALSE; + is_targa = FALSE; + outfilename = NULL; + cinfo->err->trace_level = 0; + + /* Scan command line options, adjust parameters */ + + for (argn = 1; argn < argc; argn++) { + arg = argv[argn]; + if (*arg != '-') { + /* Not a switch, must be a file name argument */ + if (argn <= last_file_arg_seen) { + outfilename = NULL; /* -outfile applies to just one input file */ + continue; /* ignore this name if previously processed */ + } + break; /* else done parsing switches */ + } + arg++; /* advance past switch marker character */ + + if (keymatch(arg, "arithmetic", 1)) { + /* Use arithmetic coding. */ +#ifdef C_ARITH_CODING_SUPPORTED + cinfo->arith_code = TRUE; +#else + fprintf(stderr, "%s: sorry, arithmetic coding not supported\n", + progname); + exit(EXIT_FAILURE); +#endif + + } else if (keymatch(arg, "baseline", 1)) { + /* Force baseline-compatible output (8-bit quantizer values). */ + force_baseline = TRUE; + + } else if (keymatch(arg, "dct", 2)) { + /* Select DCT algorithm. */ + if (++argn >= argc) /* advance to next argument */ + usage(); + if (keymatch(argv[argn], "int", 1)) { + cinfo->dct_method = JDCT_ISLOW; + } else if (keymatch(argv[argn], "fast", 2)) { + cinfo->dct_method = JDCT_IFAST; + } else if (keymatch(argv[argn], "float", 2)) { + cinfo->dct_method = JDCT_FLOAT; + } else + usage(); + + } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) { + /* Enable debug printouts. */ + /* On first -d, print version identification */ + static boolean printed_version = FALSE; + + if (! printed_version) { + fprintf(stderr, "Independent JPEG Group's CJPEG, version %s\n%s\n", + JVERSION, JCOPYRIGHT); + printed_version = TRUE; + } + cinfo->err->trace_level++; + + } else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) { + /* Force a monochrome JPEG file to be generated. */ + jpeg_set_colorspace(cinfo, JCS_GRAYSCALE); + + } else if (keymatch(arg, "maxmemory", 3)) { + /* Maximum memory in Kb (or Mb with 'm'). */ + long lval; + char ch = 'x'; + + if (++argn >= argc) /* advance to next argument */ + usage(); + if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1) + usage(); + if (ch == 'm' || ch == 'M') + lval *= 1000L; + cinfo->mem->max_memory_to_use = lval * 1000L; + + } else if (keymatch(arg, "optimize", 1) || keymatch(arg, "optimise", 1)) { + /* Enable entropy parm optimization. */ +#ifdef ENTROPY_OPT_SUPPORTED + cinfo->optimize_coding = TRUE; +#else + fprintf(stderr, "%s: sorry, entropy optimization was not compiled\n", + progname); + exit(EXIT_FAILURE); +#endif + + } else if (keymatch(arg, "outfile", 4)) { + /* Set output file name. */ + if (++argn >= argc) /* advance to next argument */ + usage(); + outfilename = argv[argn]; /* save it away for later use */ + + } else if (keymatch(arg, "progressive", 1)) { + /* Select simple progressive mode. */ +#ifdef C_PROGRESSIVE_SUPPORTED + simple_progressive = TRUE; + /* We must postpone execution until num_components is known. */ +#else + fprintf(stderr, "%s: sorry, progressive output was not compiled\n", + progname); + exit(EXIT_FAILURE); +#endif + + } else if (keymatch(arg, "quality", 1)) { + /* Quality factor (quantization table scaling factor). */ + if (++argn >= argc) /* advance to next argument */ + usage(); + if (sscanf(argv[argn], "%d", &quality) != 1) + usage(); + /* Change scale factor in case -qtables is present. */ + q_scale_factor = jpeg_quality_scaling(quality); + + } else if (keymatch(arg, "qslots", 2)) { + /* Quantization table slot numbers. */ + if (++argn >= argc) /* advance to next argument */ + usage(); + qslotsarg = argv[argn]; + /* Must delay setting qslots until after we have processed any + * colorspace-determining switches, since jpeg_set_colorspace sets + * default quant table numbers. + */ + + } else if (keymatch(arg, "qtables", 2)) { + /* Quantization tables fetched from file. */ + if (++argn >= argc) /* advance to next argument */ + usage(); + qtablefile = argv[argn]; + /* We postpone actually reading the file in case -quality comes later. */ + + } else if (keymatch(arg, "restart", 1)) { + /* Restart interval in MCU rows (or in MCUs with 'b'). */ + long lval; + char ch = 'x'; + + if (++argn >= argc) /* advance to next argument */ + usage(); + if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1) + usage(); + if (lval < 0 || lval > 65535L) + usage(); + if (ch == 'b' || ch == 'B') { + cinfo->restart_interval = (unsigned int) lval; + cinfo->restart_in_rows = 0; /* else prior '-restart n' overrides me */ + } else { + cinfo->restart_in_rows = (int) lval; + /* restart_interval will be computed during startup */ + } + + } else if (keymatch(arg, "sample", 2)) { + /* Set sampling factors. */ + if (++argn >= argc) /* advance to next argument */ + usage(); + samplearg = argv[argn]; + /* Must delay setting sample factors until after we have processed any + * colorspace-determining switches, since jpeg_set_colorspace sets + * default sampling factors. + */ + + } else if (keymatch(arg, "scans", 2)) { + /* Set scan script. */ +#ifdef C_MULTISCAN_FILES_SUPPORTED + if (++argn >= argc) /* advance to next argument */ + usage(); + scansarg = argv[argn]; + /* We must postpone reading the file in case -progressive appears. */ +#else + fprintf(stderr, "%s: sorry, multi-scan output was not compiled\n", + progname); + exit(EXIT_FAILURE); +#endif + + } else if (keymatch(arg, "smooth", 2)) { + /* Set input smoothing factor. */ + int val; + + if (++argn >= argc) /* advance to next argument */ + usage(); + if (sscanf(argv[argn], "%d", &val) != 1) + usage(); + if (val < 0 || val > 100) + usage(); + cinfo->smoothing_factor = val; + + } else if (keymatch(arg, "targa", 1)) { + /* Input file is Targa format. */ + is_targa = TRUE; + + } else { + usage(); /* bogus switch */ + } + } + + /* Post-switch-scanning cleanup */ + + if (for_real) { + + /* Set quantization tables for selected quality. */ + /* Some or all may be overridden if -qtables is present. */ + jpeg_set_quality(cinfo, quality, force_baseline); + + if (qtablefile != NULL) /* process -qtables if it was present */ + if (! read_quant_tables(cinfo, qtablefile, + q_scale_factor, force_baseline)) + usage(); + + if (qslotsarg != NULL) /* process -qslots if it was present */ + if (! set_quant_slots(cinfo, qslotsarg)) + usage(); + + if (samplearg != NULL) /* process -sample if it was present */ + if (! set_sample_factors(cinfo, samplearg)) + usage(); + +#ifdef C_PROGRESSIVE_SUPPORTED + if (simple_progressive) /* process -progressive; -scans can override */ + jpeg_simple_progression(cinfo); +#endif + +#ifdef C_MULTISCAN_FILES_SUPPORTED + if (scansarg != NULL) /* process -scans if it was present */ + if (! read_scan_script(cinfo, scansarg)) + usage(); +#endif + } + + return argn; /* return index of next arg (file name) */ +} + + +/* + * The main program. + */ + +int +main (int argc, char **argv) +{ + struct jpeg_compress_struct cinfo; + struct jpeg_error_mgr jerr; +#ifdef PROGRESS_REPORT + struct cdjpeg_progress_mgr progress; +#endif + int file_index; + cjpeg_source_ptr src_mgr; + FILE * input_file; + FILE * output_file; + JDIMENSION num_scanlines; + + /* On Mac, fetch a command line. */ +#ifdef USE_CCOMMAND + argc = ccommand(&argv); +#endif + + progname = argv[0]; + if (progname == NULL || progname[0] == 0) + progname = "cjpeg"; /* in case C library doesn't provide it */ + + /* Initialize the JPEG compression object with default error handling. */ + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_compress(&cinfo); + /* Add some application-specific error messages (from cderror.h) */ + jerr.addon_message_table = cdjpeg_message_table; + jerr.first_addon_message = JMSG_FIRSTADDONCODE; + jerr.last_addon_message = JMSG_LASTADDONCODE; + + /* Now safe to enable signal catcher. */ +#ifdef NEED_SIGNAL_CATCHER + enable_signal_catcher((j_common_ptr) &cinfo); +#endif + + /* Initialize JPEG parameters. + * Much of this may be overridden later. + * In particular, we don't yet know the input file's color space, + * but we need to provide some value for jpeg_set_defaults() to work. + */ + + cinfo.in_color_space = JCS_RGB; /* arbitrary guess */ + jpeg_set_defaults(&cinfo); + + /* Scan command line to find file names. + * It is convenient to use just one switch-parsing routine, but the switch + * values read here are ignored; we will rescan the switches after opening + * the input file. + */ + + file_index = parse_switches(&cinfo, argc, argv, 0, FALSE); + +#ifdef TWO_FILE_COMMANDLINE + /* Must have either -outfile switch or explicit output file name */ + if (outfilename == NULL) { + if (file_index != argc-2) { + fprintf(stderr, "%s: must name one input and one output file\n", + progname); + usage(); + } + outfilename = argv[file_index+1]; + } else { + if (file_index != argc-1) { + fprintf(stderr, "%s: must name one input and one output file\n", + progname); + usage(); + } + } +#else + /* Unix style: expect zero or one file name */ + if (file_index < argc-1) { + fprintf(stderr, "%s: only one input file\n", progname); + usage(); + } +#endif /* TWO_FILE_COMMANDLINE */ + + /* Open the input file. */ + if (file_index < argc) { + if ((input_file = fopen(argv[file_index], READ_BINARY)) == NULL) { + fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]); + exit(EXIT_FAILURE); + } + } else { + /* default input file is stdin */ + input_file = read_stdin(); + } + + /* Open the output file. */ + if (outfilename != NULL) { + if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) { + fprintf(stderr, "%s: can't open %s\n", progname, outfilename); + exit(EXIT_FAILURE); + } + } else { + /* default output file is stdout */ + output_file = write_stdout(); + } + +#ifdef PROGRESS_REPORT + start_progress_monitor((j_common_ptr) &cinfo, &progress); +#endif + + /* Figure out the input file format, and set up to read it. */ + src_mgr = select_file_type(&cinfo, input_file); + src_mgr->input_file = input_file; + + /* Read the input file header to obtain file size & colorspace. */ + (*src_mgr->start_input) (&cinfo, src_mgr); + + /* Now that we know input colorspace, fix colorspace-dependent defaults */ + jpeg_default_colorspace(&cinfo); + + /* Adjust default compression parameters by re-parsing the options */ + file_index = parse_switches(&cinfo, argc, argv, 0, TRUE); + + /* Specify data destination for compression */ + jpeg_stdio_dest(&cinfo, output_file); + + /* Start compressor */ + jpeg_start_compress(&cinfo, TRUE); + + /* Process data */ + while (cinfo.next_scanline < cinfo.image_height) { + num_scanlines = (*src_mgr->get_pixel_rows) (&cinfo, src_mgr); + (void) jpeg_write_scanlines(&cinfo, src_mgr->buffer, num_scanlines); + } + + /* Finish compression and release memory */ + (*src_mgr->finish_input) (&cinfo, src_mgr); + jpeg_finish_compress(&cinfo); + jpeg_destroy_compress(&cinfo); + + /* Close files, if we opened them */ + if (input_file != stdin) + fclose(input_file); + if (output_file != stdout) + fclose(output_file); + +#ifdef PROGRESS_REPORT + end_progress_monitor((j_common_ptr) &cinfo); +#endif + + /* All done. */ + exit(jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS); + return 0; /* suppress no-return-value warnings */ +} diff --git a/lc-continuity/mk4/modimage/jpeg-6b/ckconfig.c b/lc-continuity/mk4/modimage/jpeg-6b/ckconfig.c new file mode 100644 index 0000000000000000000000000000000000000000..34baf795b00957f4a48f28b0f5797fe9734d86a2 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/ckconfig.c @@ -0,0 +1,402 @@ +/* + * ckconfig.c + * + * Copyright (C) 1991-1994, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + */ + +/* + * This program is intended to help you determine how to configure the JPEG + * software for installation on a particular system. The idea is to try to + * compile and execute this program. If your compiler fails to compile the + * program, make changes as indicated in the comments below. Once you can + * compile the program, run it, and it will produce a "jconfig.h" file for + * your system. + * + * As a general rule, each time you try to compile this program, + * pay attention only to the *first* error message you get from the compiler. + * Many C compilers will issue lots of spurious error messages once they + * have gotten confused. Go to the line indicated in the first error message, + * and read the comments preceding that line to see what to change. + * + * Almost all of the edits you may need to make to this program consist of + * changing a line that reads "#define SOME_SYMBOL" to "#undef SOME_SYMBOL", + * or vice versa. This is called defining or undefining that symbol. + */ + + +/* First we must see if your system has the include files we need. + * We start out with the assumption that your system has all the ANSI-standard + * include files. If you get any error trying to include one of these files, + * undefine the corresponding HAVE_xxx symbol. + */ + +#define HAVE_STDDEF_H /* replace 'define' by 'undef' if error here */ +#ifdef HAVE_STDDEF_H /* next line will be skipped if you undef... */ +#include +#endif + +#define HAVE_STDLIB_H /* same thing for stdlib.h */ +#ifdef HAVE_STDLIB_H +#include +#endif + +#include /* If you ain't got this, you ain't got C. */ + +/* We have to see if your string functions are defined by + * strings.h (old BSD convention) or string.h (everybody else). + * We try the non-BSD convention first; define NEED_BSD_STRINGS + * if the compiler says it can't find string.h. + */ + +#undef NEED_BSD_STRINGS + +#ifdef NEED_BSD_STRINGS +#include +#else +#include +#endif + +/* On some systems (especially older Unix machines), type size_t is + * defined only in the include file . If you get a failure + * on the size_t test below, try defining NEED_SYS_TYPES_H. + */ + +#undef NEED_SYS_TYPES_H /* start by assuming we don't need it */ +#ifdef NEED_SYS_TYPES_H +#include +#endif + + +/* Usually type size_t is defined in one of the include files we've included + * above. If not, you'll get an error on the "typedef size_t my_size_t;" line. + * In that case, first try defining NEED_SYS_TYPES_H just above. + * If that doesn't work, you'll have to search through your system library + * to figure out which include file defines "size_t". Look for a line that + * says "typedef something-or-other size_t;". Then, change the line below + * that says "#include " to instead include the file + * you found size_t in, and define NEED_SPECIAL_INCLUDE. If you can't find + * type size_t anywhere, try replacing "#include " with + * "typedef unsigned int size_t;". + */ + +#undef NEED_SPECIAL_INCLUDE /* assume we DON'T need it, for starters */ + +#ifdef NEED_SPECIAL_INCLUDE +#include +#endif + +typedef size_t my_size_t; /* The payoff: do we have size_t now? */ + + +/* The next question is whether your compiler supports ANSI-style function + * prototypes. You need to know this in order to choose between using + * makefile.ansi and using makefile.unix. + * The #define line below is set to assume you have ANSI function prototypes. + * If you get an error in this group of lines, undefine HAVE_PROTOTYPES. + */ + +#define HAVE_PROTOTYPES + +#ifdef HAVE_PROTOTYPES +int testfunction (int arg1, int * arg2); /* check prototypes */ + +struct methods_struct { /* check method-pointer declarations */ + int (*error_exit) (char *msgtext); + int (*trace_message) (char *msgtext); + int (*another_method) (void); +}; + +int testfunction (int arg1, int * arg2) /* check definitions */ +{ + return arg2[arg1]; +} + +int test2function (void) /* check void arg list */ +{ + return 0; +} +#endif + + +/* Now we want to find out if your compiler knows what "unsigned char" means. + * If you get an error on the "unsigned char un_char;" line, + * then undefine HAVE_UNSIGNED_CHAR. + */ + +#define HAVE_UNSIGNED_CHAR + +#ifdef HAVE_UNSIGNED_CHAR +unsigned char un_char; +#endif + + +/* Now we want to find out if your compiler knows what "unsigned short" means. + * If you get an error on the "unsigned short un_short;" line, + * then undefine HAVE_UNSIGNED_SHORT. + */ + +#define HAVE_UNSIGNED_SHORT + +#ifdef HAVE_UNSIGNED_SHORT +unsigned short un_short; +#endif + + +/* Now we want to find out if your compiler understands type "void". + * If you get an error anywhere in here, undefine HAVE_VOID. + */ + +#define HAVE_VOID + +#ifdef HAVE_VOID +/* Caution: a C++ compiler will insist on complete prototypes */ +typedef void * void_ptr; /* check void * */ +#ifdef HAVE_PROTOTYPES /* check ptr to function returning void */ +typedef void (*void_func) (int a, int b); +#else +typedef void (*void_func) (); +#endif + +#ifdef HAVE_PROTOTYPES /* check void function result */ +void test3function (void_ptr arg1, void_func arg2) +#else +void test3function (arg1, arg2) + void_ptr arg1; + void_func arg2; +#endif +{ + char * locptr = (char *) arg1; /* check casting to and from void * */ + arg1 = (void *) locptr; + (*arg2) (1, 2); /* check call of fcn returning void */ +} +#endif + + +/* Now we want to find out if your compiler knows what "const" means. + * If you get an error here, undefine HAVE_CONST. + */ + +#define HAVE_CONST + +#ifdef HAVE_CONST +static const int carray[3] = {1, 2, 3}; + +#ifdef HAVE_PROTOTYPES +int test4function (const int arg1) +#else +int test4function (arg1) + const int arg1; +#endif +{ + return carray[arg1]; +} +#endif + + +/* If you get an error or warning about this structure definition, + * define INCOMPLETE_TYPES_BROKEN. + */ + +#undef INCOMPLETE_TYPES_BROKEN + +#ifndef INCOMPLETE_TYPES_BROKEN +typedef struct undefined_structure * undef_struct_ptr; +#endif + + +/* If you get an error about duplicate names, + * define NEED_SHORT_EXTERNAL_NAMES. + */ + +#undef NEED_SHORT_EXTERNAL_NAMES + +#ifndef NEED_SHORT_EXTERNAL_NAMES + +int possibly_duplicate_function () +{ + return 0; +} + +int possibly_dupli_function () +{ + return 1; +} + +#endif + + + +/************************************************************************ + * OK, that's it. You should not have to change anything beyond this + * point in order to compile and execute this program. (You might get + * some warnings, but you can ignore them.) + * When you run the program, it will make a couple more tests that it + * can do automatically, and then it will create jconfig.h and print out + * any additional suggestions it has. + ************************************************************************ + */ + + +#ifdef HAVE_PROTOTYPES +int is_char_signed (int arg) +#else +int is_char_signed (arg) + int arg; +#endif +{ + if (arg == 189) { /* expected result for unsigned char */ + return 0; /* type char is unsigned */ + } + else if (arg != -67) { /* expected result for signed char */ + printf("Hmm, it seems 'char' is not eight bits wide on your machine.\n"); + printf("I fear the JPEG software will not work at all.\n\n"); + } + return 1; /* assume char is signed otherwise */ +} + + +#ifdef HAVE_PROTOTYPES +int is_shifting_signed (long arg) +#else +int is_shifting_signed (arg) + long arg; +#endif +/* See whether right-shift on a long is signed or not. */ +{ + long res = arg >> 4; + + if (res == -0x7F7E80CL) { /* expected result for signed shift */ + return 1; /* right shift is signed */ + } + /* see if unsigned-shift hack will fix it. */ + /* we can't just test exact value since it depends on width of long... */ + res |= (~0L) << (32-4); + if (res == -0x7F7E80CL) { /* expected result now? */ + return 0; /* right shift is unsigned */ + } + printf("Right shift isn't acting as I expect it to.\n"); + printf("I fear the JPEG software will not work at all.\n\n"); + return 0; /* try it with unsigned anyway */ +} + + +#ifdef HAVE_PROTOTYPES +int main (int argc, char ** argv) +#else +int main (argc, argv) + int argc; + char ** argv; +#endif +{ + char signed_char_check = (char) (-67); + FILE *outfile; + + /* Attempt to write jconfig.h */ + if ((outfile = fopen("jconfig.h", "w")) == NULL) { + printf("Failed to write jconfig.h\n"); + return 1; + } + + /* Write out all the info */ + fprintf(outfile, "/* jconfig.h --- generated by ckconfig.c */\n"); + fprintf(outfile, "/* see jconfig.doc for explanations */\n\n"); +#ifdef HAVE_PROTOTYPES + fprintf(outfile, "#define HAVE_PROTOTYPES\n"); +#else + fprintf(outfile, "#undef HAVE_PROTOTYPES\n"); +#endif +#ifdef HAVE_UNSIGNED_CHAR + fprintf(outfile, "#define HAVE_UNSIGNED_CHAR\n"); +#else + fprintf(outfile, "#undef HAVE_UNSIGNED_CHAR\n"); +#endif +#ifdef HAVE_UNSIGNED_SHORT + fprintf(outfile, "#define HAVE_UNSIGNED_SHORT\n"); +#else + fprintf(outfile, "#undef HAVE_UNSIGNED_SHORT\n"); +#endif +#ifdef HAVE_VOID + fprintf(outfile, "/* #define void char */\n"); +#else + fprintf(outfile, "#define void char\n"); +#endif +#ifdef HAVE_CONST + fprintf(outfile, "/* #define const */\n"); +#else + fprintf(outfile, "#define const\n"); +#endif + if (is_char_signed((int) signed_char_check)) + fprintf(outfile, "#undef CHAR_IS_UNSIGNED\n"); + else + fprintf(outfile, "#define CHAR_IS_UNSIGNED\n"); +#ifdef HAVE_STDDEF_H + fprintf(outfile, "#define HAVE_STDDEF_H\n"); +#else + fprintf(outfile, "#undef HAVE_STDDEF_H\n"); +#endif +#ifdef HAVE_STDLIB_H + fprintf(outfile, "#define HAVE_STDLIB_H\n"); +#else + fprintf(outfile, "#undef HAVE_STDLIB_H\n"); +#endif +#ifdef NEED_BSD_STRINGS + fprintf(outfile, "#define NEED_BSD_STRINGS\n"); +#else + fprintf(outfile, "#undef NEED_BSD_STRINGS\n"); +#endif +#ifdef NEED_SYS_TYPES_H + fprintf(outfile, "#define NEED_SYS_TYPES_H\n"); +#else + fprintf(outfile, "#undef NEED_SYS_TYPES_H\n"); +#endif + fprintf(outfile, "#undef NEED_FAR_POINTERS\n"); +#ifdef NEED_SHORT_EXTERNAL_NAMES + fprintf(outfile, "#define NEED_SHORT_EXTERNAL_NAMES\n"); +#else + fprintf(outfile, "#undef NEED_SHORT_EXTERNAL_NAMES\n"); +#endif +#ifdef INCOMPLETE_TYPES_BROKEN + fprintf(outfile, "#define INCOMPLETE_TYPES_BROKEN\n"); +#else + fprintf(outfile, "#undef INCOMPLETE_TYPES_BROKEN\n"); +#endif + fprintf(outfile, "\n#ifdef JPEG_INTERNALS\n\n"); + if (is_shifting_signed(-0x7F7E80B1L)) + fprintf(outfile, "#undef RIGHT_SHIFT_IS_UNSIGNED\n"); + else + fprintf(outfile, "#define RIGHT_SHIFT_IS_UNSIGNED\n"); + fprintf(outfile, "\n#endif /* JPEG_INTERNALS */\n"); + fprintf(outfile, "\n#ifdef JPEG_CJPEG_DJPEG\n\n"); + fprintf(outfile, "#define BMP_SUPPORTED /* BMP image file format */\n"); + fprintf(outfile, "#define GIF_SUPPORTED /* GIF image file format */\n"); + fprintf(outfile, "#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */\n"); + fprintf(outfile, "#undef RLE_SUPPORTED /* Utah RLE image file format */\n"); + fprintf(outfile, "#define TARGA_SUPPORTED /* Targa image file format */\n\n"); + fprintf(outfile, "#undef TWO_FILE_COMMANDLINE /* You may need this on non-Unix systems */\n"); + fprintf(outfile, "#undef NEED_SIGNAL_CATCHER /* Define this if you use jmemname.c */\n"); + fprintf(outfile, "#undef DONT_USE_B_MODE\n"); + fprintf(outfile, "/* #define PROGRESS_REPORT */ /* optional */\n"); + fprintf(outfile, "\n#endif /* JPEG_CJPEG_DJPEG */\n"); + + /* Close the jconfig.h file */ + fclose(outfile); + + /* User report */ + printf("Configuration check for Independent JPEG Group's software done.\n"); + printf("\nI have written the jconfig.h file for you.\n\n"); +#ifdef HAVE_PROTOTYPES + printf("You should use makefile.ansi as the starting point for your Makefile.\n"); +#else + printf("You should use makefile.unix as the starting point for your Makefile.\n"); +#endif + +#ifdef NEED_SPECIAL_INCLUDE + printf("\nYou'll need to change jconfig.h to include the system include file\n"); + printf("that you found type size_t in, or add a direct definition of type\n"); + printf("size_t if that's what you used. Just add it to the end.\n"); +#endif + + return 0; +} diff --git a/lc-continuity/mk4/modimage/jpeg-6b/coderules.doc b/lc-continuity/mk4/modimage/jpeg-6b/coderules.doc new file mode 100644 index 0000000000000000000000000000000000000000..0ab5d9bd302ea3dc548c18fa69f2505fc142896b --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/coderules.doc @@ -0,0 +1,118 @@ +IJG JPEG LIBRARY: CODING RULES + +Copyright (C) 1991-1996, Thomas G. Lane. +This file is part of the Independent JPEG Group's software. +For conditions of distribution and use, see the accompanying README file. + + +Since numerous people will be contributing code and bug fixes, it's important +to establish a common coding style. The goal of using similar coding styles +is much more important than the details of just what that style is. + +In general we follow the recommendations of "Recommended C Style and Coding +Standards" revision 6.1 (Cannon et al. as modified by Spencer, Keppel and +Brader). This document is available in the IJG FTP archive (see +jpeg/doc/cstyle.ms.tbl.Z, or cstyle.txt.Z for those without nroff/tbl). + +Block comments should be laid out thusly: + +/* + * Block comments in this style. + */ + +We indent statements in K&R style, e.g., + if (test) { + then-part; + } else { + else-part; + } +with two spaces per indentation level. (This indentation convention is +handled automatically by GNU Emacs and many other text editors.) + +Multi-word names should be written in lower case with underscores, e.g., +multi_word_name (not multiWordName). Preprocessor symbols and enum constants +are similar but upper case (MULTI_WORD_NAME). Names should be unique within +the first fifteen characters. (On some older systems, global names must be +unique within six characters. We accommodate this without cluttering the +source code by using macros to substitute shorter names.) + +We use function prototypes everywhere; we rely on automatic source code +transformation to feed prototype-less C compilers. Transformation is done +by the simple and portable tool 'ansi2knr.c' (courtesy of Ghostscript). +ansi2knr is not very bright, so it imposes a format requirement on function +declarations: the function name MUST BEGIN IN COLUMN 1. Thus all functions +should be written in the following style: + +LOCAL(int *) +function_name (int a, char *b) +{ + code... +} + +Note that each function definition must begin with GLOBAL(type), LOCAL(type), +or METHODDEF(type). These macros expand to "static type" or just "type" as +appropriate. They provide a readable indication of the routine's usage and +can readily be changed for special needs. (For instance, special linkage +keywords can be inserted for use in Windows DLLs.) + +ansi2knr does not transform method declarations (function pointers in +structs). We handle these with a macro JMETHOD, defined as + #ifdef HAVE_PROTOTYPES + #define JMETHOD(type,methodname,arglist) type (*methodname) arglist + #else + #define JMETHOD(type,methodname,arglist) type (*methodname) () + #endif +which is used like this: + struct function_pointers { + JMETHOD(void, init_entropy_encoder, (int somearg, jparms *jp)); + JMETHOD(void, term_entropy_encoder, (void)); + }; +Note the set of parentheses surrounding the parameter list. + +A similar solution is used for forward and external function declarations +(see the EXTERN and JPP macros). + +If the code is to work on non-ANSI compilers, we cannot rely on a prototype +declaration to coerce actual parameters into the right types. Therefore, use +explicit casts on actual parameters whenever the actual parameter type is not +identical to the formal parameter. Beware of implicit conversions to "int". + +It seems there are some non-ANSI compilers in which the sizeof() operator +is defined to return int, yet size_t is defined as long. Needless to say, +this is brain-damaged. Always use the SIZEOF() macro in place of sizeof(), +so that the result is guaranteed to be of type size_t. + + +The JPEG library is intended to be used within larger programs. Furthermore, +we want it to be reentrant so that it can be used by applications that process +multiple images concurrently. The following rules support these requirements: + +1. Avoid direct use of file I/O, "malloc", error report printouts, etc; +pass these through the common routines provided. + +2. Minimize global namespace pollution. Functions should be declared static +wherever possible. (Note that our method-based calling conventions help this +a lot: in many modules only the initialization function will ever need to be +called directly, so only that function need be externally visible.) All +global function names should begin with "jpeg_", and should have an +abbreviated name (unique in the first six characters) substituted by macro +when NEED_SHORT_EXTERNAL_NAMES is set. + +3. Don't use global variables; anything that must be used in another module +should be in the common data structures. + +4. Don't use static variables except for read-only constant tables. Variables +that should be private to a module can be placed into private structures (see +the system architecture document, structure.doc). + +5. Source file names should begin with "j" for files that are part of the +library proper; source files that are not part of the library, such as cjpeg.c +and djpeg.c, do not begin with "j". Keep source file names to eight +characters (plus ".c" or ".h", etc) to make life easy for MS-DOSers. Keep +compression and decompression code in separate source files --- some +applications may want only one half of the library. + +Note: these rules (particularly #4) are not followed religiously in the +modules that are used in cjpeg/djpeg but are not part of the JPEG library +proper. Those modules are not really intended to be used in other +applications. diff --git a/lc-continuity/mk4/modimage/jpeg-6b/config.guess b/lc-continuity/mk4/modimage/jpeg-6b/config.guess new file mode 100644 index 0000000000000000000000000000000000000000..413ed41c0f531d99735a9d894bda6b9dea887e5d --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/config.guess @@ -0,0 +1,883 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 93, 94, 95, 96, 1997 Free Software Foundation, Inc. +# +# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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. + +# Written by Per Bothner . +# The master version of this file is at the FSF in /home/gd/gnu/lib. +# +# 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. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit system type (host/target name). +# +# Only a few systems have been added to this list; please add others +# (but try to keep the structure clean). +# + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 8/24/94.) +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 + +trap 'rm -f dummy.c dummy.o dummy; exit 1' 1 2 15 + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + alpha:OSF1:*:*) + if test $UNAME_RELEASE = "V4.0"; then + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + fi + # 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. + cat <dummy.s + .globl main + .ent main +main: + .frame \$30,0,\$26,0 + .prologue 0 + .long 0x47e03d80 # implver $0 + lda \$2,259 + .long 0x47e20c21 # amask $2,$1 + srl \$1,8,\$2 + sll \$2,2,\$2 + sll \$0,3,\$0 + addl \$1,\$0,\$0 + addl \$2,\$0,\$0 + ret \$31,(\$26),1 + .end main +EOF + ${CC-cc} dummy.s -o dummy 2>/dev/null + if test "$?" = 0 ; then + ./dummy + case "$?" in + 7) + UNAME_MACHINE="alpha" + ;; + 15) + UNAME_MACHINE="alphaev5" + ;; + 14) + UNAME_MACHINE="alphaev56" + ;; + 10) + UNAME_MACHINE="alphapca56" + ;; + 16) + UNAME_MACHINE="alphaev6" + ;; + esac + fi + rm -f dummy.s dummy + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr [[A-Z]] [[a-z]]` + exit 0 ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit 0 ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-cbm-sysv4 + exit 0;; + amiga:NetBSD:*:*) + echo m68k-cbm-netbsd${UNAME_RELEASE} + exit 0 ;; + amiga:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + arc64:OpenBSD:*:*) + echo mips64el-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + arc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + hkmips:OpenBSD:*:*) + echo mips-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + pmax:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sgi:OpenBSD:*:*) + echo mips-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + wgrisc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit 0;; + arm32:NetBSD:*:*) + echo arm-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + exit 0 ;; + SR2?01:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit 0;; + Pyramid*:OSx*:*:*|MIS*: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 0 ;; + NILE:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit 0 ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + i86pc:SunOS:5.*:*) + echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + 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 0 ;; + 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 0 ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit 0 ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(head -1 /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 0 ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit 0 ;; + atari*:NetBSD:*:*) + echo m68k-atari-netbsd${UNAME_RELEASE} + exit 0 ;; + atari*:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sun3*:NetBSD:*:*) + echo m68k-sun-netbsd${UNAME_RELEASE} + exit 0 ;; + sun3*:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mac68k:NetBSD:*:*) + echo m68k-apple-netbsd${UNAME_RELEASE} + exit 0 ;; + mac68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme88k:OpenBSD:*:*) + echo m88k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit 0 ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit 0 ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + 2020:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit 0 ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + sed 's/^ //' << EOF >dummy.c + int main (argc, argv) int argc; char **argv; { + #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-cc} dummy.c -o dummy \ + && ./dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ + && rm dummy.c dummy && exit 0 + rm -f dummy.c dummy + echo mips-mips-riscos${UNAME_RELEASE} + exit 0 ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit 0 ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit 0 ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit 0 ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit 0 ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 -o $UNAME_PROCESSOR = mc88110 ] ; then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx \ + -o ${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 0 ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit 0 ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit 0 ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit 0 ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit 0 ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit 0 ;; + ????????: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 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i?86:AIX:*:*) + echo i386-ibm-aix + exit 0 ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + sed 's/^ //' << EOF >dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + ${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0 + rm -f dummy.c dummy + echo rs6000-ibm-aix3.2.5 + 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 0 ;; + *:AIX:*:4) + if /usr/sbin/lsattr -EHl proc0 | 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=4.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit 0 ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit 0 ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit 0 ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC NetBSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit 0 ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit 0 ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit 0 ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit 0 ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit 0 ;; + 9000/[3478]??:HP-UX:*:*) + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/7?? | 9000/8?[1679] ) HP_ARCH=hppa1.1 ;; + 9000/8?? ) HP_ARCH=hppa1.0 ;; + esac + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit 0 ;; + 3050*:HI-UX:*:*) + 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-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0 + rm -f dummy.c dummy + echo unknown-hitachi-hiuxwe2 + exit 0 ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit 0 ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit 0 ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit 0 ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit 0 ;; + i?86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit 0 ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit 0 ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit 0 ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit 0 ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit 0 ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit 0 ;; + CRAY*X-MP:*:*:*) + echo xmp-cray-unicos + exit 0 ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} + exit 0 ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ + exit 0 ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} + exit 0 ;; + CRAY-2:*:*:*) + echo cray2-cray-unicos + exit 0 ;; + F300:UNIX_System_V:*:*) + FUJITSU_SYS=`uname -p | tr [A-Z] [a-z] | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "f300-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit 0 ;; + F301:UNIX_System_V:*:*) + echo f301-fujitsu-uxpv`echo $UNAME_RELEASE | sed 's/ .*//'` + exit 0 ;; + hp3[0-9][05]:NetBSD:*:*) + echo m68k-hp-netbsd${UNAME_RELEASE} + exit 0 ;; + hp300:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + i?86:BSD/386:*:* | *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit 0 ;; + *:FreeBSD:*:*) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit 0 ;; + *:NetBSD:*:*) + echo ${UNAME_MACHINE}-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + exit 0 ;; + *:OpenBSD:*:*) + echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + exit 0 ;; + i*:CYGWIN*:*) + echo i386-pc-cygwin32 + exit 0 ;; + i*:MINGW*:*) + echo i386-pc-mingw32 + exit 0 ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin32 + exit 0 ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + *:GNU:*:*) + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit 0 ;; + *:Linux:*:*) + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. + ld_help_string=`ld --help 2>&1` + ld_supported_emulations=`echo $ld_help_string \ + | sed -ne '/supported emulations:/!d + s/[ ][ ]*/ /g + s/.*supported emulations: *// + s/ .*// + p'` + case "$ld_supported_emulations" in + i?86linux) echo "${UNAME_MACHINE}-pc-linux-gnuaout" ; exit 0 ;; + i?86coff) echo "${UNAME_MACHINE}-pc-linux-gnucoff" ; exit 0 ;; + sparclinux) echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;; + m68klinux) echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;; + elf32ppc) echo "powerpc-unknown-linux-gnu" ; exit 0 ;; + esac + + if test "${UNAME_MACHINE}" = "alpha" ; then + sed 's/^ //' <dummy.s + .globl main + .ent main + main: + .frame \$30,0,\$26,0 + .prologue 0 + .long 0x47e03d80 # implver $0 + lda \$2,259 + .long 0x47e20c21 # amask $2,$1 + srl \$1,8,\$2 + sll \$2,2,\$2 + sll \$0,3,\$0 + addl \$1,\$0,\$0 + addl \$2,\$0,\$0 + ret \$31,(\$26),1 + .end main +EOF + LIBC="" + ${CC-cc} dummy.s -o dummy 2>/dev/null + if test "$?" = 0 ; then + ./dummy + case "$?" in + 7) + UNAME_MACHINE="alpha" + ;; + 15) + UNAME_MACHINE="alphaev5" + ;; + 14) + UNAME_MACHINE="alphaev56" + ;; + 10) + UNAME_MACHINE="alphapca56" + ;; + 16) + UNAME_MACHINE="alphaev6" + ;; + esac + + objdump --private-headers dummy | \ + grep ld.so.1 > /dev/null + if test "$?" = 0 ; then + LIBC="libc1" + fi + fi + rm -f dummy.s dummy + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} ; exit 0 + elif test "${UNAME_MACHINE}" = "mips" ; then + cat >dummy.c </dev/null && ./dummy "${UNAME_MACHINE}" && rm dummy.c dummy && exit 0 + rm -f dummy.c dummy + else + # Either a pre-BFD a.out linker (linux-gnuoldld) + # or one that does not give us useful --help. + # GCC wants to distinguish between linux-gnuoldld and linux-gnuaout. + # If ld does not provide *any* "supported emulations:" + # that means it is gnuoldld. + echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations:" + test $? != 0 && echo "${UNAME_MACHINE}-pc-linux-gnuoldld" && exit 0 + + case "${UNAME_MACHINE}" in + i?86) + VENDOR=pc; + ;; + *) + VENDOR=unknown; + ;; + esac + # Determine whether the default compiler is a.out or elf + cat >dummy.c < +main(argc, argv) + int argc; + char *argv[]; +{ +#ifdef __ELF__ +# ifdef __GLIBC__ +# if __GLIBC__ >= 2 + printf ("%s-${VENDOR}-linux-gnu\n", argv[1]); +# else + printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]); +# endif +# else + printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]); +# endif +#else + printf ("%s-${VENDOR}-linux-gnuaout\n", argv[1]); +#endif + return 0; +} +EOF + ${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy "${UNAME_MACHINE}" && rm dummy.c dummy && exit 0 + rm -f dummy.c dummy + fi ;; +# 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. + i?86:DYNIX/ptx:4*:*) + echo i386-sequent-sysv4 + exit 0 ;; + 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 0 ;; + i?86:*:4.*:* | i?86:SYSTEM_V:4.*:*) + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_RELEASE} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE} + fi + exit 0 ;; + 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|egrep Release|sed -e 's/.*= //')` + (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit 0 ;; + pc:*:*:*) + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i386. + echo i386-pc-msdosdjgpp + exit 0 ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit 0 ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit 0 ;; + 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 0 ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit 0 ;; + M68*:*:R3V[567]*:*) + test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; + 3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*: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 0 + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4 && exit 0 ;; + m68*:LynxOS:2.*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit 0 ;; + i?86:LynxOS:2.*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + rs6000:LynxOS:2.*:* | PowerPC:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit 0 ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + *: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 0 ;; + PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit 0 ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit 0 ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit 0 ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit 0 ;; + news*:NEWS-OS:*:6*) + echo mips-sony-newsos6 + exit 0 ;; + R3000:*System_V*:*:* | R4000:UNIX_SYSV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit 0 ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +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"); 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`; + printf ("%s-next-nextstep%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) + printf ("vax-dec-bsd\n"); exit (0); +#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-cc} dummy.c -o dummy 2>/dev/null && ./dummy && rm dummy.c dummy && exit 0 +rm -f dummy.c dummy + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } + +# 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 0 ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + c34*) + echo c34-convex-bsd + exit 0 ;; + c38*) + echo c38-convex-bsd + exit 0 ;; + c4*) + echo c4-convex-bsd + exit 0 ;; + esac +fi + +#echo '(Unable to guess system type)' 1>&2 + +exit 1 diff --git a/lc-continuity/mk4/modimage/jpeg-6b/config.sub b/lc-continuity/mk4/modimage/jpeg-6b/config.sub new file mode 100644 index 0000000000000000000000000000000000000000..213a6d47d67831d733d74e11867cd473c7cfb635 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/config.sub @@ -0,0 +1,954 @@ +#! /bin/sh +# Configuration validation subroutine script, version 1.1. +# Copyright (C) 1991, 92, 93, 94, 95, 96, 1997 Free Software Foundation, Inc. +# 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., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, 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. + +# 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. + +# 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. + +if [ x$1 = x ] +then + echo Configuration name missing. 1>&2 + echo "Usage: $0 CPU-MFR-OPSYS" 1>&2 + echo "or $0 ALIAS" 1>&2 + echo where ALIAS is a recognized configuration type. 1>&2 + exit 1 +fi + +# First pass through any local machine types. +case $1 in + *local*) + echo $1 + exit 0 + ;; + *) + ;; +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 + linux-gnu*) + 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) + os= + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -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/'` + ;; + -sco*) + os=-sco3.2v2 + 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 + ;; +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. + tahoe | i860 | m32r | m68k | m68000 | m88k | ns32k | arc | arm \ + | arme[lb] | pyramid | mn10200 | mn10300 \ + | tron | a29k | 580 | i960 | h8300 | hppa | hppa1.0 | hppa1.1 \ + | alpha | alphaev5 | alphaev56 | we32k | ns16k | clipper \ + | i370 | sh | powerpc | powerpcle | 1750a | dsp16xx | pdp11 \ + | mips64 | mipsel | mips64el | mips64orion | mips64orionel \ + | mipstx39 | mipstx39el \ + | sparc | sparclet | sparclite | sparc64 | v850) + basic_machine=$basic_machine-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[3456]86) + 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. + vax-* | tahoe-* | i[3456]86-* | i860-* | m32r-* | m68k-* | m68000-* \ + | m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | arm-* | c[123]* \ + | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \ + | power-* | none-* | 580-* | cray2-* | h8300-* | i960-* \ + | xmp-* | ymp-* | hppa-* | hppa1.0-* | hppa1.1-* \ + | alpha-* | alphaev5-* | alphaev56-* | we32k-* | cydra-* \ + | ns16k-* | pn-* | np1-* | xps100-* | clipper-* | orion-* \ + | sparclite-* | pdp11-* | sh-* | powerpc-* | powerpcle-* \ + | sparc64-* | mips64-* | mipsel-* \ + | mips64el-* | mips64orion-* | mips64orionel-* \ + | mipstx39-* | mipstx39el-* \ + | f301-*) + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-cbm + ;; + amigaos | amigados) + basic_machine=m68k-cbm + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-cbm + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + 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 | ymp) + basic_machine=ymp-cray + os=-unicos + ;; + cray2) + basic_machine=cray2-cray + os=-unicos + ;; + [ctj]90-cray) + basic_machine=c90-cray + os=-unicos + ;; + crds | unos) + basic_machine=m68k-crds + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + 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 + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-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 + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k7[0-9][0-9] | hp7[0-9][0-9] | hp9k8[0-9]7 | hp8[0-9]7) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + os=-mvs + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i[3456]86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i[3456]86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i[3456]86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i[3456]86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + miniframe) + basic_machine=m68000-convergent + ;; + mipsel*-linux*) + basic_machine=mipsel-unknown + os=-linux-gnu + ;; + mips*-linux*) + basic_machine=mips-unknown + os=-linux-gnu + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + 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 + ;; + 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 + ;; + np1) + basic_machine=np1-gould + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pentium | p5) + basic_machine=i586-intel + ;; + pentiumpro | p6) + basic_machine=i686-intel + ;; + pentium-* | p5-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + k5) + # We don't have specific support for AMD's K5 yet, so just call it a Pentium + basic_machine=i586-amd + ;; + nexen) + # We don't have specific support for Nexgen yet, so just call it a Pentium + basic_machine=i586-nexgen + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=rs6000-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/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + 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 + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + 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 + ;; + xmp) + basic_machine=xmp-cray + os=-unicos + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + 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. + mips) + if [ x$os = x-linux-gnu ]; then + basic_machine=mips-unknown + else + basic_machine=mips-mips + fi + ;; + romp) + basic_machine=romp-ibm + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sparc) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + *) + 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. + -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* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ + | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -cygwin32* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -uxpv*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -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|'` + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -ctix* | -uts*) + os=-sysv + ;; + -ns2 ) + os=-nextstep2 + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -xenix) + os=-xenix + ;; + -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 + *-acorn) + os=-riscix1.2 + ;; + arm*-semi) + os=-aout + ;; + 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 + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-ibm) + os=-aix + ;; + *-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 + ;; + f301-fujitsu) + os=-uxpv + ;; + *) + 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 + ;; + -aix*) + vendor=ibm + ;; + -hpux*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -vxsim* | -vxworks*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os diff --git a/lc-continuity/mk4/modimage/jpeg-6b/configure b/lc-continuity/mk4/modimage/jpeg-6b/configure new file mode 100644 index 0000000000000000000000000000000000000000..35c9db5cadcf2b0b7e98ce8ad51a29ec55616fd0 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/configure @@ -0,0 +1,2011 @@ +#! /bin/sh + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.12 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: +ac_help="$ac_help + --enable-shared build shared library using GNU libtool" +ac_help="$ac_help + --enable-static build static library using GNU libtool" +ac_help="$ac_help + --enable-maxmem[=N] enable use of temp files, set max mem usage to N MB" +ac_help="$ac_help +" + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 + +ac_prev= +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=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -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 ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$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" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$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) + # 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 << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$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" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + 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) + 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" ;; + + -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 ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.12" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=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" ;; + + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *=*) + varname=`echo "$ac_option"|sed -e 's/=.*//'` + # Reject names that aren't valid shell variable names. + if test -n "`echo $varname| sed 's/[a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $varname: invalid shell variable name" 1>&2; exit 1; } + fi + val="`echo "$ac_option"|sed 's/[^=]*=//'`" + test -n "$verbose" && echo " setting shell variable $varname to $val" + eval "$varname='$val'" + eval "export $varname" ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=jcmaster.c + +# 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 its parent. + ac_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + 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 + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + + + +# Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:538: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="gcc" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +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 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:567: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + ac_prog_rejected=no + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + break + fi + done + IFS="$ac_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 $# -gt 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 + set dummy "$ac_dir/$ac_word" "$@" + shift + ac_cv_prog_CC="$@" + fi +fi +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } +fi + +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:615: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + ac_cv_prog_cc_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cc_cross=no + else + ac_cv_prog_cc_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cc_works=no +fi +rm -fr conftest* + +echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 +if test $ac_cv_prog_cc_works = no; then + { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:649: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 +cross_compiling=$ac_cv_prog_cc_cross + +echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 +echo "configure:654: checking whether we are using GNU C" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gcc=yes +else + ac_cv_prog_gcc=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gcc" 1>&6 + +if test $ac_cv_prog_gcc = yes; then + GCC=yes + test "${CFLAGS+set}" = set || CFLAGS="-O2" +else + GCC= + test "${CFLAGS+set}" = set || CFLAGS="-O" +fi + +echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 +echo "configure:681: checking how to run the C preprocessor" >&5 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then +if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # This must be in double quotes, not single quotes, because CPP may get + # substituted into the Makefile and "${CC-cc}" will confuse make. + CPP="${CC-cc} -E" + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:702: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -E -traditional-cpp" + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:719: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP=/lib/cpp +fi +rm -f conftest* +fi +rm -f conftest* + ac_cv_prog_CPP="$CPP" +fi + CPP="$ac_cv_prog_CPP" +else + ac_cv_prog_CPP="$CPP" +fi +echo "$ac_t""$CPP" 1>&6 + +echo $ac_n "checking for function prototypes""... $ac_c" 1>&6 +echo "configure:742: checking for function prototypes" >&5 +if eval "test \"`echo '$''{'ijg_cv_have_prototypes'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ijg_cv_have_prototypes=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ijg_cv_have_prototypes=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ijg_cv_have_prototypes" 1>&6 +if test $ijg_cv_have_prototypes = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_PROTOTYPES +EOF + +else + echo Your compiler does not seem to know about function prototypes. + echo Perhaps it needs a special switch to enable ANSI C mode. + echo If so, we recommend running configure like this: + echo " ./configure CC='cc -switch'" + echo where -switch is the proper switch. +fi +ac_safe=`echo "stddef.h" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for stddef.h""... $ac_c" 1>&6 +echo "configure:792: checking for stddef.h" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:802: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define HAVE_STDDEF_H +EOF + +else + echo "$ac_t""no" 1>&6 +fi + +ac_safe=`echo "stdlib.h" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for stdlib.h""... $ac_c" 1>&6 +echo "configure:828: checking for stdlib.h" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:838: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define HAVE_STDLIB_H +EOF + +else + echo "$ac_t""no" 1>&6 +fi + +ac_safe=`echo "string.h" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for string.h""... $ac_c" 1>&6 +echo "configure:864: checking for string.h" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:874: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +cat >> confdefs.h <<\EOF +#define NEED_BSD_STRINGS +EOF + +fi + +echo $ac_n "checking for size_t""... $ac_c" 1>&6 +echo "configure:900: checking for size_t" >&5 +cat > conftest.$ac_ext < +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#ifdef NEED_BSD_STRINGS +#include +#else +#include +#endif +typedef size_t my_size_t; + +int main() { + my_size_t foovar; +; return 0; } +EOF +if { (eval echo configure:923: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ijg_size_t_ok=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ijg_size_t_ok="not ANSI, perhaps it is in sys/types.h" +fi +rm -f conftest* +echo "$ac_t""$ijg_size_t_ok" 1>&6 +if test "$ijg_size_t_ok" != yes; then +ac_safe=`echo "sys/types.h" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for sys/types.h""... $ac_c" 1>&6 +echo "configure:937: checking for sys/types.h" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:947: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define NEED_SYS_TYPES_H +EOF + +cat > conftest.$ac_ext < +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "size_t" >/dev/null 2>&1; then + rm -rf conftest* + ijg_size_t_ok="size_t is in sys/types.h" +else + rm -rf conftest* + ijg_size_t_ok=no +fi +rm -f conftest* + +else + echo "$ac_t""no" 1>&6 +ijg_size_t_ok=no +fi + +echo "$ac_t""$ijg_size_t_ok" 1>&6 +if test "$ijg_size_t_ok" = no; then + echo Type size_t is not defined in any of the usual places. + echo Try putting '"typedef unsigned int size_t;"' in jconfig.h. +fi +fi +echo $ac_n "checking for type unsigned char""... $ac_c" 1>&6 +echo "configure:994: checking for type unsigned char" >&5 +cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + echo "$ac_t""yes" 1>&6 +cat >> confdefs.h <<\EOF +#define HAVE_UNSIGNED_CHAR +EOF + +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + echo "$ac_t""no" 1>&6 +fi +rm -f conftest* +echo $ac_n "checking for type unsigned short""... $ac_c" 1>&6 +echo "configure:1018: checking for type unsigned short" >&5 +cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + echo "$ac_t""yes" 1>&6 +cat >> confdefs.h <<\EOF +#define HAVE_UNSIGNED_SHORT +EOF + +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + echo "$ac_t""no" 1>&6 +fi +rm -f conftest* +echo $ac_n "checking for type void""... $ac_c" 1>&6 +echo "configure:1042: checking for type void" >&5 +cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + echo "$ac_t""yes" 1>&6 +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + echo "$ac_t""no" 1>&6 +cat >> confdefs.h <<\EOF +#define void char +EOF + +fi +rm -f conftest* + +echo $ac_n "checking for working const""... $ac_c" 1>&6 +echo "configure:1088: checking for working const" >&5 +if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <j = 5; +} +{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; +} + +; return 0; } +EOF +if { (eval echo configure:1142: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_c_const=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_c_const=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_c_const" 1>&6 +if test $ac_cv_c_const = no; then + cat >> confdefs.h <<\EOF +#define const +EOF + +fi + +echo $ac_n "checking for inline""... $ac_c" 1>&6 +echo "configure:1163: checking for inline" >&5 +ijg_cv_inline="" +cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ijg_cv_inline="__inline__" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ijg_cv_inline="__inline" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ijg_cv_inline="inline" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 +fi +rm -f conftest* +fi +rm -f conftest* +fi +rm -f conftest* +echo "$ac_t""$ijg_cv_inline" 1>&6 +cat >> confdefs.h <&6 +echo "configure:1224: checking for broken incomplete types" >&5 +cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + echo "$ac_t""ok" 1>&6 +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + echo "$ac_t""broken" 1>&6 +cat >> confdefs.h <<\EOF +#define INCOMPLETE_TYPES_BROKEN +EOF + +fi +rm -f conftest* +echo $ac_n "checking for short external names""... $ac_c" 1>&6 +echo "configure:1248: checking for short external names" >&5 +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + echo "$ac_t""ok" 1>&6 +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + echo "$ac_t""short" 1>&6 +cat >> confdefs.h <<\EOF +#define NEED_SHORT_EXTERNAL_NAMES +EOF + +fi +rm -f conftest* +echo $ac_n "checking to see if char is signed""... $ac_c" 1>&6 +echo "configure:1275: checking to see if char is signed" >&5 +if test "$cross_compiling" = yes; then + echo Assuming that char is signed on target machine. +echo If it is unsigned, this will be a little bit inefficient. + +else + cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then + echo "$ac_t""no" 1>&6 +cat >> confdefs.h <<\EOF +#define CHAR_IS_UNSIGNED +EOF + +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + echo "$ac_t""yes" 1>&6 +fi +rm -fr conftest* +fi + +echo $ac_n "checking to see if right shift is signed""... $ac_c" 1>&6 +echo "configure:1323: checking to see if right shift is signed" >&5 +if test "$cross_compiling" = yes; then + echo "$ac_t""Assuming that right shift is signed on target machine." 1>&6 +else + cat > conftest.$ac_ext <> 4; + + if (res == -0x7F7E80CL) { /* expected result for signed shift */ + return 1; /* right shift is signed */ + } + /* see if unsigned-shift hack will fix it. */ + /* we can't just test exact value since it depends on width of long... */ + res |= (~0L) << (32-4); + if (res == -0x7F7E80CL) { /* expected result now? */ + return 0; /* right shift is unsigned */ + } + printf("Right shift isn't acting as I expect it to.\n"); + printf("I fear the JPEG software will not work at all.\n\n"); + return 0; /* try it with unsigned anyway */ +} +main() { + exit(is_shifting_signed(-0x7F7E80B1L)); +} +EOF +if { (eval echo configure:1358: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then + echo "$ac_t""no" 1>&6 +cat >> confdefs.h <<\EOF +#define RIGHT_SHIFT_IS_UNSIGNED +EOF + +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + echo "$ac_t""yes" 1>&6 +fi +rm -fr conftest* +fi + +echo $ac_n "checking to see if fopen accepts b spec""... $ac_c" 1>&6 +echo "configure:1375: checking to see if fopen accepts b spec" >&5 +if test "$cross_compiling" = yes; then + echo "$ac_t""Assuming that it does." 1>&6 +else + cat > conftest.$ac_ext < +main() { + if (fopen("conftestdata", "wb") != NULL) + exit(0); + exit(1); +} +EOF +if { (eval echo configure:1390: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then + echo "$ac_t""yes" 1>&6 +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + echo "$ac_t""no" 1>&6 +cat >> confdefs.h <<\EOF +#define DONT_USE_B_MODE +EOF + +fi +rm -fr conftest* +fi + +ac_aux_dir= +for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; } +fi +ac_config_guess=$ac_aux_dir/config.guess +ac_config_sub=$ac_aux_dir/config.sub +ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 +echo "configure:1436: checking for a BSD compatible install" >&5 +if test -z "$INSTALL"; then +if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + # Account for people who put trailing slashes in PATH elements. + case "$ac_dir/" in + /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + for ac_prog in ginstall installbsd scoinst install; do + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + # OSF/1 installbsd also uses dspmsg, but is usable. + : + else + ac_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + done + ;; + esac + done + IFS="$ac_save_IFS" + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL="$ac_cv_path_install" + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL="$ac_install_sh" + fi +fi +echo "$ac_t""$INSTALL" 1>&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +# Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1488: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_RANLIB="ranlib" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":" +fi +fi +RANLIB="$ac_cv_prog_RANLIB" +if test -n "$RANLIB"; then + echo "$ac_t""$RANLIB" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + +# Decide whether to use libtool, +# and if so whether to build shared, static, or both flavors of library. +LTSHARED="no" +# Check whether --enable-shared or --disable-shared was given. +if test "${enable_shared+set}" = set; then + enableval="$enable_shared" + LTSHARED="$enableval" +fi + +LTSTATIC="no" +# Check whether --enable-static or --disable-static was given. +if test "${enable_static+set}" = set; then + enableval="$enable_static" + LTSTATIC="$enableval" +fi + +if test "x$LTSHARED" != xno -o "x$LTSTATIC" != xno; then + USELIBTOOL="yes" + LIBTOOL="./libtool" + O="lo" + A="la" + LN='$(LIBTOOL) --mode=link $(CC)' + INSTALL_LIB='$(LIBTOOL) --mode=install ${INSTALL}' + INSTALL_PROGRAM="\$(LIBTOOL) --mode=install $INSTALL_PROGRAM" +else + USELIBTOOL="no" + LIBTOOL="" + O="o" + A="a" + LN='$(CC)' + INSTALL_LIB="$INSTALL_DATA" +fi + + + + + + +# Configure libtool if needed. +if test $USELIBTOOL = yes; then + disable_shared= + disable_static= + if test "x$LTSHARED" = xno; then + disable_shared="--disable-shared" + fi + if test "x$LTSTATIC" = xno; then + disable_static="--disable-static" + fi + $srcdir/ltconfig $disable_shared $disable_static $srcdir/ltmain.sh +fi + +# Select memory manager depending on user input. +# If no "-enable-maxmem", use jmemnobs +MEMORYMGR='jmemnobs.$(O)' +MAXMEM="no" +# Check whether --enable-maxmem or --disable-maxmem was given. +if test "${enable_maxmem+set}" = set; then + enableval="$enable_maxmem" + MAXMEM="$enableval" +fi + +# support --with-maxmem for backwards compatibility with IJG V5. +# Check whether --with-maxmem or --without-maxmem was given. +if test "${with_maxmem+set}" = set; then + withval="$with_maxmem" + MAXMEM="$withval" +fi + +if test "x$MAXMEM" = xyes; then + MAXMEM=1 +fi +if test "x$MAXMEM" != xno; then + if test -n "`echo $MAXMEM | sed 's/[0-9]//g'`"; then + { echo "configure: error: non-numeric argument to --enable-maxmem" 1>&2; exit 1; } + fi + DEFAULTMAXMEM=`expr $MAXMEM \* 1048576` +cat >> confdefs.h <&6 +echo "configure:1596: checking for 'tmpfile()'" >&5 +cat > conftest.$ac_ext < +int main() { + FILE * tfile = tmpfile(); +; return 0; } +EOF +if { (eval echo configure:1605: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + echo "$ac_t""yes" 1>&6 +MEMORYMGR='jmemansi.$(O)' +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + echo "$ac_t""no" 1>&6 +MEMORYMGR='jmemname.$(O)' +cat >> confdefs.h <<\EOF +#define NEED_SIGNAL_CATCHER +EOF + +echo $ac_n "checking for 'mktemp()'""... $ac_c" 1>&6 +echo "configure:1620: checking for 'mktemp()'" >&5 +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + echo "$ac_t""yes" 1>&6 +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + echo "$ac_t""no" 1>&6 +cat >> confdefs.h <<\EOF +#define NO_MKTEMP +EOF + +fi +rm -f conftest* +fi +rm -f conftest* +fi + + +# Extract the library version ID from jpeglib.h. +echo $ac_n "checking libjpeg version number""... $ac_c" 1>&6 +echo "configure:1650: checking libjpeg version number" >&5 +JPEG_LIB_VERSION=`sed -e '/^#define JPEG_LIB_VERSION/!d' -e 's/^[^0-9]*\([0-9][0-9]*\).*$/\1/' $srcdir/jpeglib.h` +echo "$ac_t""$JPEG_LIB_VERSION" 1>&6 + + +# Prepare to massage makefile.cfg correctly. +if test $ijg_cv_have_prototypes = yes; then + A2K_DEPS="" + COM_A2K="# " +else + A2K_DEPS="ansi2knr" + COM_A2K="" +fi + + +# ansi2knr needs -DBSD if string.h is missing +if test $ac_cv_header_string_h = no; then + ANSI2KNRFLAGS="-DBSD" +else + ANSI2KNRFLAGS="" +fi + +# Substitutions to enable or disable libtool-related stuff +if test $USELIBTOOL = yes -a $ijg_cv_have_prototypes = yes; then + COM_LT="" +else + COM_LT="# " +fi + +if test "x$LTSHARED" != xno; then + FORCE_INSTALL_LIB="install-lib" +else + FORCE_INSTALL_LIB="" +fi + +# Set up -I directives +if test "x$srcdir" = x.; then + INCLUDEFLAGS='-I$(srcdir)' +else + INCLUDEFLAGS='-I. -I$(srcdir)' +fi + +trap '' 1 2 15 + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +DEFS=-DHAVE_CONFIG_H + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS </dev/null | sed 1q`: +# +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version 2.12" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir +ac_given_INSTALL="$INSTALL" + +trap 'rm -fr `echo "Makefile:makefile.cfg jconfig.h:jconfig.cfg" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +EOF +cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF +$ac_vpsub +$extrasub +s%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%g +s%@DEFS@%$DEFS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@LIBS@%$LIBS%g +s%@exec_prefix@%$exec_prefix%g +s%@prefix@%$prefix%g +s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g +s%@CC@%$CC%g +s%@CPP@%$CPP%g +s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g +s%@INSTALL_DATA@%$INSTALL_DATA%g +s%@RANLIB@%$RANLIB%g +s%@LIBTOOL@%$LIBTOOL%g +s%@O@%$O%g +s%@A@%$A%g +s%@LN@%$LN%g +s%@INSTALL_LIB@%$INSTALL_LIB%g +s%@MEMORYMGR@%$MEMORYMGR%g +s%@JPEG_LIB_VERSION@%$JPEG_LIB_VERSION%g +s%@A2K_DEPS@%$A2K_DEPS%g +s%@COM_A2K@%$COM_A2K%g +s%@ANSI2KNRFLAGS@%$ANSI2KNRFLAGS%g +s%@COM_LT@%$COM_LT%g +s%@FORCE_INSTALL_LIB@%$FORCE_INSTALL_LIB%g +s%@INCLUDEFLAGS@%$INCLUDEFLAGS%g + +CEOF +EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + case "$ac_given_INSTALL" in + [/$]*) INSTALL="$ac_given_INSTALL" ;; + *) INSTALL="$ac_dots$ac_given_INSTALL" ;; + esac + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +s%@INSTALL@%$INSTALL%g +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +fi; done +rm -f conftest.s* + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='\([ ][ ]*\)[^ ]*%\1#\2' +ac_dC='\3' +ac_dD='%g' +# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE". +ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='\([ ]\)%\1#\2define\3' +ac_uC=' ' +ac_uD='\4%g' +# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_eB='$%\1#\2define\3' +ac_eC=' ' +ac_eD='%g' + +if test "${CONFIG_HEADERS+set}" != set; then +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +fi +for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + echo creating $ac_file + + rm -f conftest.frag conftest.in conftest.out + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + cat $ac_file_inputs > conftest.in + +EOF + +# Transform confdefs.h into a sed script conftest.vals that substitutes +# the proper values into config.h.in to produce config.h. And first: +# Protect against being on the right side of a sed subst in config.status. +# Protect against being in an unquoted here document in config.status. +rm -f conftest.vals +cat > conftest.hdr <<\EOF +s/[\\&%]/\\&/g +s%[\\$`]%\\&%g +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp +s%ac_d%ac_u%gp +s%ac_u%ac_e%gp +EOF +sed -n -f conftest.hdr confdefs.h > conftest.vals +rm -f conftest.hdr + +# This sed command replaces #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +cat >> conftest.vals <<\EOF +EOF + +# Break up conftest.vals because some shells have a limit on +# the size of here documents, and old seds have small limits too. + +rm -f conftest.tail +while : +do + ac_lines=`grep -c . conftest.vals` + # grep -c gives empty output for an empty file on some AIX systems. + if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi + # Write a limited-size here document to conftest.frag. + echo ' cat > conftest.frag <> $CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS + echo 'CEOF + sed -f conftest.frag conftest.in > conftest.out + rm -f conftest.in + mv conftest.out conftest.in +' >> $CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail + rm -f conftest.vals + mv conftest.tail conftest.vals +done +rm -f conftest.vals + +cat >> $CONFIG_STATUS <<\EOF + rm -f conftest.frag conftest.h + echo "/* $ac_file. Generated automatically by configure. */" > conftest.h + cat conftest.in >> conftest.h + rm -f conftest.in + if cmp -s $ac_file conftest.h 2>/dev/null; then + echo "$ac_file is unchanged" + rm -f conftest.h + else + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + fi + rm -f $ac_file + mv conftest.h $ac_file + fi +fi; done + +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF + +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + diff --git a/lc-continuity/mk4/modimage/jpeg-6b/djpeg.1 b/lc-continuity/mk4/modimage/jpeg-6b/djpeg.1 new file mode 100644 index 0000000000000000000000000000000000000000..11beb6a5133ae9c8bcc13e11f8087e064e823441 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/djpeg.1 @@ -0,0 +1,253 @@ +.TH DJPEG 1 "22 August 1997" +.SH NAME +djpeg \- decompress a JPEG file to an image file +.SH SYNOPSIS +.B djpeg +[ +.I options +] +[ +.I filename +] +.LP +.SH DESCRIPTION +.LP +.B djpeg +decompresses the named JPEG file, or the standard input if no file is named, +and produces an image file on the standard output. PBMPLUS (PPM/PGM), BMP, +GIF, Targa, or RLE (Utah Raster Toolkit) output format can be selected. +(RLE is supported only if the URT library is available.) +.SH OPTIONS +All switch names may be abbreviated; for example, +.B \-grayscale +may be written +.B \-gray +or +.BR \-gr . +Most of the "basic" switches can be abbreviated to as little as one letter. +Upper and lower case are equivalent (thus +.B \-BMP +is the same as +.BR \-bmp ). +British spellings are also accepted (e.g., +.BR \-greyscale ), +though for brevity these are not mentioned below. +.PP +The basic switches are: +.TP +.BI \-colors " N" +Reduce image to at most N colors. This reduces the number of colors used in +the output image, so that it can be displayed on a colormapped display or +stored in a colormapped file format. For example, if you have an 8-bit +display, you'd need to reduce to 256 or fewer colors. +.TP +.BI \-quantize " N" +Same as +.BR \-colors . +.B \-colors +is the recommended name, +.B \-quantize +is provided only for backwards compatibility. +.TP +.B \-fast +Select recommended processing options for fast, low quality output. (The +default options are chosen for highest quality output.) Currently, this is +equivalent to \fB\-dct fast \-nosmooth \-onepass \-dither ordered\fR. +.TP +.B \-grayscale +Force gray-scale output even if JPEG file is color. Useful for viewing on +monochrome displays; also, +.B djpeg +runs noticeably faster in this mode. +.TP +.BI \-scale " M/N" +Scale the output image by a factor M/N. Currently the scale factor must be +1/1, 1/2, 1/4, or 1/8. Scaling is handy if the image is larger than your +screen; also, +.B djpeg +runs much faster when scaling down the output. +.TP +.B \-bmp +Select BMP output format (Windows flavor). 8-bit colormapped format is +emitted if +.B \-colors +or +.B \-grayscale +is specified, or if the JPEG file is gray-scale; otherwise, 24-bit full-color +format is emitted. +.TP +.B \-gif +Select GIF output format. Since GIF does not support more than 256 colors, +.B \-colors 256 +is assumed (unless you specify a smaller number of colors). +.TP +.B \-os2 +Select BMP output format (OS/2 1.x flavor). 8-bit colormapped format is +emitted if +.B \-colors +or +.B \-grayscale +is specified, or if the JPEG file is gray-scale; otherwise, 24-bit full-color +format is emitted. +.TP +.B \-pnm +Select PBMPLUS (PPM/PGM) output format (this is the default format). +PGM is emitted if the JPEG file is gray-scale or if +.B \-grayscale +is specified; otherwise PPM is emitted. +.TP +.B \-rle +Select RLE output format. (Requires URT library.) +.TP +.B \-targa +Select Targa output format. Gray-scale format is emitted if the JPEG file is +gray-scale or if +.B \-grayscale +is specified; otherwise, colormapped format is emitted if +.B \-colors +is specified; otherwise, 24-bit full-color format is emitted. +.PP +Switches for advanced users: +.TP +.B \-dct int +Use integer DCT method (default). +.TP +.B \-dct fast +Use fast integer DCT (less accurate). +.TP +.B \-dct float +Use floating-point DCT method. +The float method is very slightly more accurate than the int method, but is +much slower unless your machine has very fast floating-point hardware. Also +note that results of the floating-point method may vary slightly across +machines, while the integer methods should give the same results everywhere. +The fast integer method is much less accurate than the other two. +.TP +.B \-dither fs +Use Floyd-Steinberg dithering in color quantization. +.TP +.B \-dither ordered +Use ordered dithering in color quantization. +.TP +.B \-dither none +Do not use dithering in color quantization. +By default, Floyd-Steinberg dithering is applied when quantizing colors; this +is slow but usually produces the best results. Ordered dither is a compromise +between speed and quality; no dithering is fast but usually looks awful. Note +that these switches have no effect unless color quantization is being done. +Ordered dither is only available in +.B \-onepass +mode. +.TP +.BI \-map " file" +Quantize to the colors used in the specified image file. This is useful for +producing multiple files with identical color maps, or for forcing a +predefined set of colors to be used. The +.I file +must be a GIF or PPM file. This option overrides +.B \-colors +and +.BR \-onepass . +.TP +.B \-nosmooth +Use a faster, lower-quality upsampling routine. +.TP +.B \-onepass +Use one-pass instead of two-pass color quantization. The one-pass method is +faster and needs less memory, but it produces a lower-quality image. +.B \-onepass +is ignored unless you also say +.B \-colors +.IR N . +Also, the one-pass method is always used for gray-scale output (the two-pass +method is no improvement then). +.TP +.BI \-maxmemory " N" +Set limit for amount of memory to use in processing large images. Value is +in thousands of bytes, or millions of bytes if "M" is attached to the +number. For example, +.B \-max 4m +selects 4000000 bytes. If more space is needed, temporary files will be used. +.TP +.BI \-outfile " name" +Send output image to the named file, not to standard output. +.TP +.B \-verbose +Enable debug printout. More +.BR \-v 's +give more output. Also, version information is printed at startup. +.TP +.B \-debug +Same as +.BR \-verbose . +.SH EXAMPLES +.LP +This example decompresses the JPEG file foo.jpg, quantizes it to +256 colors, and saves the output in 8-bit BMP format in foo.bmp: +.IP +.B djpeg \-colors 256 \-bmp +.I foo.jpg +.B > +.I foo.bmp +.SH HINTS +To get a quick preview of an image, use the +.B \-grayscale +and/or +.B \-scale +switches. +.B \-grayscale \-scale 1/8 +is the fastest case. +.PP +Several options are available that trade off image quality to gain speed. +.B \-fast +turns on the recommended settings. +.PP +.B \-dct fast +and/or +.B \-nosmooth +gain speed at a small sacrifice in quality. +When producing a color-quantized image, +.B \-onepass \-dither ordered +is fast but much lower quality than the default behavior. +.B \-dither none +may give acceptable results in two-pass mode, but is seldom tolerable in +one-pass mode. +.PP +If you are fortunate enough to have very fast floating point hardware, +\fB\-dct float\fR may be even faster than \fB\-dct fast\fR. But on most +machines \fB\-dct float\fR is slower than \fB\-dct int\fR; in this case it is +not worth using, because its theoretical accuracy advantage is too small to be +significant in practice. +.SH ENVIRONMENT +.TP +.B JPEGMEM +If this environment variable is set, its value is the default memory limit. +The value is specified as described for the +.B \-maxmemory +switch. +.B JPEGMEM +overrides the default value specified when the program was compiled, and +itself is overridden by an explicit +.BR \-maxmemory . +.SH SEE ALSO +.BR cjpeg (1), +.BR jpegtran (1), +.BR rdjpgcom (1), +.BR wrjpgcom (1) +.br +.BR ppm (5), +.BR pgm (5) +.br +Wallace, Gregory K. "The JPEG Still Picture Compression Standard", +Communications of the ACM, April 1991 (vol. 34, no. 4), pp. 30-44. +.SH AUTHOR +Independent JPEG Group +.SH BUGS +Arithmetic coding is not supported for legal reasons. +.PP +To avoid the Unisys LZW patent, +.B djpeg +produces uncompressed GIF files. These are larger than they should be, but +are readable by standard GIF decoders. +.PP +Still not as fast as we'd like. diff --git a/lc-continuity/mk4/modimage/jpeg-6b/djpeg.c b/lc-continuity/mk4/modimage/jpeg-6b/djpeg.c new file mode 100644 index 0000000000000000000000000000000000000000..e099e90aee35fa7e092e3909ee351fe8831ac05c --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/djpeg.c @@ -0,0 +1,616 @@ +/* + * djpeg.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a command-line user interface for the JPEG decompressor. + * It should work on any system with Unix- or MS-DOS-style command lines. + * + * Two different command line styles are permitted, depending on the + * compile-time switch TWO_FILE_COMMANDLINE: + * djpeg [options] inputfile outputfile + * djpeg [options] [inputfile] + * In the second style, output is always to standard output, which you'd + * normally redirect to a file or pipe to some other program. Input is + * either from a named file or from standard input (typically redirected). + * The second style is convenient on Unix but is unhelpful on systems that + * don't support pipes. Also, you MUST use the first style if your system + * doesn't do binary I/O to stdin/stdout. + * To simplify script writing, the "-outfile" switch is provided. The syntax + * djpeg [options] -outfile outputfile inputfile + * works regardless of which command line style is used. + */ + +#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ +#include "jversion.h" /* for version message */ + +#include /* to declare isprint() */ + +#ifdef USE_CCOMMAND /* command-line reader for Macintosh */ +#ifdef __MWERKS__ +#include /* Metrowerks needs this */ +#include /* ... and this */ +#endif +#ifdef THINK_C +#include /* Think declares it here */ +#endif +#endif + + +/* Create the add-on message string table. */ + +#define JMESSAGE(code,string) string , + +static const char * const cdjpeg_message_table[] = { +#include "cderror.h" + NULL +}; + + +/* + * This list defines the known output image formats + * (not all of which need be supported by a given version). + * You can change the default output format by defining DEFAULT_FMT; + * indeed, you had better do so if you undefine PPM_SUPPORTED. + */ + +typedef enum { + FMT_BMP, /* BMP format (Windows flavor) */ + FMT_GIF, /* GIF format */ + FMT_OS2, /* BMP format (OS/2 flavor) */ + FMT_PPM, /* PPM/PGM (PBMPLUS formats) */ + FMT_RLE, /* RLE format */ + FMT_TARGA, /* Targa format */ + FMT_TIFF /* TIFF format */ +} IMAGE_FORMATS; + +#ifndef DEFAULT_FMT /* so can override from CFLAGS in Makefile */ +#define DEFAULT_FMT FMT_PPM +#endif + +static IMAGE_FORMATS requested_fmt; + + +/* + * Argument-parsing code. + * The switch parser is designed to be useful with DOS-style command line + * syntax, ie, intermixed switches and file names, where only the switches + * to the left of a given file name affect processing of that file. + * The main program in this file doesn't actually use this capability... + */ + + +static const char * progname; /* program name for error messages */ +static char * outfilename; /* for -outfile switch */ + + +LOCAL(void) +usage (void) +/* complain about bad command line */ +{ + fprintf(stderr, "usage: %s [switches] ", progname); +#ifdef TWO_FILE_COMMANDLINE + fprintf(stderr, "inputfile outputfile\n"); +#else + fprintf(stderr, "[inputfile]\n"); +#endif + + fprintf(stderr, "Switches (names may be abbreviated):\n"); + fprintf(stderr, " -colors N Reduce image to no more than N colors\n"); + fprintf(stderr, " -fast Fast, low-quality processing\n"); + fprintf(stderr, " -grayscale Force grayscale output\n"); +#ifdef IDCT_SCALING_SUPPORTED + fprintf(stderr, " -scale M/N Scale output image by fraction M/N, eg, 1/8\n"); +#endif +#ifdef BMP_SUPPORTED + fprintf(stderr, " -bmp Select BMP output format (Windows style)%s\n", + (DEFAULT_FMT == FMT_BMP ? " (default)" : "")); +#endif +#ifdef GIF_SUPPORTED + fprintf(stderr, " -gif Select GIF output format%s\n", + (DEFAULT_FMT == FMT_GIF ? " (default)" : "")); +#endif +#ifdef BMP_SUPPORTED + fprintf(stderr, " -os2 Select BMP output format (OS/2 style)%s\n", + (DEFAULT_FMT == FMT_OS2 ? " (default)" : "")); +#endif +#ifdef PPM_SUPPORTED + fprintf(stderr, " -pnm Select PBMPLUS (PPM/PGM) output format%s\n", + (DEFAULT_FMT == FMT_PPM ? " (default)" : "")); +#endif +#ifdef RLE_SUPPORTED + fprintf(stderr, " -rle Select Utah RLE output format%s\n", + (DEFAULT_FMT == FMT_RLE ? " (default)" : "")); +#endif +#ifdef TARGA_SUPPORTED + fprintf(stderr, " -targa Select Targa output format%s\n", + (DEFAULT_FMT == FMT_TARGA ? " (default)" : "")); +#endif + fprintf(stderr, "Switches for advanced users:\n"); +#ifdef DCT_ISLOW_SUPPORTED + fprintf(stderr, " -dct int Use integer DCT method%s\n", + (JDCT_DEFAULT == JDCT_ISLOW ? " (default)" : "")); +#endif +#ifdef DCT_IFAST_SUPPORTED + fprintf(stderr, " -dct fast Use fast integer DCT (less accurate)%s\n", + (JDCT_DEFAULT == JDCT_IFAST ? " (default)" : "")); +#endif +#ifdef DCT_FLOAT_SUPPORTED + fprintf(stderr, " -dct float Use floating-point DCT method%s\n", + (JDCT_DEFAULT == JDCT_FLOAT ? " (default)" : "")); +#endif + fprintf(stderr, " -dither fs Use F-S dithering (default)\n"); + fprintf(stderr, " -dither none Don't use dithering in quantization\n"); + fprintf(stderr, " -dither ordered Use ordered dither (medium speed, quality)\n"); +#ifdef QUANT_2PASS_SUPPORTED + fprintf(stderr, " -map FILE Map to colors used in named image file\n"); +#endif + fprintf(stderr, " -nosmooth Don't use high-quality upsampling\n"); +#ifdef QUANT_1PASS_SUPPORTED + fprintf(stderr, " -onepass Use 1-pass quantization (fast, low quality)\n"); +#endif + fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n"); + fprintf(stderr, " -outfile name Specify name for output file\n"); + fprintf(stderr, " -verbose or -debug Emit debug output\n"); + exit(EXIT_FAILURE); +} + + +LOCAL(int) +parse_switches (j_decompress_ptr cinfo, int argc, char **argv, + int last_file_arg_seen, boolean for_real) +/* Parse optional switches. + * Returns argv[] index of first file-name argument (== argc if none). + * Any file names with indexes <= last_file_arg_seen are ignored; + * they have presumably been processed in a previous iteration. + * (Pass 0 for last_file_arg_seen on the first or only iteration.) + * for_real is FALSE on the first (dummy) pass; we may skip any expensive + * processing. + */ +{ + int argn; + char * arg; + + /* Set up default JPEG parameters. */ + requested_fmt = DEFAULT_FMT; /* set default output file format */ + outfilename = NULL; + cinfo->err->trace_level = 0; + + /* Scan command line options, adjust parameters */ + + for (argn = 1; argn < argc; argn++) { + arg = argv[argn]; + if (*arg != '-') { + /* Not a switch, must be a file name argument */ + if (argn <= last_file_arg_seen) { + outfilename = NULL; /* -outfile applies to just one input file */ + continue; /* ignore this name if previously processed */ + } + break; /* else done parsing switches */ + } + arg++; /* advance past switch marker character */ + + if (keymatch(arg, "bmp", 1)) { + /* BMP output format. */ + requested_fmt = FMT_BMP; + + } else if (keymatch(arg, "colors", 1) || keymatch(arg, "colours", 1) || + keymatch(arg, "quantize", 1) || keymatch(arg, "quantise", 1)) { + /* Do color quantization. */ + int val; + + if (++argn >= argc) /* advance to next argument */ + usage(); + if (sscanf(argv[argn], "%d", &val) != 1) + usage(); + cinfo->desired_number_of_colors = val; + cinfo->quantize_colors = TRUE; + + } else if (keymatch(arg, "dct", 2)) { + /* Select IDCT algorithm. */ + if (++argn >= argc) /* advance to next argument */ + usage(); + if (keymatch(argv[argn], "int", 1)) { + cinfo->dct_method = JDCT_ISLOW; + } else if (keymatch(argv[argn], "fast", 2)) { + cinfo->dct_method = JDCT_IFAST; + } else if (keymatch(argv[argn], "float", 2)) { + cinfo->dct_method = JDCT_FLOAT; + } else + usage(); + + } else if (keymatch(arg, "dither", 2)) { + /* Select dithering algorithm. */ + if (++argn >= argc) /* advance to next argument */ + usage(); + if (keymatch(argv[argn], "fs", 2)) { + cinfo->dither_mode = JDITHER_FS; + } else if (keymatch(argv[argn], "none", 2)) { + cinfo->dither_mode = JDITHER_NONE; + } else if (keymatch(argv[argn], "ordered", 2)) { + cinfo->dither_mode = JDITHER_ORDERED; + } else + usage(); + + } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) { + /* Enable debug printouts. */ + /* On first -d, print version identification */ + static boolean printed_version = FALSE; + + if (! printed_version) { + fprintf(stderr, "Independent JPEG Group's DJPEG, version %s\n%s\n", + JVERSION, JCOPYRIGHT); + printed_version = TRUE; + } + cinfo->err->trace_level++; + + } else if (keymatch(arg, "fast", 1)) { + /* Select recommended processing options for quick-and-dirty output. */ + cinfo->two_pass_quantize = FALSE; + cinfo->dither_mode = JDITHER_ORDERED; + if (! cinfo->quantize_colors) /* don't override an earlier -colors */ + cinfo->desired_number_of_colors = 216; + cinfo->dct_method = JDCT_FASTEST; + cinfo->do_fancy_upsampling = FALSE; + + } else if (keymatch(arg, "gif", 1)) { + /* GIF output format. */ + requested_fmt = FMT_GIF; + + } else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) { + /* Force monochrome output. */ + cinfo->out_color_space = JCS_GRAYSCALE; + + } else if (keymatch(arg, "map", 3)) { + /* Quantize to a color map taken from an input file. */ + if (++argn >= argc) /* advance to next argument */ + usage(); + if (for_real) { /* too expensive to do twice! */ +#ifdef QUANT_2PASS_SUPPORTED /* otherwise can't quantize to supplied map */ + FILE * mapfile; + + if ((mapfile = fopen(argv[argn], READ_BINARY)) == NULL) { + fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]); + exit(EXIT_FAILURE); + } + read_color_map(cinfo, mapfile); + fclose(mapfile); + cinfo->quantize_colors = TRUE; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } + + } else if (keymatch(arg, "maxmemory", 3)) { + /* Maximum memory in Kb (or Mb with 'm'). */ + long lval; + char ch = 'x'; + + if (++argn >= argc) /* advance to next argument */ + usage(); + if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1) + usage(); + if (ch == 'm' || ch == 'M') + lval *= 1000L; + cinfo->mem->max_memory_to_use = lval * 1000L; + + } else if (keymatch(arg, "nosmooth", 3)) { + /* Suppress fancy upsampling */ + cinfo->do_fancy_upsampling = FALSE; + + } else if (keymatch(arg, "onepass", 3)) { + /* Use fast one-pass quantization. */ + cinfo->two_pass_quantize = FALSE; + + } else if (keymatch(arg, "os2", 3)) { + /* BMP output format (OS/2 flavor). */ + requested_fmt = FMT_OS2; + + } else if (keymatch(arg, "outfile", 4)) { + /* Set output file name. */ + if (++argn >= argc) /* advance to next argument */ + usage(); + outfilename = argv[argn]; /* save it away for later use */ + + } else if (keymatch(arg, "pnm", 1) || keymatch(arg, "ppm", 1)) { + /* PPM/PGM output format. */ + requested_fmt = FMT_PPM; + + } else if (keymatch(arg, "rle", 1)) { + /* RLE output format. */ + requested_fmt = FMT_RLE; + + } else if (keymatch(arg, "scale", 1)) { + /* Scale the output image by a fraction M/N. */ + if (++argn >= argc) /* advance to next argument */ + usage(); + if (sscanf(argv[argn], "%d/%d", + &cinfo->scale_num, &cinfo->scale_denom) != 2) + usage(); + + } else if (keymatch(arg, "targa", 1)) { + /* Targa output format. */ + requested_fmt = FMT_TARGA; + + } else { + usage(); /* bogus switch */ + } + } + + return argn; /* return index of next arg (file name) */ +} + + +/* + * Marker processor for COM and interesting APPn markers. + * This replaces the library's built-in processor, which just skips the marker. + * We want to print out the marker as text, to the extent possible. + * Note this code relies on a non-suspending data source. + */ + +LOCAL(unsigned int) +jpeg_getc (j_decompress_ptr cinfo) +/* Read next byte */ +{ + struct jpeg_source_mgr * datasrc = cinfo->src; + + if (datasrc->bytes_in_buffer == 0) { + if (! (*datasrc->fill_input_buffer) (cinfo)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); + } + datasrc->bytes_in_buffer--; + return GETJOCTET(*datasrc->next_input_byte++); +} + + +METHODDEF(boolean) +print_text_marker (j_decompress_ptr cinfo) +{ + boolean traceit = (cinfo->err->trace_level >= 1); + INT32 length; + unsigned int ch; + unsigned int lastch = 0; + + length = jpeg_getc(cinfo) << 8; + length += jpeg_getc(cinfo); + length -= 2; /* discount the length word itself */ + + if (traceit) { + if (cinfo->unread_marker == JPEG_COM) + fprintf(stderr, "Comment, length %ld:\n", (long) length); + else /* assume it is an APPn otherwise */ + fprintf(stderr, "APP%d, length %ld:\n", + cinfo->unread_marker - JPEG_APP0, (long) length); + } + + while (--length >= 0) { + ch = jpeg_getc(cinfo); + if (traceit) { + /* Emit the character in a readable form. + * Nonprintables are converted to \nnn form, + * while \ is converted to \\. + * Newlines in CR, CR/LF, or LF form will be printed as one newline. + */ + if (ch == '\r') { + fprintf(stderr, "\n"); + } else if (ch == '\n') { + if (lastch != '\r') + fprintf(stderr, "\n"); + } else if (ch == '\\') { + fprintf(stderr, "\\\\"); + } else if (isprint(ch)) { + putc(ch, stderr); + } else { + fprintf(stderr, "\\%03o", ch); + } + lastch = ch; + } + } + + if (traceit) + fprintf(stderr, "\n"); + + return TRUE; +} + + +/* + * The main program. + */ + +int +main (int argc, char **argv) +{ + struct jpeg_decompress_struct cinfo; + struct jpeg_error_mgr jerr; +#ifdef PROGRESS_REPORT + struct cdjpeg_progress_mgr progress; +#endif + int file_index; + djpeg_dest_ptr dest_mgr = NULL; + FILE * input_file; + FILE * output_file; + JDIMENSION num_scanlines; + + /* On Mac, fetch a command line. */ +#ifdef USE_CCOMMAND + argc = ccommand(&argv); +#endif + + progname = argv[0]; + if (progname == NULL || progname[0] == 0) + progname = "djpeg"; /* in case C library doesn't provide it */ + + /* Initialize the JPEG decompression object with default error handling. */ + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_decompress(&cinfo); + /* Add some application-specific error messages (from cderror.h) */ + jerr.addon_message_table = cdjpeg_message_table; + jerr.first_addon_message = JMSG_FIRSTADDONCODE; + jerr.last_addon_message = JMSG_LASTADDONCODE; + + /* Insert custom marker processor for COM and APP12. + * APP12 is used by some digital camera makers for textual info, + * so we provide the ability to display it as text. + * If you like, additional APPn marker types can be selected for display, + * but don't try to override APP0 or APP14 this way (see libjpeg.doc). + */ + jpeg_set_marker_processor(&cinfo, JPEG_COM, print_text_marker); + jpeg_set_marker_processor(&cinfo, JPEG_APP0+12, print_text_marker); + + /* Now safe to enable signal catcher. */ +#ifdef NEED_SIGNAL_CATCHER + enable_signal_catcher((j_common_ptr) &cinfo); +#endif + + /* Scan command line to find file names. */ + /* It is convenient to use just one switch-parsing routine, but the switch + * values read here are ignored; we will rescan the switches after opening + * the input file. + * (Exception: tracing level set here controls verbosity for COM markers + * found during jpeg_read_header...) + */ + + file_index = parse_switches(&cinfo, argc, argv, 0, FALSE); + +#ifdef TWO_FILE_COMMANDLINE + /* Must have either -outfile switch or explicit output file name */ + if (outfilename == NULL) { + if (file_index != argc-2) { + fprintf(stderr, "%s: must name one input and one output file\n", + progname); + usage(); + } + outfilename = argv[file_index+1]; + } else { + if (file_index != argc-1) { + fprintf(stderr, "%s: must name one input and one output file\n", + progname); + usage(); + } + } +#else + /* Unix style: expect zero or one file name */ + if (file_index < argc-1) { + fprintf(stderr, "%s: only one input file\n", progname); + usage(); + } +#endif /* TWO_FILE_COMMANDLINE */ + + /* Open the input file. */ + if (file_index < argc) { + if ((input_file = fopen(argv[file_index], READ_BINARY)) == NULL) { + fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]); + exit(EXIT_FAILURE); + } + } else { + /* default input file is stdin */ + input_file = read_stdin(); + } + + /* Open the output file. */ + if (outfilename != NULL) { + if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) { + fprintf(stderr, "%s: can't open %s\n", progname, outfilename); + exit(EXIT_FAILURE); + } + } else { + /* default output file is stdout */ + output_file = write_stdout(); + } + +#ifdef PROGRESS_REPORT + start_progress_monitor((j_common_ptr) &cinfo, &progress); +#endif + + /* Specify data source for decompression */ + jpeg_stdio_src(&cinfo, input_file); + + /* Read file header, set default decompression parameters */ + (void) jpeg_read_header(&cinfo, TRUE); + + /* Adjust default decompression parameters by re-parsing the options */ + file_index = parse_switches(&cinfo, argc, argv, 0, TRUE); + + /* Initialize the output module now to let it override any crucial + * option settings (for instance, GIF wants to force color quantization). + */ + switch (requested_fmt) { +#ifdef BMP_SUPPORTED + case FMT_BMP: + dest_mgr = jinit_write_bmp(&cinfo, FALSE); + break; + case FMT_OS2: + dest_mgr = jinit_write_bmp(&cinfo, TRUE); + break; +#endif +#ifdef GIF_SUPPORTED + case FMT_GIF: + dest_mgr = jinit_write_gif(&cinfo); + break; +#endif +#ifdef PPM_SUPPORTED + case FMT_PPM: + dest_mgr = jinit_write_ppm(&cinfo); + break; +#endif +#ifdef RLE_SUPPORTED + case FMT_RLE: + dest_mgr = jinit_write_rle(&cinfo); + break; +#endif +#ifdef TARGA_SUPPORTED + case FMT_TARGA: + dest_mgr = jinit_write_targa(&cinfo); + break; +#endif + default: + ERREXIT(&cinfo, JERR_UNSUPPORTED_FORMAT); + break; + } + dest_mgr->output_file = output_file; + + /* Start decompressor */ + (void) jpeg_start_decompress(&cinfo); + + /* Write output file header */ + (*dest_mgr->start_output) (&cinfo, dest_mgr); + + /* Process data */ + while (cinfo.output_scanline < cinfo.output_height) { + num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer, + dest_mgr->buffer_height); + (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines); + } + +#ifdef PROGRESS_REPORT + /* Hack: count final pass as done in case finish_output does an extra pass. + * The library won't have updated completed_passes. + */ + progress.pub.completed_passes = progress.pub.total_passes; +#endif + + /* Finish decompression and release memory. + * I must do it in this order because output module has allocated memory + * of lifespan JPOOL_IMAGE; it needs to finish before releasing memory. + */ + (*dest_mgr->finish_output) (&cinfo, dest_mgr); + (void) jpeg_finish_decompress(&cinfo); + jpeg_destroy_decompress(&cinfo); + + /* Close files, if we opened them */ + if (input_file != stdin) + fclose(input_file); + if (output_file != stdout) + fclose(output_file); + +#ifdef PROGRESS_REPORT + end_progress_monitor((j_common_ptr) &cinfo); +#endif + + /* All done. */ + exit(jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS); + return 0; /* suppress no-return-value warnings */ +} diff --git a/lc-continuity/mk4/modimage/jpeg-6b/example.c b/lc-continuity/mk4/modimage/jpeg-6b/example.c new file mode 100644 index 0000000000000000000000000000000000000000..7fc354f04d9dc3fc22634cc53a9c23fe3e161314 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/example.c @@ -0,0 +1,433 @@ +/* + * example.c + * + * This file illustrates how to use the IJG code as a subroutine library + * to read or write JPEG image files. You should look at this code in + * conjunction with the documentation file libjpeg.doc. + * + * This code will not do anything useful as-is, but it may be helpful as a + * skeleton for constructing routines that call the JPEG library. + * + * We present these routines in the same coding style used in the JPEG code + * (ANSI function definitions, etc); but you are of course free to code your + * routines in a different style if you prefer. + */ + +#include + +/* + * Include file for users of JPEG library. + * You will need to have included system headers that define at least + * the typedefs FILE and size_t before you can include jpeglib.h. + * (stdio.h is sufficient on ANSI-conforming systems.) + * You may also wish to include "jerror.h". + */ + +#include "jpeglib.h" + +/* + * is used for the optional error recovery mechanism shown in + * the second part of the example. + */ + +#include + + + +/******************** JPEG COMPRESSION SAMPLE INTERFACE *******************/ + +/* This half of the example shows how to feed data into the JPEG compressor. + * We present a minimal version that does not worry about refinements such + * as error recovery (the JPEG code will just exit() if it gets an error). + */ + + +/* + * IMAGE DATA FORMATS: + * + * The standard input image format is a rectangular array of pixels, with + * each pixel having the same number of "component" values (color channels). + * Each pixel row is an array of JSAMPLEs (which typically are unsigned chars). + * If you are working with color data, then the color values for each pixel + * must be adjacent in the row; for example, R,G,B,R,G,B,R,G,B,... for 24-bit + * RGB color. + * + * For this example, we'll assume that this data structure matches the way + * our application has stored the image in memory, so we can just pass a + * pointer to our image buffer. In particular, let's say that the image is + * RGB color and is described by: + */ + +extern JSAMPLE * image_buffer; /* Points to large array of R,G,B-order data */ +extern int image_height; /* Number of rows in image */ +extern int image_width; /* Number of columns in image */ + + +/* + * Sample routine for JPEG compression. We assume that the target file name + * and a compression quality factor are passed in. + */ + +GLOBAL(void) +write_JPEG_file (char * filename, int quality) +{ + /* This struct contains the JPEG compression parameters and pointers to + * working space (which is allocated as needed by the JPEG library). + * It is possible to have several such structures, representing multiple + * compression/decompression processes, in existence at once. We refer + * to any one struct (and its associated working data) as a "JPEG object". + */ + struct jpeg_compress_struct cinfo; + /* This struct represents a JPEG error handler. It is declared separately + * because applications often want to supply a specialized error handler + * (see the second half of this file for an example). But here we just + * take the easy way out and use the standard error handler, which will + * print a message on stderr and call exit() if compression fails. + * Note that this struct must live as long as the main JPEG parameter + * struct, to avoid dangling-pointer problems. + */ + struct jpeg_error_mgr jerr; + /* More stuff */ + FILE * outfile; /* target file */ + JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */ + int row_stride; /* physical row width in image buffer */ + + /* Step 1: allocate and initialize JPEG compression object */ + + /* We have to set up the error handler first, in case the initialization + * step fails. (Unlikely, but it could happen if you are out of memory.) + * This routine fills in the contents of struct jerr, and returns jerr's + * address which we place into the link field in cinfo. + */ + cinfo.err = jpeg_std_error(&jerr); + /* Now we can initialize the JPEG compression object. */ + jpeg_create_compress(&cinfo); + + /* Step 2: specify data destination (eg, a file) */ + /* Note: steps 2 and 3 can be done in either order. */ + + /* Here we use the library-supplied code to send compressed data to a + * stdio stream. You can also write your own code to do something else. + * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that + * requires it in order to write binary files. + */ + if ((outfile = fopen(filename, "wb")) == NULL) { + fprintf(stderr, "can't open %s\n", filename); + exit(1); + } + jpeg_stdio_dest(&cinfo, outfile); + + /* Step 3: set parameters for compression */ + + /* First we supply a description of the input image. + * Four fields of the cinfo struct must be filled in: + */ + cinfo.image_width = image_width; /* image width and height, in pixels */ + cinfo.image_height = image_height; + cinfo.input_components = 3; /* # of color components per pixel */ + cinfo.in_color_space = JCS_RGB; /* colorspace of input image */ + /* Now use the library's routine to set default compression parameters. + * (You must set at least cinfo.in_color_space before calling this, + * since the defaults depend on the source color space.) + */ + jpeg_set_defaults(&cinfo); + /* Now you can set any non-default parameters you wish to. + * Here we just illustrate the use of quality (quantization table) scaling: + */ + jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */); + + /* Step 4: Start compressor */ + + /* TRUE ensures that we will write a complete interchange-JPEG file. + * Pass TRUE unless you are very sure of what you're doing. + */ + jpeg_start_compress(&cinfo, TRUE); + + /* Step 5: while (scan lines remain to be written) */ + /* jpeg_write_scanlines(...); */ + + /* Here we use the library's state variable cinfo.next_scanline as the + * loop counter, so that we don't have to keep track ourselves. + * To keep things simple, we pass one scanline per call; you can pass + * more if you wish, though. + */ + row_stride = image_width * 3; /* JSAMPLEs per row in image_buffer */ + + while (cinfo.next_scanline < cinfo.image_height) { + /* jpeg_write_scanlines expects an array of pointers to scanlines. + * Here the array is only one element long, but you could pass + * more than one scanline at a time if that's more convenient. + */ + row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride]; + (void) jpeg_write_scanlines(&cinfo, row_pointer, 1); + } + + /* Step 6: Finish compression */ + + jpeg_finish_compress(&cinfo); + /* After finish_compress, we can close the output file. */ + fclose(outfile); + + /* Step 7: release JPEG compression object */ + + /* This is an important step since it will release a good deal of memory. */ + jpeg_destroy_compress(&cinfo); + + /* And we're done! */ +} + + +/* + * SOME FINE POINTS: + * + * In the above loop, we ignored the return value of jpeg_write_scanlines, + * which is the number of scanlines actually written. We could get away + * with this because we were only relying on the value of cinfo.next_scanline, + * which will be incremented correctly. If you maintain additional loop + * variables then you should be careful to increment them properly. + * Actually, for output to a stdio stream you needn't worry, because + * then jpeg_write_scanlines will write all the lines passed (or else exit + * with a fatal error). Partial writes can only occur if you use a data + * destination module that can demand suspension of the compressor. + * (If you don't know what that's for, you don't need it.) + * + * If the compressor requires full-image buffers (for entropy-coding + * optimization or a multi-scan JPEG file), it will create temporary + * files for anything that doesn't fit within the maximum-memory setting. + * (Note that temp files are NOT needed if you use the default parameters.) + * On some systems you may need to set up a signal handler to ensure that + * temporary files are deleted if the program is interrupted. See libjpeg.doc. + * + * Scanlines MUST be supplied in top-to-bottom order if you want your JPEG + * files to be compatible with everyone else's. If you cannot readily read + * your data in that order, you'll need an intermediate array to hold the + * image. See rdtarga.c or rdbmp.c for examples of handling bottom-to-top + * source data using the JPEG code's internal virtual-array mechanisms. + */ + + + +/******************** JPEG DECOMPRESSION SAMPLE INTERFACE *******************/ + +/* This half of the example shows how to read data from the JPEG decompressor. + * It's a bit more refined than the above, in that we show: + * (a) how to modify the JPEG library's standard error-reporting behavior; + * (b) how to allocate workspace using the library's memory manager. + * + * Just to make this example a little different from the first one, we'll + * assume that we do not intend to put the whole image into an in-memory + * buffer, but to send it line-by-line someplace else. We need a one- + * scanline-high JSAMPLE array as a work buffer, and we will let the JPEG + * memory manager allocate it for us. This approach is actually quite useful + * because we don't need to remember to deallocate the buffer separately: it + * will go away automatically when the JPEG object is cleaned up. + */ + + +/* + * ERROR HANDLING: + * + * The JPEG library's standard error handler (jerror.c) is divided into + * several "methods" which you can override individually. This lets you + * adjust the behavior without duplicating a lot of code, which you might + * have to update with each future release. + * + * Our example here shows how to override the "error_exit" method so that + * control is returned to the library's caller when a fatal error occurs, + * rather than calling exit() as the standard error_exit method does. + * + * We use C's setjmp/longjmp facility to return control. This means that the + * routine which calls the JPEG library must first execute a setjmp() call to + * establish the return point. We want the replacement error_exit to do a + * longjmp(). But we need to make the setjmp buffer accessible to the + * error_exit routine. To do this, we make a private extension of the + * standard JPEG error handler object. (If we were using C++, we'd say we + * were making a subclass of the regular error handler.) + * + * Here's the extended error handler struct: + */ + +struct my_error_mgr { + struct jpeg_error_mgr pub; /* "public" fields */ + + jmp_buf setjmp_buffer; /* for return to caller */ +}; + +typedef struct my_error_mgr * my_error_ptr; + +/* + * Here's the routine that will replace the standard error_exit method: + */ + +METHODDEF(void) +my_error_exit (j_common_ptr cinfo) +{ + /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */ + my_error_ptr myerr = (my_error_ptr) cinfo->err; + + /* Always display the message. */ + /* We could postpone this until after returning, if we chose. */ + (*cinfo->err->output_message) (cinfo); + + /* Return control to the setjmp point */ + longjmp(myerr->setjmp_buffer, 1); +} + + +/* + * Sample routine for JPEG decompression. We assume that the source file name + * is passed in. We want to return 1 on success, 0 on error. + */ + + +GLOBAL(int) +read_JPEG_file (char * filename) +{ + /* This struct contains the JPEG decompression parameters and pointers to + * working space (which is allocated as needed by the JPEG library). + */ + struct jpeg_decompress_struct cinfo; + /* We use our private extension JPEG error handler. + * Note that this struct must live as long as the main JPEG parameter + * struct, to avoid dangling-pointer problems. + */ + struct my_error_mgr jerr; + /* More stuff */ + FILE * infile; /* source file */ + JSAMPARRAY buffer; /* Output row buffer */ + int row_stride; /* physical row width in output buffer */ + + /* In this example we want to open the input file before doing anything else, + * so that the setjmp() error recovery below can assume the file is open. + * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that + * requires it in order to read binary files. + */ + + if ((infile = fopen(filename, "rb")) == NULL) { + fprintf(stderr, "can't open %s\n", filename); + return 0; + } + + /* Step 1: allocate and initialize JPEG decompression object */ + + /* We set up the normal JPEG error routines, then override error_exit. */ + cinfo.err = jpeg_std_error(&jerr.pub); + jerr.pub.error_exit = my_error_exit; + /* Establish the setjmp return context for my_error_exit to use. */ + if (setjmp(jerr.setjmp_buffer)) { + /* If we get here, the JPEG code has signaled an error. + * We need to clean up the JPEG object, close the input file, and return. + */ + jpeg_destroy_decompress(&cinfo); + fclose(infile); + return 0; + } + /* Now we can initialize the JPEG decompression object. */ + jpeg_create_decompress(&cinfo); + + /* Step 2: specify data source (eg, a file) */ + + jpeg_stdio_src(&cinfo, infile); + + /* Step 3: read file parameters with jpeg_read_header() */ + + (void) jpeg_read_header(&cinfo, TRUE); + /* We can ignore the return value from jpeg_read_header since + * (a) suspension is not possible with the stdio data source, and + * (b) we passed TRUE to reject a tables-only JPEG file as an error. + * See libjpeg.doc for more info. + */ + + /* Step 4: set parameters for decompression */ + + /* In this example, we don't need to change any of the defaults set by + * jpeg_read_header(), so we do nothing here. + */ + + /* Step 5: Start decompressor */ + + (void) jpeg_start_decompress(&cinfo); + /* We can ignore the return value since suspension is not possible + * with the stdio data source. + */ + + /* We may need to do some setup of our own at this point before reading + * the data. After jpeg_start_decompress() we have the correct scaled + * output image dimensions available, as well as the output colormap + * if we asked for color quantization. + * In this example, we need to make an output work buffer of the right size. + */ + /* JSAMPLEs per row in output buffer */ + row_stride = cinfo.output_width * cinfo.output_components; + /* Make a one-row-high sample array that will go away when done with image */ + buffer = (*cinfo.mem->alloc_sarray) + ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); + + /* Step 6: while (scan lines remain to be read) */ + /* jpeg_read_scanlines(...); */ + + /* Here we use the library's state variable cinfo.output_scanline as the + * loop counter, so that we don't have to keep track ourselves. + */ + while (cinfo.output_scanline < cinfo.output_height) { + /* jpeg_read_scanlines expects an array of pointers to scanlines. + * Here the array is only one element long, but you could ask for + * more than one scanline at a time if that's more convenient. + */ + (void) jpeg_read_scanlines(&cinfo, buffer, 1); + /* Assume put_scanline_someplace wants a pointer and sample count. */ + put_scanline_someplace(buffer[0], row_stride); + } + + /* Step 7: Finish decompression */ + + (void) jpeg_finish_decompress(&cinfo); + /* We can ignore the return value since suspension is not possible + * with the stdio data source. + */ + + /* Step 8: Release JPEG decompression object */ + + /* This is an important step since it will release a good deal of memory. */ + jpeg_destroy_decompress(&cinfo); + + /* After finish_decompress, we can close the input file. + * Here we postpone it until after no more JPEG errors are possible, + * so as to simplify the setjmp error logic above. (Actually, I don't + * think that jpeg_destroy can do an error exit, but why assume anything...) + */ + fclose(infile); + + /* At this point you may want to check to see whether any corrupt-data + * warnings occurred (test whether jerr.pub.num_warnings is nonzero). + */ + + /* And we're done! */ + return 1; +} + + +/* + * SOME FINE POINTS: + * + * In the above code, we ignored the return value of jpeg_read_scanlines, + * which is the number of scanlines actually read. We could get away with + * this because we asked for only one line at a time and we weren't using + * a suspending data source. See libjpeg.doc for more info. + * + * We cheated a bit by calling alloc_sarray() after jpeg_start_decompress(); + * we should have done it beforehand to ensure that the space would be + * counted against the JPEG max_memory setting. In some systems the above + * code would risk an out-of-memory error. However, in general we don't + * know the output image dimensions before jpeg_start_decompress(), unless we + * call jpeg_calc_output_dimensions(). See libjpeg.doc for more about this. + * + * Scanlines are returned in the same order as they appear in the JPEG file, + * which is standardly top-to-bottom. If you must emit data bottom-to-top, + * you can use one of the virtual arrays provided by the JPEG memory manager + * to invert the data. See wrbmp.c for an example. + * + * As with compression, some operating modes may require temporary files. + * On some systems you may need to set up a signal handler to ensure that + * temporary files are deleted if the program is interrupted. See libjpeg.doc. + */ diff --git a/lc-continuity/mk4/modimage/jpeg-6b/filelist.doc b/lc-continuity/mk4/modimage/jpeg-6b/filelist.doc new file mode 100644 index 0000000000000000000000000000000000000000..e14982ca55b97cb2885e7cc42574042fd2b20ef3 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/filelist.doc @@ -0,0 +1,210 @@ +IJG JPEG LIBRARY: FILE LIST + +Copyright (C) 1994-1998, Thomas G. Lane. +This file is part of the Independent JPEG Group's software. +For conditions of distribution and use, see the accompanying README file. + + +Here is a road map to the files in the IJG JPEG distribution. The +distribution includes the JPEG library proper, plus two application +programs ("cjpeg" and "djpeg") which use the library to convert JPEG +files to and from some other popular image formats. A third application +"jpegtran" uses the library to do lossless conversion between different +variants of JPEG. There are also two stand-alone applications, +"rdjpgcom" and "wrjpgcom". + + +THE JPEG LIBRARY +================ + +Include files: + +jpeglib.h JPEG library's exported data and function declarations. +jconfig.h Configuration declarations. Note: this file is not present + in the distribution; it is generated during installation. +jmorecfg.h Additional configuration declarations; need not be changed + for a standard installation. +jerror.h Declares JPEG library's error and trace message codes. +jinclude.h Central include file used by all IJG .c files to reference + system include files. +jpegint.h JPEG library's internal data structures. +jchuff.h Private declarations for Huffman encoder modules. +jdhuff.h Private declarations for Huffman decoder modules. +jdct.h Private declarations for forward & reverse DCT subsystems. +jmemsys.h Private declarations for memory management subsystem. +jversion.h Version information. + +Applications using the library should include jpeglib.h (which in turn +includes jconfig.h and jmorecfg.h). Optionally, jerror.h may be included +if the application needs to reference individual JPEG error codes. The +other include files are intended for internal use and would not normally +be included by an application program. (cjpeg/djpeg/etc do use jinclude.h, +since its function is to improve portability of the whole IJG distribution. +Most other applications will directly include the system include files they +want, and hence won't need jinclude.h.) + + +C source code files: + +These files contain most of the functions intended to be called directly by +an application program: + +jcapimin.c Application program interface: core routines for compression. +jcapistd.c Application program interface: standard compression. +jdapimin.c Application program interface: core routines for decompression. +jdapistd.c Application program interface: standard decompression. +jcomapi.c Application program interface routines common to compression + and decompression. +jcparam.c Compression parameter setting helper routines. +jctrans.c API and library routines for transcoding compression. +jdtrans.c API and library routines for transcoding decompression. + +Compression side of the library: + +jcinit.c Initialization: determines which other modules to use. +jcmaster.c Master control: setup and inter-pass sequencing logic. +jcmainct.c Main buffer controller (preprocessor => JPEG compressor). +jcprepct.c Preprocessor buffer controller. +jccoefct.c Buffer controller for DCT coefficient buffer. +jccolor.c Color space conversion. +jcsample.c Downsampling. +jcdctmgr.c DCT manager (DCT implementation selection & control). +jfdctint.c Forward DCT using slow-but-accurate integer method. +jfdctfst.c Forward DCT using faster, less accurate integer method. +jfdctflt.c Forward DCT using floating-point arithmetic. +jchuff.c Huffman entropy coding for sequential JPEG. +jcphuff.c Huffman entropy coding for progressive JPEG. +jcmarker.c JPEG marker writing. +jdatadst.c Data destination manager for stdio output. + +Decompression side of the library: + +jdmaster.c Master control: determines which other modules to use. +jdinput.c Input controller: controls input processing modules. +jdmainct.c Main buffer controller (JPEG decompressor => postprocessor). +jdcoefct.c Buffer controller for DCT coefficient buffer. +jdpostct.c Postprocessor buffer controller. +jdmarker.c JPEG marker reading. +jdhuff.c Huffman entropy decoding for sequential JPEG. +jdphuff.c Huffman entropy decoding for progressive JPEG. +jddctmgr.c IDCT manager (IDCT implementation selection & control). +jidctint.c Inverse DCT using slow-but-accurate integer method. +jidctfst.c Inverse DCT using faster, less accurate integer method. +jidctflt.c Inverse DCT using floating-point arithmetic. +jidctred.c Inverse DCTs with reduced-size outputs. +jdsample.c Upsampling. +jdcolor.c Color space conversion. +jdmerge.c Merged upsampling/color conversion (faster, lower quality). +jquant1.c One-pass color quantization using a fixed-spacing colormap. +jquant2.c Two-pass color quantization using a custom-generated colormap. + Also handles one-pass quantization to an externally given map. +jdatasrc.c Data source manager for stdio input. + +Support files for both compression and decompression: + +jerror.c Standard error handling routines (application replaceable). +jmemmgr.c System-independent (more or less) memory management code. +jutils.c Miscellaneous utility routines. + +jmemmgr.c relies on a system-dependent memory management module. The IJG +distribution includes the following implementations of the system-dependent +module: + +jmemnobs.c "No backing store": assumes adequate virtual memory exists. +jmemansi.c Makes temporary files with ANSI-standard routine tmpfile(). +jmemname.c Makes temporary files with program-generated file names. +jmemdos.c Custom implementation for MS-DOS (16-bit environment only): + can use extended and expanded memory as well as temp files. +jmemmac.c Custom implementation for Apple Macintosh. + +Exactly one of the system-dependent modules should be configured into an +installed JPEG library (see install.doc for hints about which one to use). +On unusual systems you may find it worthwhile to make a special +system-dependent memory manager. + + +Non-C source code files: + +jmemdosa.asm 80x86 assembly code support for jmemdos.c; used only in + MS-DOS-specific configurations of the JPEG library. + + +CJPEG/DJPEG/JPEGTRAN +==================== + +Include files: + +cdjpeg.h Declarations shared by cjpeg/djpeg/jpegtran modules. +cderror.h Additional error and trace message codes for cjpeg et al. +transupp.h Declarations for jpegtran support routines in transupp.c. + +C source code files: + +cjpeg.c Main program for cjpeg. +djpeg.c Main program for djpeg. +jpegtran.c Main program for jpegtran. +cdjpeg.c Utility routines used by all three programs. +rdcolmap.c Code to read a colormap file for djpeg's "-map" switch. +rdswitch.c Code to process some of cjpeg's more complex switches. + Also used by jpegtran. +transupp.c Support code for jpegtran: lossless image manipulations. + +Image file reader modules for cjpeg: + +rdbmp.c BMP file input. +rdgif.c GIF file input (now just a stub). +rdppm.c PPM/PGM file input. +rdrle.c Utah RLE file input. +rdtarga.c Targa file input. + +Image file writer modules for djpeg: + +wrbmp.c BMP file output. +wrgif.c GIF file output (a mere shadow of its former self). +wrppm.c PPM/PGM file output. +wrrle.c Utah RLE file output. +wrtarga.c Targa file output. + + +RDJPGCOM/WRJPGCOM +================= + +C source code files: + +rdjpgcom.c Stand-alone rdjpgcom application. +wrjpgcom.c Stand-alone wrjpgcom application. + +These programs do not depend on the IJG library. They do use +jconfig.h and jinclude.h, only to improve portability. + + +ADDITIONAL FILES +================ + +Documentation (see README for a guide to the documentation files): + +README Master documentation file. +*.doc Other documentation files. +*.1 Documentation in Unix man page format. +change.log Version-to-version change highlights. +example.c Sample code for calling JPEG library. + +Configuration/installation files and programs (see install.doc for more info): + +configure Unix shell script to perform automatic configuration. +ltconfig Support scripts for configure (from GNU libtool). +ltmain.sh +config.guess +config.sub +install-sh Install shell script for those Unix systems lacking one. +ckconfig.c Program to generate jconfig.h on non-Unix systems. +jconfig.doc Template for making jconfig.h by hand. +makefile.* Sample makefiles for particular systems. +jconfig.* Sample jconfig.h for particular systems. +ansi2knr.c De-ANSIfier for pre-ANSI C compilers (courtesy of + L. Peter Deutsch and Aladdin Enterprises). + +Test files (see install.doc for test procedure): + +test*.* Source and comparison files for confidence test. + These are binary image files, NOT text files. diff --git a/lc-continuity/mk4/modimage/jpeg-6b/install-sh b/lc-continuity/mk4/modimage/jpeg-6b/install-sh new file mode 100644 index 0000000000000000000000000000000000000000..e8436696c19d1bfd9e4d53c7113deb6a991818a8 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/install-sh @@ -0,0 +1,250 @@ +#!/bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5 (mit/util/scripts/install.sh). +# +# Copyright 1991 by the Massachusetts Institute of Technology +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation, and that the name of M.I.T. not be used in advertising or +# publicity pertaining to distribution of the software without specific, +# written prior permission. M.I.T. makes no representations about the +# suitability of this software for any purpose. It is provided "as is" +# without express or implied warranty. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +transformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +else + true +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d $dst ]; then + instcmd=: + else + instcmd=mkdir + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f $src -o -d $src ] + then + true + else + echo "install: $src does not exist" + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "install: no destination specified" + exit 1 + else + true + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d $dst ] + then + dst="$dst"/`basename $src` + else + true + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' +' +IFS="${IFS-${defaultIFS}}" + +oIFS="${IFS}" +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS="${oIFS}" + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp="${pathcomp}${1}" + shift + + if [ ! -d "${pathcomp}" ] ; + then + $mkdirprog "${pathcomp}" + else + true + fi + + pathcomp="${pathcomp}/" +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd $dst && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename $dst` + else + dstfile=`basename $dst $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename $dst` + else + true + fi + +# Make a temp file name in the proper directory. + + dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + + $doit $instcmd $src $dsttmp && + + trap "rm -f ${dsttmp}" 0 && + +# and set any options; do chmod last to preserve setuid bits + +# If any of these fail, we abort the whole thing. If we want to +# ignore errors from any of these, just make sure not to ignore +# errors from the above "$doit $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && + +# Now rename the file to the real destination. + + $doit $rmcmd -f $dstdir/$dstfile && + $doit $mvcmd $dsttmp $dstdir/$dstfile + +fi && + + +exit 0 diff --git a/lc-continuity/mk4/modimage/jpeg-6b/install.doc b/lc-continuity/mk4/modimage/jpeg-6b/install.doc new file mode 100644 index 0000000000000000000000000000000000000000..3702b986b6f9bf5c3156a1bd84edbebfdc911b44 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/install.doc @@ -0,0 +1,1063 @@ +INSTALLATION INSTRUCTIONS for the Independent JPEG Group's JPEG software + +Copyright (C) 1991-1998, Thomas G. Lane. +This file is part of the Independent JPEG Group's software. +For conditions of distribution and use, see the accompanying README file. + + +This file explains how to configure and install the IJG software. We have +tried to make this software extremely portable and flexible, so that it can be +adapted to almost any environment. The downside of this decision is that the +installation process is complicated. We have provided shortcuts to simplify +the task on common systems. But in any case, you will need at least a little +familiarity with C programming and program build procedures for your system. + +If you are only using this software as part of a larger program, the larger +program's installation procedure may take care of configuring the IJG code. +For example, Ghostscript's installation script will configure the IJG code. +You don't need to read this file if you just want to compile Ghostscript. + +If you are on a Unix machine, you may not need to read this file at all. +Try doing + ./configure + make + make test +If that doesn't complain, do + make install +(better do "make -n install" first to see if the makefile will put the files +where you want them). Read further if you run into snags or want to customize +the code for your system. + + +TABLE OF CONTENTS +----------------- + +Before you start +Configuring the software: + using the automatic "configure" script + using one of the supplied jconfig and makefile files + by hand +Building the software +Testing the software +Installing the software +Optional stuff +Optimization +Hints for specific systems + + +BEFORE YOU START +================ + +Before installing the software you must unpack the distributed source code. +Since you are reading this file, you have probably already succeeded in this +task. However, there is a potential for error if you needed to convert the +files to the local standard text file format (for example, if you are on +MS-DOS you may have converted LF end-of-line to CR/LF). You must apply +such conversion to all the files EXCEPT those whose names begin with "test". +The test files contain binary data; if you change them in any way then the +self-test will give bad results. + +Please check the last section of this file to see if there are hints for the +specific machine or compiler you are using. + + +CONFIGURING THE SOFTWARE +======================== + +To configure the IJG code for your system, you need to create two files: + * jconfig.h: contains values for system-dependent #define symbols. + * Makefile: controls the compilation process. +(On a non-Unix machine, you may create "project files" or some other +substitute for a Makefile. jconfig.h is needed in any environment.) + +We provide three different ways to generate these files: + * On a Unix system, you can just run the "configure" script. + * We provide sample jconfig files and makefiles for popular machines; + if your machine matches one of the samples, just copy the right sample + files to jconfig.h and Makefile. + * If all else fails, read the instructions below and make your own files. + + +Configuring the software using the automatic "configure" script +--------------------------------------------------------------- + +If you are on a Unix machine, you can just type + ./configure +and let the configure script construct appropriate configuration files. +If you're using "csh" on an old version of System V, you might need to type + sh configure +instead to prevent csh from trying to execute configure itself. +Expect configure to run for a few minutes, particularly on slower machines; +it works by compiling a series of test programs. + +Configure was created with GNU Autoconf and it follows the usual conventions +for GNU configure scripts. It makes a few assumptions that you may want to +override. You can do this by providing optional switches to configure: + +* If you want to build libjpeg as a shared library, say + ./configure --enable-shared +To get both shared and static libraries, say + ./configure --enable-shared --enable-static +Note that these switches invoke GNU libtool to take care of system-dependent +shared library building methods. If things don't work this way, please try +running configure without either switch; that should build a static library +without using libtool. If that works, your problem is probably with libtool +not with the IJG code. libtool is fairly new and doesn't support all flavors +of Unix yet. (You might be able to find a newer version of libtool than the +one included with libjpeg; see ftp.gnu.org. Report libtool problems to +bug-libtool@gnu.org.) + +* Configure will use gcc (GNU C compiler) if it's available, otherwise cc. +To force a particular compiler to be selected, use the CC option, for example + ./configure CC='cc' +The same method can be used to include any unusual compiler switches. +For example, on HP-UX you probably want to say + ./configure CC='cc -Aa' +to get HP's compiler to run in ANSI mode. + +* The default CFLAGS setting is "-O" for non-gcc compilers, "-O2" for gcc. +You can override this by saying, for example, + ./configure CFLAGS='-g' +if you want to compile with debugging support. + +* Configure will set up the makefile so that "make install" will install files +into /usr/local/bin, /usr/local/man, etc. You can specify an installation +prefix other than "/usr/local" by giving configure the option "--prefix=PATH". + +* If you don't have a lot of swap space, you may need to enable the IJG +software's internal virtual memory mechanism. To do this, give the option +"--enable-maxmem=N" where N is the default maxmemory limit in megabytes. +This is discussed in more detail under "Selecting a memory manager", below. +You probably don't need to worry about this on reasonably-sized Unix machines, +unless you plan to process very large images. + +Configure has some other features that are useful if you are cross-compiling +or working in a network of multiple machine types; but if you need those +features, you probably already know how to use them. + + +Configuring the software using one of the supplied jconfig and makefile files +----------------------------------------------------------------------------- + +If you have one of these systems, you can just use the provided configuration +files: + +Makefile jconfig file System and/or compiler + +makefile.manx jconfig.manx Amiga, Manx Aztec C +makefile.sas jconfig.sas Amiga, SAS C +makeproj.mac jconfig.mac Apple Macintosh, Metrowerks CodeWarrior +mak*jpeg.st jconfig.st Atari ST/STE/TT, Pure C or Turbo C +makefile.bcc jconfig.bcc MS-DOS or OS/2, Borland C +makefile.dj jconfig.dj MS-DOS, DJGPP (Delorie's port of GNU C) +makefile.mc6 jconfig.mc6 MS-DOS, Microsoft C (16-bit only) +makefile.wat jconfig.wat MS-DOS, OS/2, or Windows NT, Watcom C +makefile.vc jconfig.vc Windows NT/95, MS Visual C++ +make*.ds jconfig.vc Windows NT/95, MS Developer Studio +makefile.mms jconfig.vms Digital VMS, with MMS software +makefile.vms jconfig.vms Digital VMS, without MMS software + +Copy the proper jconfig file to jconfig.h and the makefile to Makefile (or +whatever your system uses as the standard makefile name). For more info see +the appropriate system-specific hints section near the end of this file. + + +Configuring the software by hand +-------------------------------- + +First, generate a jconfig.h file. If you are moderately familiar with C, +the comments in jconfig.doc should be enough information to do this; just +copy jconfig.doc to jconfig.h and edit it appropriately. Otherwise, you may +prefer to use the ckconfig.c program. You will need to compile and execute +ckconfig.c by hand --- we hope you know at least enough to do that. +ckconfig.c may not compile the first try (in fact, the whole idea is for it +to fail if anything is going to). If you get compile errors, fix them by +editing ckconfig.c according to the directions given in ckconfig.c. Once +you get it to run, it will write a suitable jconfig.h file, and will also +print out some advice about which makefile to use. + +You may also want to look at the canned jconfig files, if there is one for a +system similar to yours. + +Second, select a makefile and copy it to Makefile (or whatever your system +uses as the standard makefile name). The most generic makefiles we provide +are + makefile.ansi: if your C compiler supports function prototypes + makefile.unix: if not. +(You have function prototypes if ckconfig.c put "#define HAVE_PROTOTYPES" +in jconfig.h.) You may want to start from one of the other makefiles if +there is one for a system similar to yours. + +Look over the selected Makefile and adjust options as needed. In particular +you may want to change the CC and CFLAGS definitions. For instance, if you +are using GCC, set CC=gcc. If you had to use any compiler switches to get +ckconfig.c to work, make sure the same switches are in CFLAGS. + +If you are on a system that doesn't use makefiles, you'll need to set up +project files (or whatever you do use) to compile all the source files and +link them into executable files cjpeg, djpeg, jpegtran, rdjpgcom, and wrjpgcom. +See the file lists in any of the makefiles to find out which files go into +each program. Note that the provided makefiles all make a "library" file +libjpeg first, but you don't have to do that if you don't want to; the file +lists identify which source files are actually needed for compression, +decompression, or both. As a last resort, you can make a batch script that +just compiles everything and links it all together; makefile.vms is an example +of this (it's for VMS systems that have no make-like utility). + +Here are comments about some specific configuration decisions you'll +need to make: + +Command line style +------------------ + +These programs can use a Unix-like command line style which supports +redirection and piping, like this: + cjpeg inputfile >outputfile + cjpeg outputfile + source program | cjpeg >outputfile +The simpler "two file" command line style is just + cjpeg inputfile outputfile +You may prefer the two-file style, particularly if you don't have pipes. + +You MUST use two-file style on any system that doesn't cope well with binary +data fed through stdin/stdout; this is true for some MS-DOS compilers, for +example. If you're not on a Unix system, it's safest to assume you need +two-file style. (But if your compiler provides either the Posix-standard +fdopen() library routine or a Microsoft-compatible setmode() routine, you +can safely use the Unix command line style, by defining USE_FDOPEN or +USE_SETMODE respectively.) + +To use the two-file style, make jconfig.h say "#define TWO_FILE_COMMANDLINE". + +Selecting a memory manager +-------------------------- + +The IJG code is capable of working on images that are too big to fit in main +memory; data is swapped out to temporary files as necessary. However, the +code to do this is rather system-dependent. We provide five different +memory managers: + +* jmemansi.c This version uses the ANSI-standard library routine tmpfile(), + which not all non-ANSI systems have. On some systems + tmpfile() may put the temporary file in a non-optimal + location; if you don't like what it does, use jmemname.c. + +* jmemname.c This version creates named temporary files. For anything + except a Unix machine, you'll need to configure the + select_file_name() routine appropriately; see the comments + near the head of jmemname.c. If you use this version, define + NEED_SIGNAL_CATCHER in jconfig.h to make sure the temp files + are removed if the program is aborted. + +* jmemnobs.c (That stands for No Backing Store :-).) This will compile on + almost any system, but it assumes you have enough main memory + or virtual memory to hold the biggest images you work with. + +* jmemdos.c This should be used with most 16-bit MS-DOS compilers. + See the system-specific notes about MS-DOS for more info. + IMPORTANT: if you use this, define USE_MSDOS_MEMMGR in + jconfig.h, and include the assembly file jmemdosa.asm in the + programs. The supplied makefiles and jconfig files for + 16-bit MS-DOS compilers already do both. + +* jmemmac.c Custom version for Apple Macintosh; see the system-specific + notes for Macintosh for more info. + +To use a particular memory manager, change the SYSDEPMEM variable in your +makefile to equal the corresponding object file name (for example, jmemansi.o +or jmemansi.obj for jmemansi.c). + +If you have plenty of (real or virtual) main memory, just use jmemnobs.c. +"Plenty" means about ten bytes for every pixel in the largest images +you plan to process, so a lot of systems don't meet this criterion. +If yours doesn't, try jmemansi.c first. If that doesn't compile, you'll have +to use jmemname.c; be sure to adjust select_file_name() for local conditions. +You may also need to change unlink() to remove() in close_backing_store(). + +Except with jmemnobs.c or jmemmac.c, you need to adjust the DEFAULT_MAX_MEM +setting to a reasonable value for your system (either by adding a #define for +DEFAULT_MAX_MEM to jconfig.h, or by adding a -D switch to the Makefile). +This value limits the amount of data space the program will attempt to +allocate. Code and static data space isn't counted, so the actual memory +needs for cjpeg or djpeg are typically 100 to 150Kb more than the max-memory +setting. Larger max-memory settings reduce the amount of I/O needed to +process a large image, but too large a value can result in "insufficient +memory" failures. On most Unix machines (and other systems with virtual +memory), just set DEFAULT_MAX_MEM to several million and forget it. At the +other end of the spectrum, for MS-DOS machines you probably can't go much +above 300K to 400K. (On MS-DOS the value refers to conventional memory only. +Extended/expanded memory is handled separately by jmemdos.c.) + + +BUILDING THE SOFTWARE +===================== + +Now you should be able to compile the software. Just say "make" (or +whatever's necessary to start the compilation). Have a cup of coffee. + +Here are some things that could go wrong: + +If your compiler complains about undefined structures, you should be able to +shut it up by putting "#define INCOMPLETE_TYPES_BROKEN" in jconfig.h. + +If you have trouble with missing system include files or inclusion of the +wrong ones, read jinclude.h. This shouldn't happen if you used configure +or ckconfig.c to set up jconfig.h. + +There are a fair number of routines that do not use all of their parameters; +some compilers will issue warnings about this, which you can ignore. There +are also a few configuration checks that may give "unreachable code" warnings. +Any other warning deserves investigation. + +If you don't have a getenv() library routine, define NO_GETENV. + +Also see the system-specific hints, below. + + +TESTING THE SOFTWARE +==================== + +As a quick test of functionality we've included a small sample image in +several forms: + testorig.jpg Starting point for the djpeg tests. + testimg.ppm The output of djpeg testorig.jpg + testimg.bmp The output of djpeg -bmp -colors 256 testorig.jpg + testimg.jpg The output of cjpeg testimg.ppm + testprog.jpg Progressive-mode equivalent of testorig.jpg. + testimgp.jpg The output of cjpeg -progressive -optimize testimg.ppm +(The first- and second-generation .jpg files aren't identical since JPEG is +lossy.) If you can generate duplicates of the testimg* files then you +probably have working programs. + +With most of the makefiles, "make test" will perform the necessary +comparisons. + +If you're using a makefile that doesn't provide the test option, run djpeg +and cjpeg by hand and compare the output files to testimg* with whatever +binary file comparison tool you have. The files should be bit-for-bit +identical. + +If the programs complain "MAX_ALLOC_CHUNK is wrong, please fix", then you +need to reduce MAX_ALLOC_CHUNK to a value that fits in type size_t. +Try adding "#define MAX_ALLOC_CHUNK 65520L" to jconfig.h. A less likely +configuration error is "ALIGN_TYPE is wrong, please fix": defining ALIGN_TYPE +as long should take care of that one. + +If the cjpeg test run fails with "Missing Huffman code table entry", it's a +good bet that you needed to define RIGHT_SHIFT_IS_UNSIGNED. Go back to the +configuration step and run ckconfig.c. (This is a good plan for any other +test failure, too.) + +If you are using Unix (one-file) command line style on a non-Unix system, +it's a good idea to check that binary I/O through stdin/stdout actually +works. You should get the same results from "djpeg out.ppm" +as from "djpeg -outfile out.ppm testorig.jpg". Note that the makefiles all +use the latter style and therefore do not exercise stdin/stdout! If this +check fails, try recompiling with USE_SETMODE or USE_FDOPEN defined. +If it still doesn't work, better use two-file style. + +If you chose a memory manager other than jmemnobs.c, you should test that +temporary-file usage works. Try "djpeg -bmp -colors 256 -max 0 testorig.jpg" +and make sure its output matches testimg.bmp. If you have any really large +images handy, try compressing them with -optimize and/or decompressing with +-colors 256 to make sure your DEFAULT_MAX_MEM setting is not too large. + +NOTE: this is far from an exhaustive test of the JPEG software; some modules, +such as 1-pass color quantization, are not exercised at all. It's just a +quick test to give you some confidence that you haven't missed something +major. + + +INSTALLING THE SOFTWARE +======================= + +Once you're done with the above steps, you can install the software by +copying the executable files (cjpeg, djpeg, jpegtran, rdjpgcom, and wrjpgcom) +to wherever you normally install programs. On Unix systems, you'll also want +to put the man pages (cjpeg.1, djpeg.1, jpegtran.1, rdjpgcom.1, wrjpgcom.1) +in the man-page directory. The pre-fab makefiles don't support this step +since there's such a wide variety of installation procedures on different +systems. + +If you generated a Makefile with the "configure" script, you can just say + make install +to install the programs and their man pages into the standard places. +(You'll probably need to be root to do this.) We recommend first saying + make -n install +to see where configure thought the files should go. You may need to edit +the Makefile, particularly if your system's conventions for man page +filenames don't match what configure expects. + +If you want to install the IJG library itself, for use in compiling other +programs besides ours, then you need to put the four include files + jpeglib.h jerror.h jconfig.h jmorecfg.h +into your include-file directory, and put the library file libjpeg.a +(extension may vary depending on system) wherever library files go. +If you generated a Makefile with "configure", it will do what it thinks +is the right thing if you say + make install-lib + + +OPTIONAL STUFF +============== + +Progress monitor: + +If you like, you can #define PROGRESS_REPORT (in jconfig.h) to enable display +of percent-done progress reports. The routine provided in cdjpeg.c merely +prints percentages to stderr, but you can customize it to do something +fancier. + +Utah RLE file format support: + +We distribute the software with support for RLE image files (Utah Raster +Toolkit format) disabled, because the RLE support won't compile without the +Utah library. If you have URT version 3.1 or later, you can enable RLE +support as follows: + 1. #define RLE_SUPPORTED in jconfig.h. + 2. Add a -I option to CFLAGS in the Makefile for the directory + containing the URT .h files (typically the "include" + subdirectory of the URT distribution). + 3. Add -L... -lrle to LDLIBS in the Makefile, where ... specifies + the directory containing the URT "librle.a" file (typically the + "lib" subdirectory of the URT distribution). + +Support for 12-bit-deep pixel data: + +The JPEG standard allows either 8-bit or 12-bit data precision. (For color, +this means 8 or 12 bits per channel, of course.) If you need to work with +deeper than 8-bit data, you can compile the IJG code for 12-bit operation. +To do so: + 1. In jmorecfg.h, define BITS_IN_JSAMPLE as 12 rather than 8. + 2. In jconfig.h, undefine BMP_SUPPORTED, RLE_SUPPORTED, and TARGA_SUPPORTED, + because the code for those formats doesn't handle 12-bit data and won't + even compile. (The PPM code does work, as explained below. The GIF + code works too; it scales 8-bit GIF data to and from 12-bit depth + automatically.) + 3. Compile. Don't expect "make test" to pass, since the supplied test + files are for 8-bit data. + +Currently, 12-bit support does not work on 16-bit-int machines. + +Note that a 12-bit version will not read 8-bit JPEG files, nor vice versa; +so you'll want to keep around a regular 8-bit compilation as well. +(Run-time selection of data depth, to allow a single copy that does both, +is possible but would probably slow things down considerably; it's very low +on our to-do list.) + +The PPM reader (rdppm.c) can read 12-bit data from either text-format or +binary-format PPM and PGM files. Binary-format PPM/PGM files which have a +maxval greater than 255 are assumed to use 2 bytes per sample, LSB first +(little-endian order). As of early 1995, 2-byte binary format is not +officially supported by the PBMPLUS library, but it is expected that a +future release of PBMPLUS will support it. Note that the PPM reader will +read files of any maxval regardless of the BITS_IN_JSAMPLE setting; incoming +data is automatically rescaled to either maxval=255 or maxval=4095 as +appropriate for the cjpeg bit depth. + +The PPM writer (wrppm.c) will normally write 2-byte binary PPM or PGM +format, maxval 4095, when compiled with BITS_IN_JSAMPLE=12. Since this +format is not yet widely supported, you can disable it by compiling wrppm.c +with PPM_NORAWWORD defined; then the data is scaled down to 8 bits to make a +standard 1-byte/sample PPM or PGM file. (Yes, this means still another copy +of djpeg to keep around. But hopefully you won't need it for very long. +Poskanzer's supposed to get that new PBMPLUS release out Real Soon Now.) + +Of course, if you are working with 12-bit data, you probably have it stored +in some other, nonstandard format. In that case you'll probably want to +write your own I/O modules to read and write your format. + +Note that a 12-bit version of cjpeg always runs in "-optimize" mode, in +order to generate valid Huffman tables. This is necessary because our +default Huffman tables only cover 8-bit data. + +Removing code: + +If you need to make a smaller version of the JPEG software, some optional +functions can be removed at compile time. See the xxx_SUPPORTED #defines in +jconfig.h and jmorecfg.h. If at all possible, we recommend that you leave in +decoder support for all valid JPEG files, to ensure that you can read anyone's +output. Taking out support for image file formats that you don't use is the +most painless way to make the programs smaller. Another possibility is to +remove some of the DCT methods: in particular, the "IFAST" method may not be +enough faster than the others to be worth keeping on your machine. (If you +do remove ISLOW or IFAST, be sure to redefine JDCT_DEFAULT or JDCT_FASTEST +to a supported method, by adding a #define in jconfig.h.) + + +OPTIMIZATION +============ + +Unless you own a Cray, you'll probably be interested in making the JPEG +software go as fast as possible. This section covers some machine-dependent +optimizations you may want to try. We suggest that before trying any of +this, you first get the basic installation to pass the self-test step. +Repeat the self-test after any optimization to make sure that you haven't +broken anything. + +The integer DCT routines perform a lot of multiplications. These +multiplications must yield 32-bit results, but none of their input values +are more than 16 bits wide. On many machines, notably the 680x0 and 80x86 +CPUs, a 16x16=>32 bit multiply instruction is faster than a full 32x32=>32 +bit multiply. Unfortunately there is no portable way to specify such a +multiplication in C, but some compilers can generate one when you use the +right combination of casts. See the MULTIPLYxxx macro definitions in +jdct.h. If your compiler makes "int" be 32 bits and "short" be 16 bits, +defining SHORTxSHORT_32 is fairly likely to work. When experimenting with +alternate definitions, be sure to test not only whether the code still works +(use the self-test), but also whether it is actually faster --- on some +compilers, alternate definitions may compute the right answer, yet be slower +than the default. Timing cjpeg on a large PGM (grayscale) input file is the +best way to check this, as the DCT will be the largest fraction of the runtime +in that mode. (Note: some of the distributed compiler-specific jconfig files +already contain #define switches to select appropriate MULTIPLYxxx +definitions.) + +If your machine has sufficiently fast floating point hardware, you may find +that the float DCT method is faster than the integer DCT methods, even +after tweaking the integer multiply macros. In that case you may want to +make the float DCT be the default method. (The only objection to this is +that float DCT results may vary slightly across machines.) To do that, add +"#define JDCT_DEFAULT JDCT_FLOAT" to jconfig.h. Even if you don't change +the default, you should redefine JDCT_FASTEST, which is the method selected +by djpeg's -fast switch. Don't forget to update the documentation files +(usage.doc and/or cjpeg.1, djpeg.1) to agree with what you've done. + +If access to "short" arrays is slow on your machine, it may be a win to +define type JCOEF as int rather than short. This will cost a good deal of +memory though, particularly in some multi-pass modes, so don't do it unless +you have memory to burn and short is REALLY slow. + +If your compiler can compile function calls in-line, make sure the INLINE +macro in jmorecfg.h is defined as the keyword that marks a function +inline-able. Some compilers have a switch that tells the compiler to inline +any function it thinks is profitable (e.g., -finline-functions for gcc). +Enabling such a switch is likely to make the compiled code bigger but faster. + +In general, it's worth trying the maximum optimization level of your compiler, +and experimenting with any optional optimizations such as loop unrolling. +(Unfortunately, far too many compilers have optimizer bugs ... be prepared to +back off if the code fails self-test.) If you do any experimentation along +these lines, please report the optimal settings to jpeg-info@uunet.uu.net so +we can mention them in future releases. Be sure to specify your machine and +compiler version. + + +HINTS FOR SPECIFIC SYSTEMS +========================== + +We welcome reports on changes needed for systems not mentioned here. Submit +'em to jpeg-info@uunet.uu.net. Also, if configure or ckconfig.c is wrong +about how to configure the JPEG software for your system, please let us know. + + +Acorn RISC OS: + +(Thanks to Simon Middleton for these hints on compiling with Desktop C.) +After renaming the files according to Acorn conventions, take a copy of +makefile.ansi, change all occurrences of 'libjpeg.a' to 'libjpeg.o' and +change these definitions as indicated: + +CFLAGS= -throwback -IC: -Wn +LDLIBS=C:o.Stubs +SYSDEPMEM=jmemansi.o +LN=Link +AR=LibFile -c -o + +Also add a new line '.c.o:; $(cc) $< $(cflags) -c -o $@'. Remove the +lines '$(RM) libjpeg.o' and '$(AR2) libjpeg.o' and the 'jconfig.h' +dependency section. + +Copy jconfig.doc to jconfig.h. Edit jconfig.h to define TWO_FILE_COMMANDLINE +and CHAR_IS_UNSIGNED. + +Run the makefile using !AMU not !Make. If you want to use the 'clean' and +'test' makefile entries then you will have to fiddle with the syntax a bit +and rename the test files. + + +Amiga: + +SAS C 6.50 reportedly is too buggy to compile the IJG code properly. +A patch to update to 6.51 is available from SAS or AmiNet FTP sites. + +The supplied config files are set up to use jmemname.c as the memory +manager, with temporary files being created on the device named by +"JPEGTMP:". + + +Atari ST/STE/TT: + +Copy the project files makcjpeg.st, makdjpeg.st, maktjpeg.st, and makljpeg.st +to cjpeg.prj, djpeg.prj, jpegtran.prj, and libjpeg.prj respectively. The +project files should work as-is with Pure C. For Turbo C, change library +filenames "pc..." to "tc..." in each project file. Note that libjpeg.prj +selects jmemansi.c as the recommended memory manager. You'll probably want to +adjust the DEFAULT_MAX_MEM setting --- you want it to be a couple hundred K +less than your normal free memory. Put "#define DEFAULT_MAX_MEM nnnn" into +jconfig.h to do this. + +To use the 68881/68882 coprocessor for the floating point DCT, add the +compiler option "-8" to the project files and replace pcfltlib.lib with +pc881lib.lib in cjpeg.prj and djpeg.prj. Or if you don't have a +coprocessor, you may prefer to remove the float DCT code by undefining +DCT_FLOAT_SUPPORTED in jmorecfg.h (since without a coprocessor, the float +code will be too slow to be useful). In that case, you can delete +pcfltlib.lib from the project files. + +Note that you must make libjpeg.lib before making cjpeg.ttp, djpeg.ttp, +or jpegtran.ttp. You'll have to perform the self-test by hand. + +We haven't bothered to include project files for rdjpgcom and wrjpgcom. +Those source files should just be compiled by themselves; they don't +depend on the JPEG library. + +There is a bug in some older versions of the Turbo C library which causes the +space used by temporary files created with "tmpfile()" not to be freed after +an abnormal program exit. If you check your disk afterwards, you will find +cluster chains that are allocated but not used by a file. This should not +happen in cjpeg/djpeg/jpegtran, since we enable a signal catcher to explicitly +close temp files before exiting. But if you use the JPEG library with your +own code, be sure to supply a signal catcher, or else use a different +system-dependent memory manager. + + +Cray: + +Should you be so fortunate as to be running JPEG on a Cray YMP, there is a +compiler bug in old versions of Cray's Standard C (prior to 3.1). If you +still have an old compiler, you'll need to insert a line reading +"#pragma novector" just before the loop + for (i = 1; i <= (int) htbl->bits[l]; i++) + huffsize[p++] = (char) l; +in fix_huff_tbl (in V5beta1, line 204 of jchuff.c and line 176 of jdhuff.c). +[This bug may or may not still occur with the current IJG code, but it's +probably a dead issue anyway...] + + +HP-UX: + +If you have HP-UX 7.05 or later with the "software development" C compiler, +you should run the compiler in ANSI mode. If using the configure script, +say + ./configure CC='cc -Aa' +(or -Ae if you prefer). If configuring by hand, use makefile.ansi and add +"-Aa" to the CFLAGS line in the makefile. + +If you have a pre-7.05 system, or if you are using the non-ANSI C compiler +delivered with a minimum HP-UX system, then you must use makefile.unix +(and do NOT add -Aa); or just run configure without the CC option. + +On HP 9000 series 800 machines, the HP C compiler is buggy in revisions prior +to A.08.07. If you get complaints about "not a typedef name", you'll have to +use makefile.unix, or run configure without the CC option. + + +Macintosh, generic comments: + +The supplied user-interface files (cjpeg.c, djpeg.c, etc) are set up to +provide a Unix-style command line interface. You can use this interface on +the Mac by means of the ccommand() library routine provided by Metrowerks +CodeWarrior or Think C. This is only appropriate for testing the library, +however; to make a user-friendly equivalent of cjpeg/djpeg you'd really want +to develop a Mac-style user interface. There isn't a complete example +available at the moment, but there are some helpful starting points: +1. Sam Bushell's free "To JPEG" applet provides drag-and-drop conversion to +JPEG under System 7 and later. This only illustrates how to use the +compression half of the library, but it does a very nice job of that part. +The CodeWarrior source code is available from http://www.pobox.com/~jsam. +2. Jim Brunner prepared a Mac-style user interface for both compression and +decompression. Unfortunately, it hasn't been updated since IJG v4, and +the library's API has changed considerably since then. Still it may be of +some help, particularly as a guide to compiling the IJG code under Think C. +Jim's code is available from the Info-Mac archives, at sumex-aim.stanford.edu +or mirrors thereof; see file /info-mac/dev/src/jpeg-convert-c.hqx. + +jmemmac.c is the recommended memory manager back end for Macintosh. It uses +NewPtr/DisposePtr instead of malloc/free, and has a Mac-specific +implementation of jpeg_mem_available(). It also creates temporary files that +follow Mac conventions. (That part of the code relies on System-7-or-later OS +functions. See the comments in jmemmac.c if you need to run it on System 6.) +NOTE that USE_MAC_MEMMGR must be defined in jconfig.h to use jmemmac.c. + +You can also use jmemnobs.c, if you don't care about handling images larger +than available memory. If you use any memory manager back end other than +jmemmac.c, we recommend replacing "malloc" and "free" by "NewPtr" and +"DisposePtr", because Mac C libraries often have peculiar implementations of +malloc/free. (For instance, free() may not return the freed space to the +Mac Memory Manager. This is undesirable for the IJG code because jmemmgr.c +already clumps space requests.) + + +Macintosh, Metrowerks CodeWarrior: + +The Unix-command-line-style interface can be used by defining USE_CCOMMAND. +You'll also need to define TWO_FILE_COMMANDLINE to avoid stdin/stdout. +This means that when using the cjpeg/djpeg programs, you'll have to type the +input and output file names in the "Arguments" text-edit box, rather than +using the file radio buttons. (Perhaps USE_FDOPEN or USE_SETMODE would +eliminate the problem, but I haven't heard from anyone who's tried it.) + +On 680x0 Macs, Metrowerks defines type "double" as a 10-byte IEEE extended +float. jmemmgr.c won't like this: it wants sizeof(ALIGN_TYPE) to be a power +of 2. Add "#define ALIGN_TYPE long" to jconfig.h to eliminate the complaint. + +The supplied configuration file jconfig.mac can be used for your jconfig.h; +it includes all the recommended symbol definitions. If you have AppleScript +installed, you can run the supplied script makeproj.mac to create CodeWarrior +project files for the library and the testbed applications, then build the +library and applications. (Thanks to Dan Sears and Don Agro for this nifty +hack, which saves us from trying to maintain CodeWarrior project files as part +of the IJG distribution...) + + +Macintosh, Think C: + +The documentation in Jim Brunner's "JPEG Convert" source code (see above) +includes detailed build instructions for Think C; it's probably somewhat +out of date for the current release, but may be helpful. + +If you want to build the minimal command line version, proceed as follows. +You'll have to prepare project files for the programs; we don't include any +in the distribution since they are not text files. Use the file lists in +any of the supplied makefiles as a guide. Also add the ANSI and Unix C +libraries in a separate segment. You may need to divide the JPEG files into +more than one segment; we recommend dividing compression and decompression +modules. Define USE_CCOMMAND in jconfig.h so that the ccommand() routine is +called. You must also define TWO_FILE_COMMANDLINE because stdin/stdout +don't handle binary data correctly. + +On 680x0 Macs, Think C defines type "double" as a 12-byte IEEE extended float. +jmemmgr.c won't like this: it wants sizeof(ALIGN_TYPE) to be a power of 2. +Add "#define ALIGN_TYPE long" to jconfig.h to eliminate the complaint. + +jconfig.mac should work as a jconfig.h configuration file for Think C, +but the makeproj.mac AppleScript script is specific to CodeWarrior. Sorry. + + +MIPS R3000: + +MIPS's cc version 1.31 has a rather nasty optimization bug. Don't use -O +if you have that compiler version. (Use "cc -V" to check the version.) +Note that the R3000 chip is found in workstations from DEC and others. + + +MS-DOS, generic comments for 16-bit compilers: + +The IJG code is designed to work well in 80x86 "small" or "medium" memory +models (i.e., data pointers are 16 bits unless explicitly declared "far"; +code pointers can be either size). You may be able to use small model to +compile cjpeg or djpeg by itself, but you will probably have to use medium +model for any larger application. This won't make much difference in +performance. You *will* take a noticeable performance hit if you use a +large-data memory model, and you should avoid "huge" model if at all +possible. Be sure that NEED_FAR_POINTERS is defined in jconfig.h if you use +a small-data memory model; be sure it is NOT defined if you use a large-data +model. (The supplied makefiles and jconfig files for Borland and Microsoft C +compile in medium model and define NEED_FAR_POINTERS.) + +The DOS-specific memory manager, jmemdos.c, should be used if possible. +It needs some assembly-code routines which are in jmemdosa.asm; make sure +your makefile assembles that file and includes it in the library. If you +don't have a suitable assembler, you can get pre-assembled object files for +jmemdosa by FTP from ftp.uu.net:/graphics/jpeg/jdosaobj.zip. (DOS-oriented +distributions of the IJG source code often include these object files.) + +When using jmemdos.c, jconfig.h must define USE_MSDOS_MEMMGR and must set +MAX_ALLOC_CHUNK to less than 64K (65520L is a typical value). If your +C library's far-heap malloc() can't allocate blocks that large, reduce +MAX_ALLOC_CHUNK to whatever it can handle. + +If you can't use jmemdos.c for some reason --- for example, because you +don't have an assembler to assemble jmemdosa.asm --- you'll have to fall +back to jmemansi.c or jmemname.c. You'll probably still need to set +MAX_ALLOC_CHUNK in jconfig.h, because most DOS C libraries won't malloc() +more than 64K at a time. IMPORTANT: if you use jmemansi.c or jmemname.c, +you will have to compile in a large-data memory model in order to get the +right stdio library. Too bad. + +wrjpgcom needs to be compiled in large model, because it malloc()s a 64KB +work area to hold the comment text. If your C library's malloc can't +handle that, reduce MAX_COM_LENGTH as necessary in wrjpgcom.c. + +Most MS-DOS compilers treat stdin/stdout as text files, so you must use +two-file command line style. But if your compiler has either fdopen() or +setmode(), you can use one-file style if you like. To do this, define +USE_SETMODE or USE_FDOPEN so that stdin/stdout will be set to binary mode. +(USE_SETMODE seems to work with more DOS compilers than USE_FDOPEN.) You +should test that I/O through stdin/stdout produces the same results as I/O +to explicitly named files... the "make test" procedures in the supplied +makefiles do NOT use stdin/stdout. + + +MS-DOS, generic comments for 32-bit compilers: + +None of the above comments about memory models apply if you are using a +32-bit flat-memory-space environment, such as DJGPP or Watcom C. (And you +should use one if you have it, as performance will be much better than +8086-compatible code!) For flat-memory-space compilers, do NOT define +NEED_FAR_POINTERS, and do NOT use jmemdos.c. Use jmemnobs.c if the +environment supplies adequate virtual memory, otherwise use jmemansi.c or +jmemname.c. + +You'll still need to be careful about binary I/O through stdin/stdout. +See the last paragraph of the previous section. + + +MS-DOS, Borland C: + +Be sure to convert all the source files to DOS text format (CR/LF newlines). +Although Borland C will often work OK with unmodified Unix (LF newlines) +source files, sometimes it will give bogus compile errors. +"Illegal character '#'" is the most common such error. (This is true with +Borland C 3.1, but perhaps is fixed in newer releases.) + +If you want one-file command line style, just undefine TWO_FILE_COMMANDLINE. +jconfig.bcc already includes #define USE_SETMODE to make this work. +(fdopen does not work correctly.) + + +MS-DOS, Microsoft C: + +makefile.mc6 works with Microsoft C, DOS Visual C++, etc. It should only +be used if you want to build a 16-bit (small or medium memory model) program. + +If you want one-file command line style, just undefine TWO_FILE_COMMANDLINE. +jconfig.mc6 already includes #define USE_SETMODE to make this work. +(fdopen does not work correctly.) + +Note that this makefile assumes that the working copy of itself is called +"makefile". If you want to call it something else, say "makefile.mak", +be sure to adjust the dependency line that reads "$(RFILE) : makefile". +Otherwise the make will fail because it doesn't know how to create "makefile". +Worse, some releases of Microsoft's make utilities give an incorrect error +message in this situation. + +Old versions of MS C fail with an "out of macro expansion space" error +because they can't cope with the macro TRACEMS8 (defined in jerror.h). +If this happens to you, the easiest solution is to change TRACEMS8 to +expand to nothing. You'll lose the ability to dump out JPEG coefficient +tables with djpeg -debug -debug, but at least you can compile. + +Original MS C 6.0 is very buggy; it compiles incorrect code unless you turn +off optimization entirely (remove -O from CFLAGS). 6.00A is better, but it +still generates bad code if you enable loop optimizations (-Ol or -Ox). + +MS C 8.0 crashes when compiling jquant1.c with optimization switch /Oo ... +which is on by default. To work around this bug, compile that one file +with /Oo-. + + +Microsoft Windows (all versions), generic comments: + +Some Windows system include files define typedef boolean as "unsigned char". +The IJG code also defines typedef boolean, but we make it "int" by default. +This doesn't affect the IJG programs because we don't import those Windows +include files. But if you use the JPEG library in your own program, and some +of your program's files import one definition of boolean while some import the +other, you can get all sorts of mysterious problems. A good preventive step +is to make the IJG library use "unsigned char" for boolean. To do that, +add something like this to your jconfig.h file: + /* Define "boolean" as unsigned char, not int, per Windows custom */ + #ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */ + typedef unsigned char boolean; + #endif + #define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */ +(This is already in jconfig.vc, by the way.) + +windef.h contains the declarations + #define far + #define FAR far +Since jmorecfg.h tries to define FAR as empty, you may get a compiler +warning if you include both jpeglib.h and windef.h (which windows.h +includes). To suppress the warning, you can put "#ifndef FAR"/"#endif" +around the line "#define FAR" in jmorecfg.h. + +When using the library in a Windows application, you will almost certainly +want to modify or replace the error handler module jerror.c, since our +default error handler does a couple of inappropriate things: + 1. it tries to write error and warning messages on stderr; + 2. in event of a fatal error, it exits by calling exit(). + +A simple stopgap solution for problem 1 is to replace the line + fprintf(stderr, "%s\n", buffer); +(in output_message in jerror.c) with + MessageBox(GetActiveWindow(),buffer,"JPEG Error",MB_OK|MB_ICONERROR); +It's highly recommended that you at least do that much, since otherwise +error messages will disappear into nowhere. (Beginning with IJG v6b, this +code is already present in jerror.c; just define USE_WINDOWS_MESSAGEBOX in +jconfig.h to enable it.) + +The proper solution for problem 2 is to return control to your calling +application after a library error. This can be done with the setjmp/longjmp +technique discussed in libjpeg.doc and illustrated in example.c. (NOTE: +some older Windows C compilers provide versions of setjmp/longjmp that +don't actually work under Windows. You may need to use the Windows system +functions Catch and Throw instead.) + +The recommended memory manager under Windows is jmemnobs.c; in other words, +let Windows do any virtual memory management needed. You should NOT use +jmemdos.c nor jmemdosa.asm under Windows. + +For Windows 3.1, we recommend compiling in medium or large memory model; +for newer Windows versions, use a 32-bit flat memory model. (See the MS-DOS +sections above for more info about memory models.) In the 16-bit memory +models only, you'll need to put + #define MAX_ALLOC_CHUNK 65520L /* Maximum request to malloc() */ +into jconfig.h to limit allocation chunks to 64Kb. (Without that, you'd +have to use huge memory model, which slows things down unnecessarily.) +jmemnobs.c works without modification in large or flat memory models, but to +use medium model, you need to modify its jpeg_get_large and jpeg_free_large +routines to allocate far memory. In any case, you might like to replace +its calls to malloc and free with direct calls on Windows memory allocation +functions. + +You may also want to modify jdatasrc.c and jdatadst.c to use Windows file +operations rather than fread/fwrite. This is only necessary if your C +compiler doesn't provide a competent implementation of C stdio functions. + +You might want to tweak the RGB_xxx macros in jmorecfg.h so that the library +will accept or deliver color pixels in BGR sample order, not RGB; BGR order +is usually more convenient under Windows. Note that this change will break +the sample applications cjpeg/djpeg, but the library itself works fine. + + +Many people want to convert the IJG library into a DLL. This is reasonably +straightforward, but watch out for the following: + + 1. Don't try to compile as a DLL in small or medium memory model; use +large model, or even better, 32-bit flat model. Many places in the IJG code +assume the address of a local variable is an ordinary (not FAR) pointer; +that isn't true in a medium-model DLL. + + 2. Microsoft C cannot pass file pointers between applications and DLLs. +(See Microsoft Knowledge Base, PSS ID Number Q50336.) So jdatasrc.c and +jdatadst.c don't work if you open a file in your application and then pass +the pointer to the DLL. One workaround is to make jdatasrc.c/jdatadst.c +part of your main application rather than part of the DLL. + + 3. You'll probably need to modify the macros GLOBAL() and EXTERN() to +attach suitable linkage keywords to the exported routine names. Similarly, +you'll want to modify METHODDEF() and JMETHOD() to ensure function pointers +are declared in a way that lets application routines be called back through +the function pointers. These macros are in jmorecfg.h. Typical definitions +for a 16-bit DLL are: + #define GLOBAL(type) type _far _pascal _loadds _export + #define EXTERN(type) extern type _far _pascal _loadds + #define METHODDEF(type) static type _far _pascal + #define JMETHOD(type,methodname,arglist) \ + type (_far _pascal *methodname) arglist +For a 32-bit DLL you may want something like + #define GLOBAL(type) __declspec(dllexport) type + #define EXTERN(type) extern __declspec(dllexport) type +Although not all the GLOBAL routines are actually intended to be called by +the application, the performance cost of making them all DLL entry points is +negligible. + +The unmodified IJG library presents a very C-specific application interface, +so the resulting DLL is only usable from C or C++ applications. There has +been some talk of writing wrapper code that would present a simpler interface +usable from other languages, such as Visual Basic. This is on our to-do list +but hasn't been very high priority --- any volunteers out there? + + +Microsoft Windows, Borland C: + +The provided jconfig.bcc should work OK in a 32-bit Windows environment, +but you'll need to tweak it in a 16-bit environment (you'd need to define +NEED_FAR_POINTERS and MAX_ALLOC_CHUNK). Beware that makefile.bcc will need +alteration if you want to use it for Windows --- in particular, you should +use jmemnobs.c not jmemdos.c under Windows. + +Borland C++ 4.5 fails with an internal compiler error when trying to compile +jdmerge.c in 32-bit mode. If enough people complain, perhaps Borland will fix +it. In the meantime, the simplest known workaround is to add a redundant +definition of the variable range_limit in h2v1_merged_upsample(), at the head +of the block that handles odd image width (about line 268 in v6 jdmerge.c): + /* If image width is odd, do the last output column separately */ + if (cinfo->output_width & 1) { + register JSAMPLE * range_limit = cinfo->sample_range_limit; /* ADD THIS */ + cb = GETJSAMPLE(*inptr1); +Pretty bizarre, especially since the very similar routine h2v2_merged_upsample +doesn't trigger the bug. +Recent reports suggest that this bug does not occur with "bcc32a" (the +Pentium-optimized version of the compiler). + +Another report from a user of Borland C 4.5 was that incorrect code (leading +to a color shift in processed images) was produced if any of the following +optimization switch combinations were used: + -Ot -Og + -Ot -Op + -Ot -Om +So try backing off on optimization if you see such a problem. (Are there +several different releases all numbered "4.5"??) + + +Microsoft Windows, Microsoft Visual C++: + +jconfig.vc should work OK with any Microsoft compiler for a 32-bit memory +model. makefile.vc is intended for command-line use. (If you are using +the Developer Studio environment, you may prefer the DevStudio project +files; see below.) + +Some users feel that it's easier to call the library from C++ code if you +force VC++ to treat the library as C++ code, which you can do by renaming +all the *.c files to *.cpp (and adjusting the makefile to match). This +avoids the need to put extern "C" { ... } around #include "jpeglib.h" in +your C++ application. + + +Microsoft Windows, Microsoft Developer Studio: + +We include makefiles that should work as project files in DevStudio 4.2 or +later. There is a library makefile that builds the IJG library as a static +Win32 library, and an application makefile that builds the sample applications +as Win32 console applications. (Even if you only want the library, we +recommend building the applications so that you can run the self-test.) + +To use: +1. Copy jconfig.vc to jconfig.h, makelib.ds to jpeg.mak, and + makeapps.ds to apps.mak. (Note that the renaming is critical!) +2. Click on the .mak files to construct project workspaces. + (If you are using DevStudio more recent than 4.2, you'll probably + get a message saying that the makefiles are being updated.) +3. Build the library project, then the applications project. +4. Move the application .exe files from `app`\Release to an + appropriate location on your path. +5. To perform the self-test, execute the command line + NMAKE /f makefile.vc test + + +OS/2, Borland C++: + +Watch out for optimization bugs in older Borland compilers; you may need +to back off the optimization switch settings. See the comments in +makefile.bcc. + + +SGI: + +On some SGI systems, you may need to set "AR2= ar -ts" in the Makefile. +If you are using configure, you can do this by saying + ./configure RANLIB='ar -ts' +This change is not needed on all SGIs. Use it only if the make fails at the +stage of linking the completed programs. + +On the MIPS R4000 architecture (Indy, etc.), the compiler option "-mips2" +reportedly speeds up the float DCT method substantially, enough to make it +faster than the default int method (but still slower than the fast int +method). If you use -mips2, you may want to alter the default DCT method to +be float. To do this, put "#define JDCT_DEFAULT JDCT_FLOAT" in jconfig.h. + + +VMS: + +On an Alpha/VMS system with MMS, be sure to use the "/Marco=Alpha=1" +qualifier with MMS when building the JPEG package. + +VAX/VMS v5.5-1 may have problems with the test step of the build procedure +reporting differences when it compares the original and test images. If the +error points to the last block of the files, it is most likely bogus and may +be safely ignored. It seems to be because the files are Stream_LF and +Backup/Compare has difficulty with the (presumably) null padded files. +This problem was not observed on VAX/VMS v6.1 or AXP/VMS v6.1. diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jcapimin.c b/lc-continuity/mk4/modimage/jpeg-6b/jcapimin.c new file mode 100644 index 0000000000000000000000000000000000000000..54fb8c58c5656947c285fc8d98d5c23815aec1eb --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jcapimin.c @@ -0,0 +1,280 @@ +/* + * jcapimin.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains application interface code for the compression half + * of the JPEG library. These are the "minimum" API routines that may be + * needed in either the normal full-compression case or the transcoding-only + * case. + * + * Most of the routines intended to be called directly by an application + * are in this file or in jcapistd.c. But also see jcparam.c for + * parameter-setup helper routines, jcomapi.c for routines shared by + * compression and decompression, and jctrans.c for the transcoding case. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* + * Initialization of a JPEG compression object. + * The error manager must already be set up (in case memory manager fails). + */ + +GLOBAL(void) +jpeg_CreateCompress (j_compress_ptr cinfo, int version, size_t structsize) +{ + int i; + + /* Guard against version mismatches between library and caller. */ + cinfo->mem = NULL; /* so jpeg_destroy knows mem mgr not called */ + if (version != JPEG_LIB_VERSION) + ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version); + if (structsize != SIZEOF(struct jpeg_compress_struct)) + ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE, + (int) SIZEOF(struct jpeg_compress_struct), (int) structsize); + + /* For debugging purposes, we zero the whole master structure. + * But the application has already set the err pointer, and may have set + * client_data, so we have to save and restore those fields. + * Note: if application hasn't set client_data, tools like Purify may + * complain here. + */ + { + struct jpeg_error_mgr * err = cinfo->err; + void * client_data = cinfo->client_data; /* ignore Purify complaint here */ + MEMZERO(cinfo, SIZEOF(struct jpeg_compress_struct)); + cinfo->err = err; + cinfo->client_data = client_data; + } + cinfo->is_decompressor = FALSE; + + /* Initialize a memory manager instance for this object */ + jinit_memory_mgr((j_common_ptr) cinfo); + + /* Zero out pointers to permanent structures. */ + cinfo->progress = NULL; + cinfo->dest = NULL; + + cinfo->comp_info = NULL; + + for (i = 0; i < NUM_QUANT_TBLS; i++) + cinfo->quant_tbl_ptrs[i] = NULL; + + for (i = 0; i < NUM_HUFF_TBLS; i++) { + cinfo->dc_huff_tbl_ptrs[i] = NULL; + cinfo->ac_huff_tbl_ptrs[i] = NULL; + } + + cinfo->script_space = NULL; + + cinfo->input_gamma = 1.0; /* in case application forgets */ + + /* OK, I'm ready */ + cinfo->global_state = CSTATE_START; +} + + +/* + * Destruction of a JPEG compression object + */ + +GLOBAL(void) +jpeg_destroy_compress (j_compress_ptr cinfo) +{ + jpeg_destroy((j_common_ptr) cinfo); /* use common routine */ +} + + +/* + * Abort processing of a JPEG compression operation, + * but don't destroy the object itself. + */ + +GLOBAL(void) +jpeg_abort_compress (j_compress_ptr cinfo) +{ + jpeg_abort((j_common_ptr) cinfo); /* use common routine */ +} + + +/* + * Forcibly suppress or un-suppress all quantization and Huffman tables. + * Marks all currently defined tables as already written (if suppress) + * or not written (if !suppress). This will control whether they get emitted + * by a subsequent jpeg_start_compress call. + * + * This routine is exported for use by applications that want to produce + * abbreviated JPEG datastreams. It logically belongs in jcparam.c, but + * since it is called by jpeg_start_compress, we put it here --- otherwise + * jcparam.o would be linked whether the application used it or not. + */ + +GLOBAL(void) +jpeg_suppress_tables (j_compress_ptr cinfo, boolean suppress) +{ + int i; + JQUANT_TBL * qtbl; + JHUFF_TBL * htbl; + + for (i = 0; i < NUM_QUANT_TBLS; i++) { + if ((qtbl = cinfo->quant_tbl_ptrs[i]) != NULL) + qtbl->sent_table = suppress; + } + + for (i = 0; i < NUM_HUFF_TBLS; i++) { + if ((htbl = cinfo->dc_huff_tbl_ptrs[i]) != NULL) + htbl->sent_table = suppress; + if ((htbl = cinfo->ac_huff_tbl_ptrs[i]) != NULL) + htbl->sent_table = suppress; + } +} + + +/* + * Finish JPEG compression. + * + * If a multipass operating mode was selected, this may do a great deal of + * work including most of the actual output. + */ + +GLOBAL(void) +jpeg_finish_compress (j_compress_ptr cinfo) +{ + JDIMENSION iMCU_row; + + if (cinfo->global_state == CSTATE_SCANNING || + cinfo->global_state == CSTATE_RAW_OK) { + /* Terminate first pass */ + if (cinfo->next_scanline < cinfo->image_height) + ERREXIT(cinfo, JERR_TOO_LITTLE_DATA); + (*cinfo->master->finish_pass) (cinfo); + } else if (cinfo->global_state != CSTATE_WRCOEFS) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + /* Perform any remaining passes */ + while (! cinfo->master->is_last_pass) { + (*cinfo->master->prepare_for_pass) (cinfo); + for (iMCU_row = 0; iMCU_row < cinfo->total_iMCU_rows; iMCU_row++) { + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) iMCU_row; + cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + /* We bypass the main controller and invoke coef controller directly; + * all work is being done from the coefficient buffer. + */ + if (! (*cinfo->coef->compress_data) (cinfo, (JSAMPIMAGE) NULL)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); + } + (*cinfo->master->finish_pass) (cinfo); + } + /* Write EOI, do final cleanup */ + (*cinfo->marker->write_file_trailer) (cinfo); + (*cinfo->dest->term_destination) (cinfo); + /* We can use jpeg_abort to release memory and reset global_state */ + jpeg_abort((j_common_ptr) cinfo); +} + + +/* + * Write a special marker. + * This is only recommended for writing COM or APPn markers. + * Must be called after jpeg_start_compress() and before + * first call to jpeg_write_scanlines() or jpeg_write_raw_data(). + */ + +GLOBAL(void) +jpeg_write_marker (j_compress_ptr cinfo, int marker, + const JOCTET *dataptr, unsigned int datalen) +{ + JMETHOD(void, write_marker_byte, (j_compress_ptr info, int val)); + + if (cinfo->next_scanline != 0 || + (cinfo->global_state != CSTATE_SCANNING && + cinfo->global_state != CSTATE_RAW_OK && + cinfo->global_state != CSTATE_WRCOEFS)) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + (*cinfo->marker->write_marker_header) (cinfo, marker, datalen); + write_marker_byte = cinfo->marker->write_marker_byte; /* copy for speed */ + while (datalen--) { + (*write_marker_byte) (cinfo, *dataptr); + dataptr++; + } +} + +/* Same, but piecemeal. */ + +GLOBAL(void) +jpeg_write_m_header (j_compress_ptr cinfo, int marker, unsigned int datalen) +{ + if (cinfo->next_scanline != 0 || + (cinfo->global_state != CSTATE_SCANNING && + cinfo->global_state != CSTATE_RAW_OK && + cinfo->global_state != CSTATE_WRCOEFS)) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + (*cinfo->marker->write_marker_header) (cinfo, marker, datalen); +} + +GLOBAL(void) +jpeg_write_m_byte (j_compress_ptr cinfo, int val) +{ + (*cinfo->marker->write_marker_byte) (cinfo, val); +} + + +/* + * Alternate compression function: just write an abbreviated table file. + * Before calling this, all parameters and a data destination must be set up. + * + * To produce a pair of files containing abbreviated tables and abbreviated + * image data, one would proceed as follows: + * + * initialize JPEG object + * set JPEG parameters + * set destination to table file + * jpeg_write_tables(cinfo); + * set destination to image file + * jpeg_start_compress(cinfo, FALSE); + * write data... + * jpeg_finish_compress(cinfo); + * + * jpeg_write_tables has the side effect of marking all tables written + * (same as jpeg_suppress_tables(..., TRUE)). Thus a subsequent start_compress + * will not re-emit the tables unless it is passed write_all_tables=TRUE. + */ + +GLOBAL(void) +jpeg_write_tables (j_compress_ptr cinfo) +{ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + /* (Re)initialize error mgr and destination modules */ + (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); + (*cinfo->dest->init_destination) (cinfo); + /* Initialize the marker writer ... bit of a crock to do it here. */ + jinit_marker_writer(cinfo); + /* Write them tables! */ + (*cinfo->marker->write_tables_only) (cinfo); + /* And clean up. */ + (*cinfo->dest->term_destination) (cinfo); + /* + * In library releases up through v6a, we called jpeg_abort() here to free + * any working memory allocated by the destination manager and marker + * writer. Some applications had a problem with that: they allocated space + * of their own from the library memory manager, and didn't want it to go + * away during write_tables. So now we do nothing. This will cause a + * memory leak if an app calls write_tables repeatedly without doing a full + * compression cycle or otherwise resetting the JPEG object. However, that + * seems less bad than unexpectedly freeing memory in the normal case. + * An app that prefers the old behavior can call jpeg_abort for itself after + * each call to jpeg_write_tables(). + */ +} diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jcapistd.c b/lc-continuity/mk4/modimage/jpeg-6b/jcapistd.c new file mode 100644 index 0000000000000000000000000000000000000000..c0320b1b190f5b3b14e9f903bcd0a5cba8c84ef2 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jcapistd.c @@ -0,0 +1,161 @@ +/* + * jcapistd.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains application interface code for the compression half + * of the JPEG library. These are the "standard" API routines that are + * used in the normal full-compression case. They are not used by a + * transcoding-only application. Note that if an application links in + * jpeg_start_compress, it will end up linking in the entire compressor. + * We thus must separate this file from jcapimin.c to avoid linking the + * whole compression library into a transcoder. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* + * Compression initialization. + * Before calling this, all parameters and a data destination must be set up. + * + * We require a write_all_tables parameter as a failsafe check when writing + * multiple datastreams from the same compression object. Since prior runs + * will have left all the tables marked sent_table=TRUE, a subsequent run + * would emit an abbreviated stream (no tables) by default. This may be what + * is wanted, but for safety's sake it should not be the default behavior: + * programmers should have to make a deliberate choice to emit abbreviated + * images. Therefore the documentation and examples should encourage people + * to pass write_all_tables=TRUE; then it will take active thought to do the + * wrong thing. + */ + +GLOBAL(void) +jpeg_start_compress (j_compress_ptr cinfo, boolean write_all_tables) +{ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + if (write_all_tables) + jpeg_suppress_tables(cinfo, FALSE); /* mark all tables to be written */ + + /* (Re)initialize error mgr and destination modules */ + (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); + (*cinfo->dest->init_destination) (cinfo); + /* Perform master selection of active modules */ + jinit_compress_master(cinfo); + /* Set up for the first pass */ + (*cinfo->master->prepare_for_pass) (cinfo); + /* Ready for application to drive first pass through jpeg_write_scanlines + * or jpeg_write_raw_data. + */ + cinfo->next_scanline = 0; + cinfo->global_state = (cinfo->raw_data_in ? CSTATE_RAW_OK : CSTATE_SCANNING); +} + + +/* + * Write some scanlines of data to the JPEG compressor. + * + * The return value will be the number of lines actually written. + * This should be less than the supplied num_lines only in case that + * the data destination module has requested suspension of the compressor, + * or if more than image_height scanlines are passed in. + * + * Note: we warn about excess calls to jpeg_write_scanlines() since + * this likely signals an application programmer error. However, + * excess scanlines passed in the last valid call are *silently* ignored, + * so that the application need not adjust num_lines for end-of-image + * when using a multiple-scanline buffer. + */ + +GLOBAL(JDIMENSION) +jpeg_write_scanlines (j_compress_ptr cinfo, JSAMPARRAY scanlines, + JDIMENSION num_lines) +{ + JDIMENSION row_ctr, rows_left; + + if (cinfo->global_state != CSTATE_SCANNING) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + if (cinfo->next_scanline >= cinfo->image_height) + WARNMS(cinfo, JWRN_TOO_MUCH_DATA); + + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) cinfo->next_scanline; + cinfo->progress->pass_limit = (long) cinfo->image_height; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + + /* Give master control module another chance if this is first call to + * jpeg_write_scanlines. This lets output of the frame/scan headers be + * delayed so that application can write COM, etc, markers between + * jpeg_start_compress and jpeg_write_scanlines. + */ + if (cinfo->master->call_pass_startup) + (*cinfo->master->pass_startup) (cinfo); + + /* Ignore any extra scanlines at bottom of image. */ + rows_left = cinfo->image_height - cinfo->next_scanline; + if (num_lines > rows_left) + num_lines = rows_left; + + row_ctr = 0; + (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, num_lines); + cinfo->next_scanline += row_ctr; + return row_ctr; +} + + +/* + * Alternate entry point to write raw data. + * Processes exactly one iMCU row per call, unless suspended. + */ + +GLOBAL(JDIMENSION) +jpeg_write_raw_data (j_compress_ptr cinfo, JSAMPIMAGE data, + JDIMENSION num_lines) +{ + JDIMENSION lines_per_iMCU_row; + + if (cinfo->global_state != CSTATE_RAW_OK) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + if (cinfo->next_scanline >= cinfo->image_height) { + WARNMS(cinfo, JWRN_TOO_MUCH_DATA); + return 0; + } + + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) cinfo->next_scanline; + cinfo->progress->pass_limit = (long) cinfo->image_height; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + + /* Give master control module another chance if this is first call to + * jpeg_write_raw_data. This lets output of the frame/scan headers be + * delayed so that application can write COM, etc, markers between + * jpeg_start_compress and jpeg_write_raw_data. + */ + if (cinfo->master->call_pass_startup) + (*cinfo->master->pass_startup) (cinfo); + + /* Verify that at least one iMCU row has been passed. */ + lines_per_iMCU_row = cinfo->max_v_samp_factor * DCTSIZE; + if (num_lines < lines_per_iMCU_row) + ERREXIT(cinfo, JERR_BUFFER_SIZE); + + /* Directly compress the row. */ + if (! (*cinfo->coef->compress_data) (cinfo, data)) { + /* If compressor did not consume the whole row, suspend processing. */ + return 0; + } + + /* OK, we processed one iMCU row. */ + cinfo->next_scanline += lines_per_iMCU_row; + return lines_per_iMCU_row; +} diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jccoefct.c b/lc-continuity/mk4/modimage/jpeg-6b/jccoefct.c new file mode 100644 index 0000000000000000000000000000000000000000..1963ddb61b15689e36e3f1774007d3583b787a26 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jccoefct.c @@ -0,0 +1,449 @@ +/* + * jccoefct.c + * + * Copyright (C) 1994-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the coefficient buffer controller for compression. + * This controller is the top level of the JPEG compressor proper. + * The coefficient buffer lies between forward-DCT and entropy encoding steps. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* We use a full-image coefficient buffer when doing Huffman optimization, + * and also for writing multiple-scan JPEG files. In all cases, the DCT + * step is run during the first pass, and subsequent passes need only read + * the buffered coefficients. + */ +#ifdef ENTROPY_OPT_SUPPORTED +#define FULL_COEF_BUFFER_SUPPORTED +#else +#ifdef C_MULTISCAN_FILES_SUPPORTED +#define FULL_COEF_BUFFER_SUPPORTED +#endif +#endif + + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_c_coef_controller pub; /* public fields */ + + JDIMENSION iMCU_row_num; /* iMCU row # within image */ + JDIMENSION mcu_ctr; /* counts MCUs processed in current row */ + int MCU_vert_offset; /* counts MCU rows within iMCU row */ + int MCU_rows_per_iMCU_row; /* number of such rows needed */ + + /* For single-pass compression, it's sufficient to buffer just one MCU + * (although this may prove a bit slow in practice). We allocate a + * workspace of C_MAX_BLOCKS_IN_MCU coefficient blocks, and reuse it for each + * MCU constructed and sent. (On 80x86, the workspace is FAR even though + * it's not really very big; this is to keep the module interfaces unchanged + * when a large coefficient buffer is necessary.) + * In multi-pass modes, this array points to the current MCU's blocks + * within the virtual arrays. + */ + JBLOCKROW MCU_buffer[C_MAX_BLOCKS_IN_MCU]; + + /* In multi-pass modes, we need a virtual block array for each component. */ + jvirt_barray_ptr whole_image[MAX_COMPONENTS]; +} my_coef_controller; + +typedef my_coef_controller * my_coef_ptr; + + +/* Forward declarations */ +METHODDEF(boolean) compress_data + JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); +#ifdef FULL_COEF_BUFFER_SUPPORTED +METHODDEF(boolean) compress_first_pass + JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); +METHODDEF(boolean) compress_output + JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); +#endif + + +LOCAL(void) +start_iMCU_row (j_compress_ptr cinfo) +/* Reset within-iMCU-row counters for a new row */ +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + + /* In an interleaved scan, an MCU row is the same as an iMCU row. + * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. + * But at the bottom of the image, process only what's left. + */ + if (cinfo->comps_in_scan > 1) { + coef->MCU_rows_per_iMCU_row = 1; + } else { + if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1)) + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; + else + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; + } + + coef->mcu_ctr = 0; + coef->MCU_vert_offset = 0; +} + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + + coef->iMCU_row_num = 0; + start_iMCU_row(cinfo); + + switch (pass_mode) { + case JBUF_PASS_THRU: + if (coef->whole_image[0] != NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + coef->pub.compress_data = compress_data; + break; +#ifdef FULL_COEF_BUFFER_SUPPORTED + case JBUF_SAVE_AND_PASS: + if (coef->whole_image[0] == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + coef->pub.compress_data = compress_first_pass; + break; + case JBUF_CRANK_DEST: + if (coef->whole_image[0] == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + coef->pub.compress_data = compress_output; + break; +#endif + default: + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + break; + } +} + + +/* + * Process some data in the single-pass case. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor block rows for each component in the image. + * Returns TRUE if the iMCU row is completed, FALSE if suspended. + * + * NB: input_buf contains a plane for each component in image, + * which we index according to the component's SOF position. + */ + +METHODDEF(boolean) +compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + int blkn, bi, ci, yindex, yoffset, blockcnt; + JDIMENSION ypos, xpos; + jpeg_component_info *compptr; + + /* Loop to write as much as one whole iMCU row */ + for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; + yoffset++) { + for (MCU_col_num = coef->mcu_ctr; MCU_col_num <= last_MCU_col; + MCU_col_num++) { + /* Determine where data comes from in input_buf and do the DCT thing. + * Each call on forward_DCT processes a horizontal row of DCT blocks + * as wide as an MCU; we rely on having allocated the MCU_buffer[] blocks + * sequentially. Dummy blocks at the right or bottom edge are filled in + * specially. The data in them does not matter for image reconstruction, + * so we fill them with values that will encode to the smallest amount of + * data, viz: all zeroes in the AC entries, DC entries equal to previous + * block's DC value. (Thanks to Thomas Kinsman for this idea.) + */ + blkn = 0; + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width + : compptr->last_col_width; + xpos = MCU_col_num * compptr->MCU_sample_width; + ypos = yoffset * DCTSIZE; /* ypos == (yoffset+yindex) * DCTSIZE */ + for (yindex = 0; yindex < compptr->MCU_height; yindex++) { + if (coef->iMCU_row_num < last_iMCU_row || + yoffset+yindex < compptr->last_row_height) { + (*cinfo->fdct->forward_DCT) (cinfo, compptr, + input_buf[compptr->component_index], + coef->MCU_buffer[blkn], + ypos, xpos, (JDIMENSION) blockcnt); + if (blockcnt < compptr->MCU_width) { + /* Create some dummy blocks at the right edge of the image. */ + jzero_far((void FAR *) coef->MCU_buffer[blkn + blockcnt], + (compptr->MCU_width - blockcnt) * SIZEOF(JBLOCK)); + for (bi = blockcnt; bi < compptr->MCU_width; bi++) { + coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn+bi-1][0][0]; + } + } + } else { + /* Create a row of dummy blocks at the bottom of the image. */ + jzero_far((void FAR *) coef->MCU_buffer[blkn], + compptr->MCU_width * SIZEOF(JBLOCK)); + for (bi = 0; bi < compptr->MCU_width; bi++) { + coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn-1][0][0]; + } + } + blkn += compptr->MCU_width; + ypos += DCTSIZE; + } + } + /* Try to write the MCU. In event of a suspension failure, we will + * re-DCT the MCU on restart (a bit inefficient, could be fixed...) + */ + if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) { + /* Suspension forced; update state counters and exit */ + coef->MCU_vert_offset = yoffset; + coef->mcu_ctr = MCU_col_num; + return FALSE; + } + } + /* Completed an MCU row, but perhaps not an iMCU row */ + coef->mcu_ctr = 0; + } + /* Completed the iMCU row, advance counters for next one */ + coef->iMCU_row_num++; + start_iMCU_row(cinfo); + return TRUE; +} + + +#ifdef FULL_COEF_BUFFER_SUPPORTED + +/* + * Process some data in the first pass of a multi-pass case. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor block rows for each component in the image. + * This amount of data is read from the source buffer, DCT'd and quantized, + * and saved into the virtual arrays. We also generate suitable dummy blocks + * as needed at the right and lower edges. (The dummy blocks are constructed + * in the virtual arrays, which have been padded appropriately.) This makes + * it possible for subsequent passes not to worry about real vs. dummy blocks. + * + * We must also emit the data to the entropy encoder. This is conveniently + * done by calling compress_output() after we've loaded the current strip + * of the virtual arrays. + * + * NB: input_buf contains a plane for each component in image. All + * components are DCT'd and loaded into the virtual arrays in this pass. + * However, it may be that only a subset of the components are emitted to + * the entropy encoder during this first pass; be careful about looking + * at the scan-dependent variables (MCU dimensions, etc). + */ + +METHODDEF(boolean) +compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + JDIMENSION blocks_across, MCUs_across, MCUindex; + int bi, ci, h_samp_factor, block_row, block_rows, ndummy; + JCOEF lastDC; + jpeg_component_info *compptr; + JBLOCKARRAY buffer; + JBLOCKROW thisblockrow, lastblockrow; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Align the virtual buffer for this component. */ + buffer = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[ci], + coef->iMCU_row_num * compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, TRUE); + /* Count non-dummy DCT block rows in this iMCU row. */ + if (coef->iMCU_row_num < last_iMCU_row) + block_rows = compptr->v_samp_factor; + else { + /* NB: can't use last_row_height here, since may not be set! */ + block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor); + if (block_rows == 0) block_rows = compptr->v_samp_factor; + } + blocks_across = compptr->width_in_blocks; + h_samp_factor = compptr->h_samp_factor; + /* Count number of dummy blocks to be added at the right margin. */ + ndummy = (int) (blocks_across % h_samp_factor); + if (ndummy > 0) + ndummy = h_samp_factor - ndummy; + /* Perform DCT for all non-dummy blocks in this iMCU row. Each call + * on forward_DCT processes a complete horizontal row of DCT blocks. + */ + for (block_row = 0; block_row < block_rows; block_row++) { + thisblockrow = buffer[block_row]; + (*cinfo->fdct->forward_DCT) (cinfo, compptr, + input_buf[ci], thisblockrow, + (JDIMENSION) (block_row * DCTSIZE), + (JDIMENSION) 0, blocks_across); + if (ndummy > 0) { + /* Create dummy blocks at the right edge of the image. */ + thisblockrow += blocks_across; /* => first dummy block */ + jzero_far((void FAR *) thisblockrow, ndummy * SIZEOF(JBLOCK)); + lastDC = thisblockrow[-1][0]; + for (bi = 0; bi < ndummy; bi++) { + thisblockrow[bi][0] = lastDC; + } + } + } + /* If at end of image, create dummy block rows as needed. + * The tricky part here is that within each MCU, we want the DC values + * of the dummy blocks to match the last real block's DC value. + * This squeezes a few more bytes out of the resulting file... + */ + if (coef->iMCU_row_num == last_iMCU_row) { + blocks_across += ndummy; /* include lower right corner */ + MCUs_across = blocks_across / h_samp_factor; + for (block_row = block_rows; block_row < compptr->v_samp_factor; + block_row++) { + thisblockrow = buffer[block_row]; + lastblockrow = buffer[block_row-1]; + jzero_far((void FAR *) thisblockrow, + (size_t) (blocks_across * SIZEOF(JBLOCK))); + for (MCUindex = 0; MCUindex < MCUs_across; MCUindex++) { + lastDC = lastblockrow[h_samp_factor-1][0]; + for (bi = 0; bi < h_samp_factor; bi++) { + thisblockrow[bi][0] = lastDC; + } + thisblockrow += h_samp_factor; /* advance to next MCU in row */ + lastblockrow += h_samp_factor; + } + } + } + } + /* NB: compress_output will increment iMCU_row_num if successful. + * A suspension return will result in redoing all the work above next time. + */ + + /* Emit data to the entropy encoder, sharing code with subsequent passes */ + return compress_output(cinfo, input_buf); +} + + +/* + * Process some data in subsequent passes of a multi-pass case. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor block rows for each component in the scan. + * The data is obtained from the virtual arrays and fed to the entropy coder. + * Returns TRUE if the iMCU row is completed, FALSE if suspended. + * + * NB: input_buf is ignored; it is likely to be a NULL pointer. + */ + +METHODDEF(boolean) +compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + int blkn, ci, xindex, yindex, yoffset; + JDIMENSION start_col; + JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; + JBLOCKROW buffer_ptr; + jpeg_component_info *compptr; + + /* Align the virtual buffers for the components used in this scan. + * NB: during first pass, this is safe only because the buffers will + * already be aligned properly, so jmemmgr.c won't need to do any I/O. + */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + buffer[ci] = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], + coef->iMCU_row_num * compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, FALSE); + } + + /* Loop to process one whole iMCU row */ + for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; + yoffset++) { + for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row; + MCU_col_num++) { + /* Construct list of pointers to DCT blocks belonging to this MCU */ + blkn = 0; /* index of current DCT block within MCU */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + start_col = MCU_col_num * compptr->MCU_width; + for (yindex = 0; yindex < compptr->MCU_height; yindex++) { + buffer_ptr = buffer[ci][yindex+yoffset] + start_col; + for (xindex = 0; xindex < compptr->MCU_width; xindex++) { + coef->MCU_buffer[blkn++] = buffer_ptr++; + } + } + } + /* Try to write the MCU. */ + if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) { + /* Suspension forced; update state counters and exit */ + coef->MCU_vert_offset = yoffset; + coef->mcu_ctr = MCU_col_num; + return FALSE; + } + } + /* Completed an MCU row, but perhaps not an iMCU row */ + coef->mcu_ctr = 0; + } + /* Completed the iMCU row, advance counters for next one */ + coef->iMCU_row_num++; + start_iMCU_row(cinfo); + return TRUE; +} + +#endif /* FULL_COEF_BUFFER_SUPPORTED */ + + +/* + * Initialize coefficient buffer controller. + */ + +GLOBAL(void) +jinit_c_coef_controller (j_compress_ptr cinfo, boolean need_full_buffer) +{ + my_coef_ptr coef; + + coef = (my_coef_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_coef_controller)); + cinfo->coef = (struct jpeg_c_coef_controller *) coef; + coef->pub.start_pass = start_pass_coef; + + /* Create the coefficient buffer. */ + if (need_full_buffer) { +#ifdef FULL_COEF_BUFFER_SUPPORTED + /* Allocate a full-image virtual array for each component, */ + /* padded to a multiple of samp_factor DCT blocks in each direction. */ + int ci; + jpeg_component_info *compptr; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + coef->whole_image[ci] = (*cinfo->mem->request_virt_barray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, + (JDIMENSION) jround_up((long) compptr->width_in_blocks, + (long) compptr->h_samp_factor), + (JDIMENSION) jround_up((long) compptr->height_in_blocks, + (long) compptr->v_samp_factor), + (JDIMENSION) compptr->v_samp_factor); + } +#else + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); +#endif + } else { + /* We only need a single-MCU buffer. */ + JBLOCKROW buffer; + int i; + + buffer = (JBLOCKROW) + (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, + C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); + for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) { + coef->MCU_buffer[i] = buffer + i; + } + coef->whole_image[0] = NULL; /* flag for no virtual arrays */ + } +} diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jccolor.c b/lc-continuity/mk4/modimage/jpeg-6b/jccolor.c new file mode 100644 index 0000000000000000000000000000000000000000..0a8a4b5d13c303c4d14cd5b4333adcbb3cfcc4a2 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jccolor.c @@ -0,0 +1,459 @@ +/* + * jccolor.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains input colorspace conversion routines. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Private subobject */ + +typedef struct { + struct jpeg_color_converter pub; /* public fields */ + + /* Private state for RGB->YCC conversion */ + INT32 * rgb_ycc_tab; /* => table for RGB to YCbCr conversion */ +} my_color_converter; + +typedef my_color_converter * my_cconvert_ptr; + + +/**************** RGB -> YCbCr conversion: most common case **************/ + +/* + * YCbCr is defined per CCIR 601-1, except that Cb and Cr are + * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. + * The conversion equations to be implemented are therefore + * Y = 0.29900 * R + 0.58700 * G + 0.11400 * B + * Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B + CENTERJSAMPLE + * Cr = 0.50000 * R - 0.41869 * G - 0.08131 * B + CENTERJSAMPLE + * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) + * Note: older versions of the IJG code used a zero offset of MAXJSAMPLE/2, + * rather than CENTERJSAMPLE, for Cb and Cr. This gave equal positive and + * negative swings for Cb/Cr, but meant that grayscale values (Cb=Cr=0) + * were not represented exactly. Now we sacrifice exact representation of + * maximum red and maximum blue in order to get exact grayscales. + * + * To avoid floating-point arithmetic, we represent the fractional constants + * as integers scaled up by 2^16 (about 4 digits precision); we have to divide + * the products by 2^16, with appropriate rounding, to get the correct answer. + * + * For even more speed, we avoid doing any multiplications in the inner loop + * by precalculating the constants times R,G,B for all possible values. + * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); + * for 12-bit samples it is still acceptable. It's not very reasonable for + * 16-bit samples, but if you want lossless storage you shouldn't be changing + * colorspace anyway. + * The CENTERJSAMPLE offsets and the rounding fudge-factor of 0.5 are included + * in the tables to save adding them separately in the inner loop. + */ + +#define SCALEBITS 16 /* speediest right-shift on some machines */ +#define CBCR_OFFSET ((INT32) CENTERJSAMPLE << SCALEBITS) +#define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) +#define FIX(x) ((INT32) ((x) * (1L< Y section */ +#define G_Y_OFF (1*(MAXJSAMPLE+1)) /* offset to G => Y section */ +#define B_Y_OFF (2*(MAXJSAMPLE+1)) /* etc. */ +#define R_CB_OFF (3*(MAXJSAMPLE+1)) +#define G_CB_OFF (4*(MAXJSAMPLE+1)) +#define B_CB_OFF (5*(MAXJSAMPLE+1)) +#define R_CR_OFF B_CB_OFF /* B=>Cb, R=>Cr are the same */ +#define G_CR_OFF (6*(MAXJSAMPLE+1)) +#define B_CR_OFF (7*(MAXJSAMPLE+1)) +#define TABLE_SIZE (8*(MAXJSAMPLE+1)) + + +/* + * Initialize for RGB->YCC colorspace conversion. + */ + +METHODDEF(void) +rgb_ycc_start (j_compress_ptr cinfo) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + INT32 * rgb_ycc_tab; + INT32 i; + + /* Allocate and fill in the conversion tables. */ + cconvert->rgb_ycc_tab = rgb_ycc_tab = (INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (TABLE_SIZE * SIZEOF(INT32))); + + for (i = 0; i <= MAXJSAMPLE; i++) { + rgb_ycc_tab[i+R_Y_OFF] = FIX(0.29900) * i; + rgb_ycc_tab[i+G_Y_OFF] = FIX(0.58700) * i; + rgb_ycc_tab[i+B_Y_OFF] = FIX(0.11400) * i + ONE_HALF; + rgb_ycc_tab[i+R_CB_OFF] = (-FIX(0.16874)) * i; + rgb_ycc_tab[i+G_CB_OFF] = (-FIX(0.33126)) * i; + /* We use a rounding fudge-factor of 0.5-epsilon for Cb and Cr. + * This ensures that the maximum output will round to MAXJSAMPLE + * not MAXJSAMPLE+1, and thus that we don't have to range-limit. + */ + rgb_ycc_tab[i+B_CB_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF-1; +/* B=>Cb and R=>Cr tables are the same + rgb_ycc_tab[i+R_CR_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF-1; +*/ + rgb_ycc_tab[i+G_CR_OFF] = (-FIX(0.41869)) * i; + rgb_ycc_tab[i+B_CR_OFF] = (-FIX(0.08131)) * i; + } +} + + +/* + * Convert some rows of samples to the JPEG colorspace. + * + * Note that we change from the application's interleaved-pixel format + * to our internal noninterleaved, one-plane-per-component format. + * The input buffer is therefore three times as wide as the output buffer. + * + * A starting row offset is provided only for the output buffer. The caller + * can easily adjust the passed input_buf value to accommodate any row + * offset required on that side. + */ + +METHODDEF(void) +rgb_ycc_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + register int r, g, b; + register INT32 * ctab = cconvert->rgb_ycc_tab; + register JSAMPROW inptr; + register JSAMPROW outptr0, outptr1, outptr2; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->image_width; + + while (--num_rows >= 0) { + inptr = *input_buf++; + outptr0 = output_buf[0][output_row]; + outptr1 = output_buf[1][output_row]; + outptr2 = output_buf[2][output_row]; + output_row++; + for (col = 0; col < num_cols; col++) { + r = GETJSAMPLE(inptr[RGB_RED]); + g = GETJSAMPLE(inptr[RGB_GREEN]); + b = GETJSAMPLE(inptr[RGB_BLUE]); + inptr += RGB_PIXELSIZE; + /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations + * must be too; we do not need an explicit range-limiting operation. + * Hence the value being shifted is never negative, and we don't + * need the general RIGHT_SHIFT macro. + */ + /* Y */ + outptr0[col] = (JSAMPLE) + ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) + >> SCALEBITS); + /* Cb */ + outptr1[col] = (JSAMPLE) + ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF]) + >> SCALEBITS); + /* Cr */ + outptr2[col] = (JSAMPLE) + ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF]) + >> SCALEBITS); + } + } +} + + +/**************** Cases other than RGB -> YCbCr **************/ + + +/* + * Convert some rows of samples to the JPEG colorspace. + * This version handles RGB->grayscale conversion, which is the same + * as the RGB->Y portion of RGB->YCbCr. + * We assume rgb_ycc_start has been called (we only use the Y tables). + */ + +METHODDEF(void) +rgb_gray_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + register int r, g, b; + register INT32 * ctab = cconvert->rgb_ycc_tab; + register JSAMPROW inptr; + register JSAMPROW outptr; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->image_width; + + while (--num_rows >= 0) { + inptr = *input_buf++; + outptr = output_buf[0][output_row]; + output_row++; + for (col = 0; col < num_cols; col++) { + r = GETJSAMPLE(inptr[RGB_RED]); + g = GETJSAMPLE(inptr[RGB_GREEN]); + b = GETJSAMPLE(inptr[RGB_BLUE]); + inptr += RGB_PIXELSIZE; + /* Y */ + outptr[col] = (JSAMPLE) + ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) + >> SCALEBITS); + } + } +} + + +/* + * Convert some rows of samples to the JPEG colorspace. + * This version handles Adobe-style CMYK->YCCK conversion, + * where we convert R=1-C, G=1-M, and B=1-Y to YCbCr using the same + * conversion as above, while passing K (black) unchanged. + * We assume rgb_ycc_start has been called. + */ + +METHODDEF(void) +cmyk_ycck_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + register int r, g, b; + register INT32 * ctab = cconvert->rgb_ycc_tab; + register JSAMPROW inptr; + register JSAMPROW outptr0, outptr1, outptr2, outptr3; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->image_width; + + while (--num_rows >= 0) { + inptr = *input_buf++; + outptr0 = output_buf[0][output_row]; + outptr1 = output_buf[1][output_row]; + outptr2 = output_buf[2][output_row]; + outptr3 = output_buf[3][output_row]; + output_row++; + for (col = 0; col < num_cols; col++) { + r = MAXJSAMPLE - GETJSAMPLE(inptr[0]); + g = MAXJSAMPLE - GETJSAMPLE(inptr[1]); + b = MAXJSAMPLE - GETJSAMPLE(inptr[2]); + /* K passes through as-is */ + outptr3[col] = inptr[3]; /* don't need GETJSAMPLE here */ + inptr += 4; + /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations + * must be too; we do not need an explicit range-limiting operation. + * Hence the value being shifted is never negative, and we don't + * need the general RIGHT_SHIFT macro. + */ + /* Y */ + outptr0[col] = (JSAMPLE) + ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) + >> SCALEBITS); + /* Cb */ + outptr1[col] = (JSAMPLE) + ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF]) + >> SCALEBITS); + /* Cr */ + outptr2[col] = (JSAMPLE) + ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF]) + >> SCALEBITS); + } + } +} + + +/* + * Convert some rows of samples to the JPEG colorspace. + * This version handles grayscale output with no conversion. + * The source can be either plain grayscale or YCbCr (since Y == gray). + */ + +METHODDEF(void) +grayscale_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + register JSAMPROW inptr; + register JSAMPROW outptr; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->image_width; + int instride = cinfo->input_components; + + while (--num_rows >= 0) { + inptr = *input_buf++; + outptr = output_buf[0][output_row]; + output_row++; + for (col = 0; col < num_cols; col++) { + outptr[col] = inptr[0]; /* don't need GETJSAMPLE() here */ + inptr += instride; + } + } +} + + +/* + * Convert some rows of samples to the JPEG colorspace. + * This version handles multi-component colorspaces without conversion. + * We assume input_components == num_components. + */ + +METHODDEF(void) +null_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + register JSAMPROW inptr; + register JSAMPROW outptr; + register JDIMENSION col; + register int ci; + int nc = cinfo->num_components; + JDIMENSION num_cols = cinfo->image_width; + + while (--num_rows >= 0) { + /* It seems fastest to make a separate pass for each component. */ + for (ci = 0; ci < nc; ci++) { + inptr = *input_buf; + outptr = output_buf[ci][output_row]; + for (col = 0; col < num_cols; col++) { + outptr[col] = inptr[ci]; /* don't need GETJSAMPLE() here */ + inptr += nc; + } + } + input_buf++; + output_row++; + } +} + + +/* + * Empty method for start_pass. + */ + +METHODDEF(void) +null_method (j_compress_ptr cinfo) +{ + /* no work needed */ +} + + +/* + * Module initialization routine for input colorspace conversion. + */ + +GLOBAL(void) +jinit_color_converter (j_compress_ptr cinfo) +{ + my_cconvert_ptr cconvert; + + cconvert = (my_cconvert_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_color_converter)); + cinfo->cconvert = (struct jpeg_color_converter *) cconvert; + /* set start_pass to null method until we find out differently */ + cconvert->pub.start_pass = null_method; + + /* Make sure input_components agrees with in_color_space */ + switch (cinfo->in_color_space) { + case JCS_GRAYSCALE: + if (cinfo->input_components != 1) + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + break; + + case JCS_RGB: +#if RGB_PIXELSIZE != 3 + if (cinfo->input_components != RGB_PIXELSIZE) + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + break; +#endif /* else share code with YCbCr */ + + case JCS_YCbCr: + if (cinfo->input_components != 3) + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + break; + + case JCS_CMYK: + case JCS_YCCK: + if (cinfo->input_components != 4) + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + break; + + default: /* JCS_UNKNOWN can be anything */ + if (cinfo->input_components < 1) + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + break; + } + + /* Check num_components, set conversion method based on requested space */ + switch (cinfo->jpeg_color_space) { + case JCS_GRAYSCALE: + if (cinfo->num_components != 1) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + if (cinfo->in_color_space == JCS_GRAYSCALE) + cconvert->pub.color_convert = grayscale_convert; + else if (cinfo->in_color_space == JCS_RGB) { + cconvert->pub.start_pass = rgb_ycc_start; + cconvert->pub.color_convert = rgb_gray_convert; + } else if (cinfo->in_color_space == JCS_YCbCr) + cconvert->pub.color_convert = grayscale_convert; + else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_RGB: + if (cinfo->num_components != 3) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + if (cinfo->in_color_space == JCS_RGB && RGB_PIXELSIZE == 3) + cconvert->pub.color_convert = null_convert; + else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_YCbCr: + if (cinfo->num_components != 3) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + if (cinfo->in_color_space == JCS_RGB) { + cconvert->pub.start_pass = rgb_ycc_start; + cconvert->pub.color_convert = rgb_ycc_convert; + } else if (cinfo->in_color_space == JCS_YCbCr) + cconvert->pub.color_convert = null_convert; + else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_CMYK: + if (cinfo->num_components != 4) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + if (cinfo->in_color_space == JCS_CMYK) + cconvert->pub.color_convert = null_convert; + else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_YCCK: + if (cinfo->num_components != 4) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + if (cinfo->in_color_space == JCS_CMYK) { + cconvert->pub.start_pass = rgb_ycc_start; + cconvert->pub.color_convert = cmyk_ycck_convert; + } else if (cinfo->in_color_space == JCS_YCCK) + cconvert->pub.color_convert = null_convert; + else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + default: /* allow null conversion of JCS_UNKNOWN */ + if (cinfo->jpeg_color_space != cinfo->in_color_space || + cinfo->num_components != cinfo->input_components) + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + cconvert->pub.color_convert = null_convert; + break; + } +} diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jcdctmgr.c b/lc-continuity/mk4/modimage/jpeg-6b/jcdctmgr.c new file mode 100644 index 0000000000000000000000000000000000000000..61fa79b9e68bcc3e3bfe84b9a50af55a9598214b --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jcdctmgr.c @@ -0,0 +1,387 @@ +/* + * jcdctmgr.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the forward-DCT management logic. + * This code selects a particular DCT implementation to be used, + * and it performs related housekeeping chores including coefficient + * quantization. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdct.h" /* Private declarations for DCT subsystem */ + + +/* Private subobject for this module */ + +typedef struct { + struct jpeg_forward_dct pub; /* public fields */ + + /* Pointer to the DCT routine actually in use */ + forward_DCT_method_ptr do_dct; + + /* The actual post-DCT divisors --- not identical to the quant table + * entries, because of scaling (especially for an unnormalized DCT). + * Each table is given in normal array order. + */ + DCTELEM * divisors[NUM_QUANT_TBLS]; + +#ifdef DCT_FLOAT_SUPPORTED + /* Same as above for the floating-point case. */ + float_DCT_method_ptr do_float_dct; + FAST_FLOAT * float_divisors[NUM_QUANT_TBLS]; +#endif +} my_fdct_controller; + +typedef my_fdct_controller * my_fdct_ptr; + + +/* + * Initialize for a processing pass. + * Verify that all referenced Q-tables are present, and set up + * the divisor table for each one. + * In the current implementation, DCT of all components is done during + * the first pass, even if only some components will be output in the + * first scan. Hence all components should be examined here. + */ + +METHODDEF(void) +start_pass_fdctmgr (j_compress_ptr cinfo) +{ + my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct; + int ci, qtblno, i; + jpeg_component_info *compptr; + JQUANT_TBL * qtbl; + DCTELEM * dtbl; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + qtblno = compptr->quant_tbl_no; + /* Make sure specified quantization table is present */ + if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || + cinfo->quant_tbl_ptrs[qtblno] == NULL) + ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno); + qtbl = cinfo->quant_tbl_ptrs[qtblno]; + /* Compute divisors for this quant table */ + /* We may do this more than once for same table, but it's not a big deal */ + switch (cinfo->dct_method) { +#ifdef DCT_ISLOW_SUPPORTED + case JDCT_ISLOW: + /* For LL&M IDCT method, divisors are equal to raw quantization + * coefficients multiplied by 8 (to counteract scaling). + */ + if (fdct->divisors[qtblno] == NULL) { + fdct->divisors[qtblno] = (DCTELEM *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + DCTSIZE2 * SIZEOF(DCTELEM)); + } + dtbl = fdct->divisors[qtblno]; + for (i = 0; i < DCTSIZE2; i++) { + dtbl[i] = ((DCTELEM) qtbl->quantval[i]) << 3; + } + break; +#endif +#ifdef DCT_IFAST_SUPPORTED + case JDCT_IFAST: + { + /* For AA&N IDCT method, divisors are equal to quantization + * coefficients scaled by scalefactor[row]*scalefactor[col], where + * scalefactor[0] = 1 + * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 + * We apply a further scale factor of 8. + */ +#define CONST_BITS 14 + static const INT16 aanscales[DCTSIZE2] = { + /* precomputed values scaled up by 14 bits */ + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, + 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, + 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, + 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, + 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 + }; + SHIFT_TEMPS + + if (fdct->divisors[qtblno] == NULL) { + fdct->divisors[qtblno] = (DCTELEM *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + DCTSIZE2 * SIZEOF(DCTELEM)); + } + dtbl = fdct->divisors[qtblno]; + for (i = 0; i < DCTSIZE2; i++) { + dtbl[i] = (DCTELEM) + DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i], + (INT32) aanscales[i]), + CONST_BITS-3); + } + } + break; +#endif +#ifdef DCT_FLOAT_SUPPORTED + case JDCT_FLOAT: + { + /* For float AA&N IDCT method, divisors are equal to quantization + * coefficients scaled by scalefactor[row]*scalefactor[col], where + * scalefactor[0] = 1 + * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 + * We apply a further scale factor of 8. + * What's actually stored is 1/divisor so that the inner loop can + * use a multiplication rather than a division. + */ + FAST_FLOAT * fdtbl; + int row, col; + static const double aanscalefactor[DCTSIZE] = { + 1.0, 1.387039845, 1.306562965, 1.175875602, + 1.0, 0.785694958, 0.541196100, 0.275899379 + }; + + if (fdct->float_divisors[qtblno] == NULL) { + fdct->float_divisors[qtblno] = (FAST_FLOAT *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + DCTSIZE2 * SIZEOF(FAST_FLOAT)); + } + fdtbl = fdct->float_divisors[qtblno]; + i = 0; + for (row = 0; row < DCTSIZE; row++) { + for (col = 0; col < DCTSIZE; col++) { + fdtbl[i] = (FAST_FLOAT) + (1.0 / (((double) qtbl->quantval[i] * + aanscalefactor[row] * aanscalefactor[col] * 8.0))); + i++; + } + } + } + break; +#endif + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; + } + } +} + + +/* + * Perform forward DCT on one or more blocks of a component. + * + * The input samples are taken from the sample_data[] array starting at + * position start_row/start_col, and moving to the right for any additional + * blocks. The quantized coefficients are returned in coef_blocks[]. + */ + +METHODDEF(void) +forward_DCT (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY sample_data, JBLOCKROW coef_blocks, + JDIMENSION start_row, JDIMENSION start_col, + JDIMENSION num_blocks) +/* This version is used for integer DCT implementations. */ +{ + /* This routine is heavily used, so it's worth coding it tightly. */ + my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct; + forward_DCT_method_ptr do_dct = fdct->do_dct; + DCTELEM * divisors = fdct->divisors[compptr->quant_tbl_no]; + DCTELEM workspace[DCTSIZE2]; /* work area for FDCT subroutine */ + JDIMENSION bi; + + sample_data += start_row; /* fold in the vertical offset once */ + + for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) { + /* Load data into workspace, applying unsigned->signed conversion */ + { register DCTELEM *workspaceptr; + register JSAMPROW elemptr; + register int elemr; + + workspaceptr = workspace; + for (elemr = 0; elemr < DCTSIZE; elemr++) { + elemptr = sample_data[elemr] + start_col; +#if DCTSIZE == 8 /* unroll the inner loop */ + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; +#else + { register int elemc; + for (elemc = DCTSIZE; elemc > 0; elemc--) { + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + } + } +#endif + } + } + + /* Perform the DCT */ + (*do_dct) (workspace); + + /* Quantize/descale the coefficients, and store into coef_blocks[] */ + { register DCTELEM temp, qval; + register int i; + register JCOEFPTR output_ptr = coef_blocks[bi]; + + for (i = 0; i < DCTSIZE2; i++) { + qval = divisors[i]; + temp = workspace[i]; + /* Divide the coefficient value by qval, ensuring proper rounding. + * Since C does not specify the direction of rounding for negative + * quotients, we have to force the dividend positive for portability. + * + * In most files, at least half of the output values will be zero + * (at default quantization settings, more like three-quarters...) + * so we should ensure that this case is fast. On many machines, + * a comparison is enough cheaper than a divide to make a special test + * a win. Since both inputs will be nonnegative, we need only test + * for a < b to discover whether a/b is 0. + * If your machine's division is fast enough, define FAST_DIVIDE. + */ +#ifdef FAST_DIVIDE +#define DIVIDE_BY(a,b) a /= b +#else +#define DIVIDE_BY(a,b) if (a >= b) a /= b; else a = 0 +#endif + if (temp < 0) { + temp = -temp; + temp += qval>>1; /* for rounding */ + DIVIDE_BY(temp, qval); + temp = -temp; + } else { + temp += qval>>1; /* for rounding */ + DIVIDE_BY(temp, qval); + } + output_ptr[i] = (JCOEF) temp; + } + } + } +} + + +#ifdef DCT_FLOAT_SUPPORTED + +METHODDEF(void) +forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY sample_data, JBLOCKROW coef_blocks, + JDIMENSION start_row, JDIMENSION start_col, + JDIMENSION num_blocks) +/* This version is used for floating-point DCT implementations. */ +{ + /* This routine is heavily used, so it's worth coding it tightly. */ + my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct; + float_DCT_method_ptr do_dct = fdct->do_float_dct; + FAST_FLOAT * divisors = fdct->float_divisors[compptr->quant_tbl_no]; + FAST_FLOAT workspace[DCTSIZE2]; /* work area for FDCT subroutine */ + JDIMENSION bi; + + sample_data += start_row; /* fold in the vertical offset once */ + + for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) { + /* Load data into workspace, applying unsigned->signed conversion */ + { register FAST_FLOAT *workspaceptr; + register JSAMPROW elemptr; + register int elemr; + + workspaceptr = workspace; + for (elemr = 0; elemr < DCTSIZE; elemr++) { + elemptr = sample_data[elemr] + start_col; +#if DCTSIZE == 8 /* unroll the inner loop */ + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); +#else + { register int elemc; + for (elemc = DCTSIZE; elemc > 0; elemc--) { + *workspaceptr++ = (FAST_FLOAT) + (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + } + } +#endif + } + } + + /* Perform the DCT */ + (*do_dct) (workspace); + + /* Quantize/descale the coefficients, and store into coef_blocks[] */ + { register FAST_FLOAT temp; + register int i; + register JCOEFPTR output_ptr = coef_blocks[bi]; + + for (i = 0; i < DCTSIZE2; i++) { + /* Apply the quantization and scaling factor */ + temp = workspace[i] * divisors[i]; + /* Round to nearest integer. + * Since C does not specify the direction of rounding for negative + * quotients, we have to force the dividend positive for portability. + * The maximum coefficient size is +-16K (for 12-bit data), so this + * code should work for either 16-bit or 32-bit ints. + */ + output_ptr[i] = (JCOEF) ((int) (temp + (FAST_FLOAT) 16384.5) - 16384); + } + } + } +} + +#endif /* DCT_FLOAT_SUPPORTED */ + + +/* + * Initialize FDCT manager. + */ + +GLOBAL(void) +jinit_forward_dct (j_compress_ptr cinfo) +{ + my_fdct_ptr fdct; + int i; + + fdct = (my_fdct_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_fdct_controller)); + cinfo->fdct = (struct jpeg_forward_dct *) fdct; + fdct->pub.start_pass = start_pass_fdctmgr; + + switch (cinfo->dct_method) { +#ifdef DCT_ISLOW_SUPPORTED + case JDCT_ISLOW: + fdct->pub.forward_DCT = forward_DCT; + fdct->do_dct = jpeg_fdct_islow; + break; +#endif +#ifdef DCT_IFAST_SUPPORTED + case JDCT_IFAST: + fdct->pub.forward_DCT = forward_DCT; + fdct->do_dct = jpeg_fdct_ifast; + break; +#endif +#ifdef DCT_FLOAT_SUPPORTED + case JDCT_FLOAT: + fdct->pub.forward_DCT = forward_DCT_float; + fdct->do_float_dct = jpeg_fdct_float; + break; +#endif + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; + } + + /* Mark divisor tables unallocated */ + for (i = 0; i < NUM_QUANT_TBLS; i++) { + fdct->divisors[i] = NULL; +#ifdef DCT_FLOAT_SUPPORTED + fdct->float_divisors[i] = NULL; +#endif + } +} diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jchuff.c b/lc-continuity/mk4/modimage/jpeg-6b/jchuff.c new file mode 100644 index 0000000000000000000000000000000000000000..f235250548671f2d52cabd12ce366a07db4cbf34 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jchuff.c @@ -0,0 +1,909 @@ +/* + * jchuff.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains Huffman entropy encoding routines. + * + * Much of the complexity here has to do with supporting output suspension. + * If the data destination module demands suspension, we want to be able to + * back up to the start of the current MCU. To do this, we copy state + * variables into local working storage, and update them back to the + * permanent JPEG objects only upon successful completion of an MCU. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jchuff.h" /* Declarations shared with jcphuff.c */ + + +/* Expanded entropy encoder object for Huffman encoding. + * + * The savable_state subrecord contains fields that change within an MCU, + * but must not be updated permanently until we complete the MCU. + */ + +typedef struct { + INT32 put_buffer; /* current bit-accumulation buffer */ + int put_bits; /* # of bits now in it */ + int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ +} savable_state; + +/* This macro is to work around compilers with missing or broken + * structure assignment. You'll need to fix this code if you have + * such a compiler and you change MAX_COMPS_IN_SCAN. + */ + +#ifndef NO_STRUCT_ASSIGN +#define ASSIGN_STATE(dest,src) ((dest) = (src)) +#else +#if MAX_COMPS_IN_SCAN == 4 +#define ASSIGN_STATE(dest,src) \ + ((dest).put_buffer = (src).put_buffer, \ + (dest).put_bits = (src).put_bits, \ + (dest).last_dc_val[0] = (src).last_dc_val[0], \ + (dest).last_dc_val[1] = (src).last_dc_val[1], \ + (dest).last_dc_val[2] = (src).last_dc_val[2], \ + (dest).last_dc_val[3] = (src).last_dc_val[3]) +#endif +#endif + + +typedef struct { + struct jpeg_entropy_encoder pub; /* public fields */ + + savable_state saved; /* Bit buffer & DC state at start of MCU */ + + /* These fields are NOT loaded into local working state. */ + unsigned int restarts_to_go; /* MCUs left in this restart interval */ + int next_restart_num; /* next restart number to write (0-7) */ + + /* Pointers to derived tables (these workspaces have image lifespan) */ + c_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS]; + c_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS]; + +#ifdef ENTROPY_OPT_SUPPORTED /* Statistics tables for optimization */ + long * dc_count_ptrs[NUM_HUFF_TBLS]; + long * ac_count_ptrs[NUM_HUFF_TBLS]; +#endif +} huff_entropy_encoder; + +typedef huff_entropy_encoder * huff_entropy_ptr; + +/* Working state while writing an MCU. + * This struct contains all the fields that are needed by subroutines. + */ + +typedef struct { + JOCTET * next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + savable_state cur; /* Current bit buffer & DC state */ + j_compress_ptr cinfo; /* dump_buffer needs access to this */ +} working_state; + + +/* Forward declarations */ +METHODDEF(boolean) encode_mcu_huff JPP((j_compress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(void) finish_pass_huff JPP((j_compress_ptr cinfo)); +#ifdef ENTROPY_OPT_SUPPORTED +METHODDEF(boolean) encode_mcu_gather JPP((j_compress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(void) finish_pass_gather JPP((j_compress_ptr cinfo)); +#endif + + +/* + * Initialize for a Huffman-compressed scan. + * If gather_statistics is TRUE, we do not output anything during the scan, + * just count the Huffman symbols used and generate Huffman code tables. + */ + +METHODDEF(void) +start_pass_huff (j_compress_ptr cinfo, boolean gather_statistics) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + int ci, dctbl, actbl; + jpeg_component_info * compptr; + + if (gather_statistics) { +#ifdef ENTROPY_OPT_SUPPORTED + entropy->pub.encode_mcu = encode_mcu_gather; + entropy->pub.finish_pass = finish_pass_gather; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + entropy->pub.encode_mcu = encode_mcu_huff; + entropy->pub.finish_pass = finish_pass_huff; + } + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + dctbl = compptr->dc_tbl_no; + actbl = compptr->ac_tbl_no; + if (gather_statistics) { +#ifdef ENTROPY_OPT_SUPPORTED + /* Check for invalid table indexes */ + /* (make_c_derived_tbl does this in the other path) */ + if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dctbl); + if (actbl < 0 || actbl >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, actbl); + /* Allocate and zero the statistics tables */ + /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */ + if (entropy->dc_count_ptrs[dctbl] == NULL) + entropy->dc_count_ptrs[dctbl] = (long *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + 257 * SIZEOF(long)); + MEMZERO(entropy->dc_count_ptrs[dctbl], 257 * SIZEOF(long)); + if (entropy->ac_count_ptrs[actbl] == NULL) + entropy->ac_count_ptrs[actbl] = (long *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + 257 * SIZEOF(long)); + MEMZERO(entropy->ac_count_ptrs[actbl], 257 * SIZEOF(long)); +#endif + } else { + /* Compute derived values for Huffman tables */ + /* We may do this more than once for a table, but it's not expensive */ + jpeg_make_c_derived_tbl(cinfo, TRUE, dctbl, + & entropy->dc_derived_tbls[dctbl]); + jpeg_make_c_derived_tbl(cinfo, FALSE, actbl, + & entropy->ac_derived_tbls[actbl]); + } + /* Initialize DC predictions to 0 */ + entropy->saved.last_dc_val[ci] = 0; + } + + /* Initialize bit buffer to empty */ + entropy->saved.put_buffer = 0; + entropy->saved.put_bits = 0; + + /* Initialize restart stuff */ + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num = 0; +} + + +/* + * Compute the derived values for a Huffman table. + * This routine also performs some validation checks on the table. + * + * Note this is also used by jcphuff.c. + */ + +GLOBAL(void) +jpeg_make_c_derived_tbl (j_compress_ptr cinfo, boolean isDC, int tblno, + c_derived_tbl ** pdtbl) +{ + JHUFF_TBL *htbl; + c_derived_tbl *dtbl; + int p, i, l, lastp, si, maxsymbol; + char huffsize[257]; + unsigned int huffcode[257]; + unsigned int code; + + /* Note that huffsize[] and huffcode[] are filled in code-length order, + * paralleling the order of the symbols themselves in htbl->huffval[]. + */ + + /* Find the input Huffman table */ + if (tblno < 0 || tblno >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); + htbl = + isDC ? cinfo->dc_huff_tbl_ptrs[tblno] : cinfo->ac_huff_tbl_ptrs[tblno]; + if (htbl == NULL) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); + + /* Allocate a workspace if we haven't already done so. */ + if (*pdtbl == NULL) + *pdtbl = (c_derived_tbl *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(c_derived_tbl)); + dtbl = *pdtbl; + + /* Figure C.1: make table of Huffman code length for each symbol */ + + p = 0; + for (l = 1; l <= 16; l++) { + i = (int) htbl->bits[l]; + if (i < 0 || p + i > 256) /* protect against table overrun */ + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + while (i--) + huffsize[p++] = (char) l; + } + huffsize[p] = 0; + lastp = p; + + /* Figure C.2: generate the codes themselves */ + /* We also validate that the counts represent a legal Huffman code tree. */ + + code = 0; + si = huffsize[0]; + p = 0; + while (huffsize[p]) { + while (((int) huffsize[p]) == si) { + huffcode[p++] = code; + code++; + } + /* code is now 1 more than the last code used for codelength si; but + * it must still fit in si bits, since no code is allowed to be all ones. + */ + if (((INT32) code) >= (((INT32) 1) << si)) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + code <<= 1; + si++; + } + + /* Figure C.3: generate encoding tables */ + /* These are code and size indexed by symbol value */ + + /* Set all codeless symbols to have code length 0; + * this lets us detect duplicate VAL entries here, and later + * allows emit_bits to detect any attempt to emit such symbols. + */ + MEMZERO(dtbl->ehufsi, SIZEOF(dtbl->ehufsi)); + + /* This is also a convenient place to check for out-of-range + * and duplicated VAL entries. We allow 0..255 for AC symbols + * but only 0..15 for DC. (We could constrain them further + * based on data depth and mode, but this seems enough.) + */ + maxsymbol = isDC ? 15 : 255; + + for (p = 0; p < lastp; p++) { + i = htbl->huffval[p]; + if (i < 0 || i > maxsymbol || dtbl->ehufsi[i]) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + dtbl->ehufco[i] = huffcode[p]; + dtbl->ehufsi[i] = huffsize[p]; + } +} + + +/* Outputting bytes to the file */ + +/* Emit a byte, taking 'action' if must suspend. */ +#define emit_byte(state,val,action) \ + { *(state)->next_output_byte++ = (JOCTET) (val); \ + if (--(state)->free_in_buffer == 0) \ + if (! dump_buffer(state)) \ + { action; } } + + +LOCAL(boolean) +dump_buffer (working_state * state) +/* Empty the output buffer; return TRUE if successful, FALSE if must suspend */ +{ + struct jpeg_destination_mgr * dest = state->cinfo->dest; + + if (! (*dest->empty_output_buffer) (state->cinfo)) + return FALSE; + /* After a successful buffer dump, must reset buffer pointers */ + state->next_output_byte = dest->next_output_byte; + state->free_in_buffer = dest->free_in_buffer; + return TRUE; +} + + +/* Outputting bits to the file */ + +/* Only the right 24 bits of put_buffer are used; the valid bits are + * left-justified in this part. At most 16 bits can be passed to emit_bits + * in one call, and we never retain more than 7 bits in put_buffer + * between calls, so 24 bits are sufficient. + */ + +INLINE +LOCAL(boolean) +emit_bits (working_state * state, unsigned int code, int size) +/* Emit some bits; return TRUE if successful, FALSE if must suspend */ +{ + /* This routine is heavily used, so it's worth coding tightly. */ + register INT32 put_buffer = (INT32) code; + register int put_bits = state->cur.put_bits; + + /* if size is 0, caller used an invalid Huffman table entry */ + if (size == 0) + ERREXIT(state->cinfo, JERR_HUFF_MISSING_CODE); + + put_buffer &= (((INT32) 1)<cur.put_buffer; /* and merge with old buffer contents */ + + while (put_bits >= 8) { + int c = (int) ((put_buffer >> 16) & 0xFF); + + emit_byte(state, c, return FALSE); + if (c == 0xFF) { /* need to stuff a zero byte? */ + emit_byte(state, 0, return FALSE); + } + put_buffer <<= 8; + put_bits -= 8; + } + + state->cur.put_buffer = put_buffer; /* update state variables */ + state->cur.put_bits = put_bits; + + return TRUE; +} + + +LOCAL(boolean) +flush_bits (working_state * state) +{ + if (! emit_bits(state, 0x7F, 7)) /* fill any partial byte with ones */ + return FALSE; + state->cur.put_buffer = 0; /* and reset bit-buffer to empty */ + state->cur.put_bits = 0; + return TRUE; +} + + +/* Encode a single block's worth of coefficients */ + +LOCAL(boolean) +encode_one_block (working_state * state, JCOEFPTR block, int last_dc_val, + c_derived_tbl *dctbl, c_derived_tbl *actbl) +{ + register int temp, temp2; + register int nbits; + register int k, r, i; + + /* Encode the DC coefficient difference per section F.1.2.1 */ + + temp = temp2 = block[0] - last_dc_val; + + if (temp < 0) { + temp = -temp; /* temp is abs value of input */ + /* For a negative input, want temp2 = bitwise complement of abs(input) */ + /* This code assumes we are on a two's complement machine */ + temp2--; + } + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 0; + while (temp) { + nbits++; + temp >>= 1; + } + /* Check for out-of-range coefficient values. + * Since we're encoding a difference, the range limit is twice as much. + */ + if (nbits > MAX_COEF_BITS+1) + ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); + + /* Emit the Huffman-coded symbol for the number of bits */ + if (! emit_bits(state, dctbl->ehufco[nbits], dctbl->ehufsi[nbits])) + return FALSE; + + /* Emit that number of bits of the value, if positive, */ + /* or the complement of its magnitude, if negative. */ + if (nbits) /* emit_bits rejects calls with size 0 */ + if (! emit_bits(state, (unsigned int) temp2, nbits)) + return FALSE; + + /* Encode the AC coefficients per section F.1.2.2 */ + + r = 0; /* r = run length of zeros */ + + for (k = 1; k < DCTSIZE2; k++) { + if ((temp = block[jpeg_natural_order[k]]) == 0) { + r++; + } else { + /* if run length > 15, must emit special run-length-16 codes (0xF0) */ + while (r > 15) { + if (! emit_bits(state, actbl->ehufco[0xF0], actbl->ehufsi[0xF0])) + return FALSE; + r -= 16; + } + + temp2 = temp; + if (temp < 0) { + temp = -temp; /* temp is abs value of input */ + /* This code assumes we are on a two's complement machine */ + temp2--; + } + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 1; /* there must be at least one 1 bit */ + while ((temp >>= 1)) + nbits++; + /* Check for out-of-range coefficient values */ + if (nbits > MAX_COEF_BITS) + ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); + + /* Emit Huffman symbol for run length / number of bits */ + i = (r << 4) + nbits; + if (! emit_bits(state, actbl->ehufco[i], actbl->ehufsi[i])) + return FALSE; + + /* Emit that number of bits of the value, if positive, */ + /* or the complement of its magnitude, if negative. */ + if (! emit_bits(state, (unsigned int) temp2, nbits)) + return FALSE; + + r = 0; + } + } + + /* If the last coef(s) were zero, emit an end-of-block code */ + if (r > 0) + if (! emit_bits(state, actbl->ehufco[0], actbl->ehufsi[0])) + return FALSE; + + return TRUE; +} + + +/* + * Emit a restart marker & resynchronize predictions. + */ + +LOCAL(boolean) +emit_restart (working_state * state, int restart_num) +{ + int ci; + + if (! flush_bits(state)) + return FALSE; + + emit_byte(state, 0xFF, return FALSE); + emit_byte(state, JPEG_RST0 + restart_num, return FALSE); + + /* Re-initialize DC predictions to 0 */ + for (ci = 0; ci < state->cinfo->comps_in_scan; ci++) + state->cur.last_dc_val[ci] = 0; + + /* The restart counter is not updated until we successfully write the MCU. */ + + return TRUE; +} + + +/* + * Encode and output one MCU's worth of Huffman-compressed coefficients. + */ + +METHODDEF(boolean) +encode_mcu_huff (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + working_state state; + int blkn, ci; + jpeg_component_info * compptr; + + /* Load up working state */ + state.next_output_byte = cinfo->dest->next_output_byte; + state.free_in_buffer = cinfo->dest->free_in_buffer; + ASSIGN_STATE(state.cur, entropy->saved); + state.cinfo = cinfo; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! emit_restart(&state, entropy->next_restart_num)) + return FALSE; + } + + /* Encode the MCU data blocks */ + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + if (! encode_one_block(&state, + MCU_data[blkn][0], state.cur.last_dc_val[ci], + entropy->dc_derived_tbls[compptr->dc_tbl_no], + entropy->ac_derived_tbls[compptr->ac_tbl_no])) + return FALSE; + /* Update last_dc_val */ + state.cur.last_dc_val[ci] = MCU_data[blkn][0][0]; + } + + /* Completed MCU, so update state */ + cinfo->dest->next_output_byte = state.next_output_byte; + cinfo->dest->free_in_buffer = state.free_in_buffer; + ASSIGN_STATE(entropy->saved, state.cur); + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* + * Finish up at the end of a Huffman-compressed scan. + */ + +METHODDEF(void) +finish_pass_huff (j_compress_ptr cinfo) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + working_state state; + + /* Load up working state ... flush_bits needs it */ + state.next_output_byte = cinfo->dest->next_output_byte; + state.free_in_buffer = cinfo->dest->free_in_buffer; + ASSIGN_STATE(state.cur, entropy->saved); + state.cinfo = cinfo; + + /* Flush out the last data */ + if (! flush_bits(&state)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); + + /* Update state */ + cinfo->dest->next_output_byte = state.next_output_byte; + cinfo->dest->free_in_buffer = state.free_in_buffer; + ASSIGN_STATE(entropy->saved, state.cur); +} + + +/* + * Huffman coding optimization. + * + * We first scan the supplied data and count the number of uses of each symbol + * that is to be Huffman-coded. (This process MUST agree with the code above.) + * Then we build a Huffman coding tree for the observed counts. + * Symbols which are not needed at all for the particular image are not + * assigned any code, which saves space in the DHT marker as well as in + * the compressed data. + */ + +#ifdef ENTROPY_OPT_SUPPORTED + + +/* Process a single block's worth of coefficients */ + +LOCAL(void) +htest_one_block (j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val, + long dc_counts[], long ac_counts[]) +{ + register int temp; + register int nbits; + register int k, r; + + /* Encode the DC coefficient difference per section F.1.2.1 */ + + temp = block[0] - last_dc_val; + if (temp < 0) + temp = -temp; + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 0; + while (temp) { + nbits++; + temp >>= 1; + } + /* Check for out-of-range coefficient values. + * Since we're encoding a difference, the range limit is twice as much. + */ + if (nbits > MAX_COEF_BITS+1) + ERREXIT(cinfo, JERR_BAD_DCT_COEF); + + /* Count the Huffman symbol for the number of bits */ + dc_counts[nbits]++; + + /* Encode the AC coefficients per section F.1.2.2 */ + + r = 0; /* r = run length of zeros */ + + for (k = 1; k < DCTSIZE2; k++) { + if ((temp = block[jpeg_natural_order[k]]) == 0) { + r++; + } else { + /* if run length > 15, must emit special run-length-16 codes (0xF0) */ + while (r > 15) { + ac_counts[0xF0]++; + r -= 16; + } + + /* Find the number of bits needed for the magnitude of the coefficient */ + if (temp < 0) + temp = -temp; + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 1; /* there must be at least one 1 bit */ + while ((temp >>= 1)) + nbits++; + /* Check for out-of-range coefficient values */ + if (nbits > MAX_COEF_BITS) + ERREXIT(cinfo, JERR_BAD_DCT_COEF); + + /* Count Huffman symbol for run length / number of bits */ + ac_counts[(r << 4) + nbits]++; + + r = 0; + } + } + + /* If the last coef(s) were zero, emit an end-of-block code */ + if (r > 0) + ac_counts[0]++; +} + + +/* + * Trial-encode one MCU's worth of Huffman-compressed coefficients. + * No data is actually output, so no suspension return is possible. + */ + +METHODDEF(boolean) +encode_mcu_gather (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + int blkn, ci; + jpeg_component_info * compptr; + + /* Take care of restart intervals if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + /* Re-initialize DC predictions to 0 */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) + entropy->saved.last_dc_val[ci] = 0; + /* Update restart state */ + entropy->restarts_to_go = cinfo->restart_interval; + } + entropy->restarts_to_go--; + } + + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + htest_one_block(cinfo, MCU_data[blkn][0], entropy->saved.last_dc_val[ci], + entropy->dc_count_ptrs[compptr->dc_tbl_no], + entropy->ac_count_ptrs[compptr->ac_tbl_no]); + entropy->saved.last_dc_val[ci] = MCU_data[blkn][0][0]; + } + + return TRUE; +} + + +/* + * Generate the best Huffman code table for the given counts, fill htbl. + * Note this is also used by jcphuff.c. + * + * The JPEG standard requires that no symbol be assigned a codeword of all + * one bits (so that padding bits added at the end of a compressed segment + * can't look like a valid code). Because of the canonical ordering of + * codewords, this just means that there must be an unused slot in the + * longest codeword length category. Section K.2 of the JPEG spec suggests + * reserving such a slot by pretending that symbol 256 is a valid symbol + * with count 1. In theory that's not optimal; giving it count zero but + * including it in the symbol set anyway should give a better Huffman code. + * But the theoretically better code actually seems to come out worse in + * practice, because it produces more all-ones bytes (which incur stuffed + * zero bytes in the final file). In any case the difference is tiny. + * + * The JPEG standard requires Huffman codes to be no more than 16 bits long. + * If some symbols have a very small but nonzero probability, the Huffman tree + * must be adjusted to meet the code length restriction. We currently use + * the adjustment method suggested in JPEG section K.2. This method is *not* + * optimal; it may not choose the best possible limited-length code. But + * typically only very-low-frequency symbols will be given less-than-optimal + * lengths, so the code is almost optimal. Experimental comparisons against + * an optimal limited-length-code algorithm indicate that the difference is + * microscopic --- usually less than a hundredth of a percent of total size. + * So the extra complexity of an optimal algorithm doesn't seem worthwhile. + */ + +GLOBAL(void) +jpeg_gen_optimal_table (j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[]) +{ +#define MAX_CLEN 32 /* assumed maximum initial code length */ + UINT8 bits[MAX_CLEN+1]; /* bits[k] = # of symbols with code length k */ + int codesize[257]; /* codesize[k] = code length of symbol k */ + int others[257]; /* next symbol in current branch of tree */ + int c1, c2; + int p, i, j; + long v; + + /* This algorithm is explained in section K.2 of the JPEG standard */ + + MEMZERO(bits, SIZEOF(bits)); + MEMZERO(codesize, SIZEOF(codesize)); + for (i = 0; i < 257; i++) + others[i] = -1; /* init links to empty */ + + freq[256] = 1; /* make sure 256 has a nonzero count */ + /* Including the pseudo-symbol 256 in the Huffman procedure guarantees + * that no real symbol is given code-value of all ones, because 256 + * will be placed last in the largest codeword category. + */ + + /* Huffman's basic algorithm to assign optimal code lengths to symbols */ + + for (;;) { + /* Find the smallest nonzero frequency, set c1 = its symbol */ + /* In case of ties, take the larger symbol number */ + c1 = -1; + v = 1000000000L; + for (i = 0; i <= 256; i++) { + if (freq[i] && freq[i] <= v) { + v = freq[i]; + c1 = i; + } + } + + /* Find the next smallest nonzero frequency, set c2 = its symbol */ + /* In case of ties, take the larger symbol number */ + c2 = -1; + v = 1000000000L; + for (i = 0; i <= 256; i++) { + if (freq[i] && freq[i] <= v && i != c1) { + v = freq[i]; + c2 = i; + } + } + + /* Done if we've merged everything into one frequency */ + if (c2 < 0) + break; + + /* Else merge the two counts/trees */ + freq[c1] += freq[c2]; + freq[c2] = 0; + + /* Increment the codesize of everything in c1's tree branch */ + codesize[c1]++; + while (others[c1] >= 0) { + c1 = others[c1]; + codesize[c1]++; + } + + others[c1] = c2; /* chain c2 onto c1's tree branch */ + + /* Increment the codesize of everything in c2's tree branch */ + codesize[c2]++; + while (others[c2] >= 0) { + c2 = others[c2]; + codesize[c2]++; + } + } + + /* Now count the number of symbols of each code length */ + for (i = 0; i <= 256; i++) { + if (codesize[i]) { + /* The JPEG standard seems to think that this can't happen, */ + /* but I'm paranoid... */ + if (codesize[i] > MAX_CLEN) + ERREXIT(cinfo, JERR_HUFF_CLEN_OVERFLOW); + + bits[codesize[i]]++; + } + } + + /* JPEG doesn't allow symbols with code lengths over 16 bits, so if the pure + * Huffman procedure assigned any such lengths, we must adjust the coding. + * Here is what the JPEG spec says about how this next bit works: + * Since symbols are paired for the longest Huffman code, the symbols are + * removed from this length category two at a time. The prefix for the pair + * (which is one bit shorter) is allocated to one of the pair; then, + * skipping the BITS entry for that prefix length, a code word from the next + * shortest nonzero BITS entry is converted into a prefix for two code words + * one bit longer. + */ + + for (i = MAX_CLEN; i > 16; i--) { + while (bits[i] > 0) { + j = i - 2; /* find length of new prefix to be used */ + while (bits[j] == 0) + j--; + + bits[i] -= 2; /* remove two symbols */ + bits[i-1]++; /* one goes in this length */ + bits[j+1] += 2; /* two new symbols in this length */ + bits[j]--; /* symbol of this length is now a prefix */ + } + } + + /* Remove the count for the pseudo-symbol 256 from the largest codelength */ + while (bits[i] == 0) /* find largest codelength still in use */ + i--; + bits[i]--; + + /* Return final symbol counts (only for lengths 0..16) */ + MEMCOPY(htbl->bits, bits, SIZEOF(htbl->bits)); + + /* Return a list of the symbols sorted by code length */ + /* It's not real clear to me why we don't need to consider the codelength + * changes made above, but the JPEG spec seems to think this works. + */ + p = 0; + for (i = 1; i <= MAX_CLEN; i++) { + for (j = 0; j <= 255; j++) { + if (codesize[j] == i) { + htbl->huffval[p] = (UINT8) j; + p++; + } + } + } + + /* Set sent_table FALSE so updated table will be written to JPEG file. */ + htbl->sent_table = FALSE; +} + + +/* + * Finish up a statistics-gathering pass and create the new Huffman tables. + */ + +METHODDEF(void) +finish_pass_gather (j_compress_ptr cinfo) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + int ci, dctbl, actbl; + jpeg_component_info * compptr; + JHUFF_TBL **htblptr; + boolean did_dc[NUM_HUFF_TBLS]; + boolean did_ac[NUM_HUFF_TBLS]; + + /* It's important not to apply jpeg_gen_optimal_table more than once + * per table, because it clobbers the input frequency counts! + */ + MEMZERO(did_dc, SIZEOF(did_dc)); + MEMZERO(did_ac, SIZEOF(did_ac)); + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + dctbl = compptr->dc_tbl_no; + actbl = compptr->ac_tbl_no; + if (! did_dc[dctbl]) { + htblptr = & cinfo->dc_huff_tbl_ptrs[dctbl]; + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + jpeg_gen_optimal_table(cinfo, *htblptr, entropy->dc_count_ptrs[dctbl]); + did_dc[dctbl] = TRUE; + } + if (! did_ac[actbl]) { + htblptr = & cinfo->ac_huff_tbl_ptrs[actbl]; + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + jpeg_gen_optimal_table(cinfo, *htblptr, entropy->ac_count_ptrs[actbl]); + did_ac[actbl] = TRUE; + } + } +} + + +#endif /* ENTROPY_OPT_SUPPORTED */ + + +/* + * Module initialization routine for Huffman entropy encoding. + */ + +GLOBAL(void) +jinit_huff_encoder (j_compress_ptr cinfo) +{ + huff_entropy_ptr entropy; + int i; + + entropy = (huff_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(huff_entropy_encoder)); + cinfo->entropy = (struct jpeg_entropy_encoder *) entropy; + entropy->pub.start_pass = start_pass_huff; + + /* Mark tables unallocated */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL; +#ifdef ENTROPY_OPT_SUPPORTED + entropy->dc_count_ptrs[i] = entropy->ac_count_ptrs[i] = NULL; +#endif + } +} diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jchuff.h b/lc-continuity/mk4/modimage/jpeg-6b/jchuff.h new file mode 100644 index 0000000000000000000000000000000000000000..a9599fc1e6f9613ca5b7ce02a3b734f0c89cba51 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jchuff.h @@ -0,0 +1,47 @@ +/* + * jchuff.h + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains declarations for Huffman entropy encoding routines + * that are shared between the sequential encoder (jchuff.c) and the + * progressive encoder (jcphuff.c). No other modules need to see these. + */ + +/* The legal range of a DCT coefficient is + * -1024 .. +1023 for 8-bit data; + * -16384 .. +16383 for 12-bit data. + * Hence the magnitude should always fit in 10 or 14 bits respectively. + */ + +#if BITS_IN_JSAMPLE == 8 +#define MAX_COEF_BITS 10 +#else +#define MAX_COEF_BITS 14 +#endif + +/* Derived data constructed for each Huffman table */ + +typedef struct { + unsigned int ehufco[256]; /* code for each symbol */ + char ehufsi[256]; /* length of code for each symbol */ + /* If no code has been allocated for a symbol S, ehufsi[S] contains 0 */ +} c_derived_tbl; + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_make_c_derived_tbl jMkCDerived +#define jpeg_gen_optimal_table jGenOptTbl +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + +/* Expand a Huffman table definition into the derived format */ +EXTERN(void) jpeg_make_c_derived_tbl + JPP((j_compress_ptr cinfo, boolean isDC, int tblno, + c_derived_tbl ** pdtbl)); + +/* Generate an optimal table definition given the specified counts */ +EXTERN(void) jpeg_gen_optimal_table + JPP((j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[])); diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jcinit.c b/lc-continuity/mk4/modimage/jpeg-6b/jcinit.c new file mode 100644 index 0000000000000000000000000000000000000000..5efffe33166bc0d6ac7ea8c691a00be5b9ff0de8 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jcinit.c @@ -0,0 +1,72 @@ +/* + * jcinit.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains initialization logic for the JPEG compressor. + * This routine is in charge of selecting the modules to be executed and + * making an initialization call to each one. + * + * Logically, this code belongs in jcmaster.c. It's split out because + * linking this routine implies linking the entire compression library. + * For a transcoding-only application, we want to be able to use jcmaster.c + * without linking in the whole library. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* + * Master selection of compression modules. + * This is done once at the start of processing an image. We determine + * which modules will be used and give them appropriate initialization calls. + */ + +GLOBAL(void) +jinit_compress_master (j_compress_ptr cinfo) +{ + /* Initialize master control (includes parameter checking/processing) */ + jinit_c_master_control(cinfo, FALSE /* full compression */); + + /* Preprocessing */ + if (! cinfo->raw_data_in) { + jinit_color_converter(cinfo); + jinit_downsampler(cinfo); + jinit_c_prep_controller(cinfo, FALSE /* never need full buffer here */); + } + /* Forward DCT */ + jinit_forward_dct(cinfo); + /* Entropy encoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) { + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); + } else { + if (cinfo->progressive_mode) { +#ifdef C_PROGRESSIVE_SUPPORTED + jinit_phuff_encoder(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else + jinit_huff_encoder(cinfo); + } + + /* Need a full-image coefficient buffer in any multi-pass mode. */ + jinit_c_coef_controller(cinfo, + (boolean) (cinfo->num_scans > 1 || cinfo->optimize_coding)); + jinit_c_main_controller(cinfo, FALSE /* never need full buffer here */); + + jinit_marker_writer(cinfo); + + /* We can now tell the memory manager to allocate virtual arrays. */ + (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); + + /* Write the datastream header (SOI) immediately. + * Frame and scan headers are postponed till later. + * This lets application insert special markers after the SOI. + */ + (*cinfo->marker->write_file_header) (cinfo); +} diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jcmainct.c b/lc-continuity/mk4/modimage/jpeg-6b/jcmainct.c new file mode 100644 index 0000000000000000000000000000000000000000..e0279a7e017a2ee5a3c6f5bc434e220ddcebbfc5 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jcmainct.c @@ -0,0 +1,293 @@ +/* + * jcmainct.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the main buffer controller for compression. + * The main buffer lies between the pre-processor and the JPEG + * compressor proper; it holds downsampled data in the JPEG colorspace. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Note: currently, there is no operating mode in which a full-image buffer + * is needed at this step. If there were, that mode could not be used with + * "raw data" input, since this module is bypassed in that case. However, + * we've left the code here for possible use in special applications. + */ +#undef FULL_MAIN_BUFFER_SUPPORTED + + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_c_main_controller pub; /* public fields */ + + JDIMENSION cur_iMCU_row; /* number of current iMCU row */ + JDIMENSION rowgroup_ctr; /* counts row groups received in iMCU row */ + boolean suspended; /* remember if we suspended output */ + J_BUF_MODE pass_mode; /* current operating mode */ + + /* If using just a strip buffer, this points to the entire set of buffers + * (we allocate one for each component). In the full-image case, this + * points to the currently accessible strips of the virtual arrays. + */ + JSAMPARRAY buffer[MAX_COMPONENTS]; + +#ifdef FULL_MAIN_BUFFER_SUPPORTED + /* If using full-image storage, this array holds pointers to virtual-array + * control blocks for each component. Unused if not full-image storage. + */ + jvirt_sarray_ptr whole_image[MAX_COMPONENTS]; +#endif +} my_main_controller; + +typedef my_main_controller * my_main_ptr; + + +/* Forward declarations */ +METHODDEF(void) process_data_simple_main + JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf, + JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail)); +#ifdef FULL_MAIN_BUFFER_SUPPORTED +METHODDEF(void) process_data_buffer_main + JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf, + JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail)); +#endif + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_main (j_compress_ptr cinfo, J_BUF_MODE pass_mode) +{ + my_main_ptr main = (my_main_ptr) cinfo->main; + + /* Do nothing in raw-data mode. */ + if (cinfo->raw_data_in) + return; + + main->cur_iMCU_row = 0; /* initialize counters */ + main->rowgroup_ctr = 0; + main->suspended = FALSE; + main->pass_mode = pass_mode; /* save mode for use by process_data */ + + switch (pass_mode) { + case JBUF_PASS_THRU: +#ifdef FULL_MAIN_BUFFER_SUPPORTED + if (main->whole_image[0] != NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); +#endif + main->pub.process_data = process_data_simple_main; + break; +#ifdef FULL_MAIN_BUFFER_SUPPORTED + case JBUF_SAVE_SOURCE: + case JBUF_CRANK_DEST: + case JBUF_SAVE_AND_PASS: + if (main->whole_image[0] == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + main->pub.process_data = process_data_buffer_main; + break; +#endif + default: + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + break; + } +} + + +/* + * Process some data. + * This routine handles the simple pass-through mode, + * where we have only a strip buffer. + */ + +METHODDEF(void) +process_data_simple_main (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail) +{ + my_main_ptr main = (my_main_ptr) cinfo->main; + + while (main->cur_iMCU_row < cinfo->total_iMCU_rows) { + /* Read input data if we haven't filled the main buffer yet */ + if (main->rowgroup_ctr < DCTSIZE) + (*cinfo->prep->pre_process_data) (cinfo, + input_buf, in_row_ctr, in_rows_avail, + main->buffer, &main->rowgroup_ctr, + (JDIMENSION) DCTSIZE); + + /* If we don't have a full iMCU row buffered, return to application for + * more data. Note that preprocessor will always pad to fill the iMCU row + * at the bottom of the image. + */ + if (main->rowgroup_ctr != DCTSIZE) + return; + + /* Send the completed row to the compressor */ + if (! (*cinfo->coef->compress_data) (cinfo, main->buffer)) { + /* If compressor did not consume the whole row, then we must need to + * suspend processing and return to the application. In this situation + * we pretend we didn't yet consume the last input row; otherwise, if + * it happened to be the last row of the image, the application would + * think we were done. + */ + if (! main->suspended) { + (*in_row_ctr)--; + main->suspended = TRUE; + } + return; + } + /* We did finish the row. Undo our little suspension hack if a previous + * call suspended; then mark the main buffer empty. + */ + if (main->suspended) { + (*in_row_ctr)++; + main->suspended = FALSE; + } + main->rowgroup_ctr = 0; + main->cur_iMCU_row++; + } +} + + +#ifdef FULL_MAIN_BUFFER_SUPPORTED + +/* + * Process some data. + * This routine handles all of the modes that use a full-size buffer. + */ + +METHODDEF(void) +process_data_buffer_main (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail) +{ + my_main_ptr main = (my_main_ptr) cinfo->main; + int ci; + jpeg_component_info *compptr; + boolean writing = (main->pass_mode != JBUF_CRANK_DEST); + + while (main->cur_iMCU_row < cinfo->total_iMCU_rows) { + /* Realign the virtual buffers if at the start of an iMCU row. */ + if (main->rowgroup_ctr == 0) { + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + main->buffer[ci] = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, main->whole_image[ci], + main->cur_iMCU_row * (compptr->v_samp_factor * DCTSIZE), + (JDIMENSION) (compptr->v_samp_factor * DCTSIZE), writing); + } + /* In a read pass, pretend we just read some source data. */ + if (! writing) { + *in_row_ctr += cinfo->max_v_samp_factor * DCTSIZE; + main->rowgroup_ctr = DCTSIZE; + } + } + + /* If a write pass, read input data until the current iMCU row is full. */ + /* Note: preprocessor will pad if necessary to fill the last iMCU row. */ + if (writing) { + (*cinfo->prep->pre_process_data) (cinfo, + input_buf, in_row_ctr, in_rows_avail, + main->buffer, &main->rowgroup_ctr, + (JDIMENSION) DCTSIZE); + /* Return to application if we need more data to fill the iMCU row. */ + if (main->rowgroup_ctr < DCTSIZE) + return; + } + + /* Emit data, unless this is a sink-only pass. */ + if (main->pass_mode != JBUF_SAVE_SOURCE) { + if (! (*cinfo->coef->compress_data) (cinfo, main->buffer)) { + /* If compressor did not consume the whole row, then we must need to + * suspend processing and return to the application. In this situation + * we pretend we didn't yet consume the last input row; otherwise, if + * it happened to be the last row of the image, the application would + * think we were done. + */ + if (! main->suspended) { + (*in_row_ctr)--; + main->suspended = TRUE; + } + return; + } + /* We did finish the row. Undo our little suspension hack if a previous + * call suspended; then mark the main buffer empty. + */ + if (main->suspended) { + (*in_row_ctr)++; + main->suspended = FALSE; + } + } + + /* If get here, we are done with this iMCU row. Mark buffer empty. */ + main->rowgroup_ctr = 0; + main->cur_iMCU_row++; + } +} + +#endif /* FULL_MAIN_BUFFER_SUPPORTED */ + + +/* + * Initialize main buffer controller. + */ + +GLOBAL(void) +jinit_c_main_controller (j_compress_ptr cinfo, boolean need_full_buffer) +{ + my_main_ptr main; + int ci; + jpeg_component_info *compptr; + + main = (my_main_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_main_controller)); + cinfo->main = (struct jpeg_c_main_controller *) main; + main->pub.start_pass = start_pass_main; + + /* We don't need to create a buffer in raw-data mode. */ + if (cinfo->raw_data_in) + return; + + /* Create the buffer. It holds downsampled data, so each component + * may be of a different size. + */ + if (need_full_buffer) { +#ifdef FULL_MAIN_BUFFER_SUPPORTED + /* Allocate a full-image virtual array for each component */ + /* Note we pad the bottom to a multiple of the iMCU height */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + main->whole_image[ci] = (*cinfo->mem->request_virt_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, + compptr->width_in_blocks * DCTSIZE, + (JDIMENSION) jround_up((long) compptr->height_in_blocks, + (long) compptr->v_samp_factor) * DCTSIZE, + (JDIMENSION) (compptr->v_samp_factor * DCTSIZE)); + } +#else + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); +#endif + } else { +#ifdef FULL_MAIN_BUFFER_SUPPORTED + main->whole_image[0] = NULL; /* flag for no virtual arrays */ +#endif + /* Allocate a strip buffer for each component */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + main->buffer[ci] = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + compptr->width_in_blocks * DCTSIZE, + (JDIMENSION) (compptr->v_samp_factor * DCTSIZE)); + } + } +} diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jcmarker.c b/lc-continuity/mk4/modimage/jpeg-6b/jcmarker.c new file mode 100644 index 0000000000000000000000000000000000000000..3d1e6c6d524850e0d401fcec9f590d5648d13ee7 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jcmarker.c @@ -0,0 +1,664 @@ +/* + * jcmarker.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains routines to write JPEG datastream markers. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +typedef enum { /* JPEG marker codes */ + M_SOF0 = 0xc0, + M_SOF1 = 0xc1, + M_SOF2 = 0xc2, + M_SOF3 = 0xc3, + + M_SOF5 = 0xc5, + M_SOF6 = 0xc6, + M_SOF7 = 0xc7, + + M_JPG = 0xc8, + M_SOF9 = 0xc9, + M_SOF10 = 0xca, + M_SOF11 = 0xcb, + + M_SOF13 = 0xcd, + M_SOF14 = 0xce, + M_SOF15 = 0xcf, + + M_DHT = 0xc4, + + M_DAC = 0xcc, + + M_RST0 = 0xd0, + M_RST1 = 0xd1, + M_RST2 = 0xd2, + M_RST3 = 0xd3, + M_RST4 = 0xd4, + M_RST5 = 0xd5, + M_RST6 = 0xd6, + M_RST7 = 0xd7, + + M_SOI = 0xd8, + M_EOI = 0xd9, + M_SOS = 0xda, + M_DQT = 0xdb, + M_DNL = 0xdc, + M_DRI = 0xdd, + M_DHP = 0xde, + M_EXP = 0xdf, + + M_APP0 = 0xe0, + M_APP1 = 0xe1, + M_APP2 = 0xe2, + M_APP3 = 0xe3, + M_APP4 = 0xe4, + M_APP5 = 0xe5, + M_APP6 = 0xe6, + M_APP7 = 0xe7, + M_APP8 = 0xe8, + M_APP9 = 0xe9, + M_APP10 = 0xea, + M_APP11 = 0xeb, + M_APP12 = 0xec, + M_APP13 = 0xed, + M_APP14 = 0xee, + M_APP15 = 0xef, + + M_JPG0 = 0xf0, + M_JPG13 = 0xfd, + M_COM = 0xfe, + + M_TEM = 0x01, + + M_ERROR = 0x100 +} JPEG_MARKER; + + +/* Private state */ + +typedef struct { + struct jpeg_marker_writer pub; /* public fields */ + + unsigned int last_restart_interval; /* last DRI value emitted; 0 after SOI */ +} my_marker_writer; + +typedef my_marker_writer * my_marker_ptr; + + +/* + * Basic output routines. + * + * Note that we do not support suspension while writing a marker. + * Therefore, an application using suspension must ensure that there is + * enough buffer space for the initial markers (typ. 600-700 bytes) before + * calling jpeg_start_compress, and enough space to write the trailing EOI + * (a few bytes) before calling jpeg_finish_compress. Multipass compression + * modes are not supported at all with suspension, so those two are the only + * points where markers will be written. + */ + +LOCAL(void) +emit_byte (j_compress_ptr cinfo, int val) +/* Emit a byte */ +{ + struct jpeg_destination_mgr * dest = cinfo->dest; + + *(dest->next_output_byte)++ = (JOCTET) val; + if (--dest->free_in_buffer == 0) { + if (! (*dest->empty_output_buffer) (cinfo)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); + } +} + + +LOCAL(void) +emit_marker (j_compress_ptr cinfo, JPEG_MARKER mark) +/* Emit a marker code */ +{ + emit_byte(cinfo, 0xFF); + emit_byte(cinfo, (int) mark); +} + + +LOCAL(void) +emit_2bytes (j_compress_ptr cinfo, int value) +/* Emit a 2-byte integer; these are always MSB first in JPEG files */ +{ + emit_byte(cinfo, (value >> 8) & 0xFF); + emit_byte(cinfo, value & 0xFF); +} + + +/* + * Routines to write specific marker types. + */ + +LOCAL(int) +emit_dqt (j_compress_ptr cinfo, int index) +/* Emit a DQT marker */ +/* Returns the precision used (0 = 8bits, 1 = 16bits) for baseline checking */ +{ + JQUANT_TBL * qtbl = cinfo->quant_tbl_ptrs[index]; + int prec; + int i; + + if (qtbl == NULL) + ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, index); + + prec = 0; + for (i = 0; i < DCTSIZE2; i++) { + if (qtbl->quantval[i] > 255) + prec = 1; + } + + if (! qtbl->sent_table) { + emit_marker(cinfo, M_DQT); + + emit_2bytes(cinfo, prec ? DCTSIZE2*2 + 1 + 2 : DCTSIZE2 + 1 + 2); + + emit_byte(cinfo, index + (prec<<4)); + + for (i = 0; i < DCTSIZE2; i++) { + /* The table entries must be emitted in zigzag order. */ + unsigned int qval = qtbl->quantval[jpeg_natural_order[i]]; + if (prec) + emit_byte(cinfo, (int) (qval >> 8)); + emit_byte(cinfo, (int) (qval & 0xFF)); + } + + qtbl->sent_table = TRUE; + } + + return prec; +} + + +LOCAL(void) +emit_dht (j_compress_ptr cinfo, int index, boolean is_ac) +/* Emit a DHT marker */ +{ + JHUFF_TBL * htbl; + int length, i; + + if (is_ac) { + htbl = cinfo->ac_huff_tbl_ptrs[index]; + index += 0x10; /* output index has AC bit set */ + } else { + htbl = cinfo->dc_huff_tbl_ptrs[index]; + } + + if (htbl == NULL) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, index); + + if (! htbl->sent_table) { + emit_marker(cinfo, M_DHT); + + length = 0; + for (i = 1; i <= 16; i++) + length += htbl->bits[i]; + + emit_2bytes(cinfo, length + 2 + 1 + 16); + emit_byte(cinfo, index); + + for (i = 1; i <= 16; i++) + emit_byte(cinfo, htbl->bits[i]); + + for (i = 0; i < length; i++) + emit_byte(cinfo, htbl->huffval[i]); + + htbl->sent_table = TRUE; + } +} + + +LOCAL(void) +emit_dac (j_compress_ptr cinfo) +/* Emit a DAC marker */ +/* Since the useful info is so small, we want to emit all the tables in */ +/* one DAC marker. Therefore this routine does its own scan of the table. */ +{ +#ifdef C_ARITH_CODING_SUPPORTED + char dc_in_use[NUM_ARITH_TBLS]; + char ac_in_use[NUM_ARITH_TBLS]; + int length, i; + jpeg_component_info *compptr; + + for (i = 0; i < NUM_ARITH_TBLS; i++) + dc_in_use[i] = ac_in_use[i] = 0; + + for (i = 0; i < cinfo->comps_in_scan; i++) { + compptr = cinfo->cur_comp_info[i]; + dc_in_use[compptr->dc_tbl_no] = 1; + ac_in_use[compptr->ac_tbl_no] = 1; + } + + length = 0; + for (i = 0; i < NUM_ARITH_TBLS; i++) + length += dc_in_use[i] + ac_in_use[i]; + + emit_marker(cinfo, M_DAC); + + emit_2bytes(cinfo, length*2 + 2); + + for (i = 0; i < NUM_ARITH_TBLS; i++) { + if (dc_in_use[i]) { + emit_byte(cinfo, i); + emit_byte(cinfo, cinfo->arith_dc_L[i] + (cinfo->arith_dc_U[i]<<4)); + } + if (ac_in_use[i]) { + emit_byte(cinfo, i + 0x10); + emit_byte(cinfo, cinfo->arith_ac_K[i]); + } + } +#endif /* C_ARITH_CODING_SUPPORTED */ +} + + +LOCAL(void) +emit_dri (j_compress_ptr cinfo) +/* Emit a DRI marker */ +{ + emit_marker(cinfo, M_DRI); + + emit_2bytes(cinfo, 4); /* fixed length */ + + emit_2bytes(cinfo, (int) cinfo->restart_interval); +} + + +LOCAL(void) +emit_sof (j_compress_ptr cinfo, JPEG_MARKER code) +/* Emit a SOF marker */ +{ + int ci; + jpeg_component_info *compptr; + + emit_marker(cinfo, code); + + emit_2bytes(cinfo, 3 * cinfo->num_components + 2 + 5 + 1); /* length */ + + /* Make sure image isn't bigger than SOF field can handle */ + if ((long) cinfo->image_height > 65535L || + (long) cinfo->image_width > 65535L) + ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) 65535); + + emit_byte(cinfo, cinfo->data_precision); + emit_2bytes(cinfo, (int) cinfo->image_height); + emit_2bytes(cinfo, (int) cinfo->image_width); + + emit_byte(cinfo, cinfo->num_components); + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + emit_byte(cinfo, compptr->component_id); + emit_byte(cinfo, (compptr->h_samp_factor << 4) + compptr->v_samp_factor); + emit_byte(cinfo, compptr->quant_tbl_no); + } +} + + +LOCAL(void) +emit_sos (j_compress_ptr cinfo) +/* Emit a SOS marker */ +{ + int i, td, ta; + jpeg_component_info *compptr; + + emit_marker(cinfo, M_SOS); + + emit_2bytes(cinfo, 2 * cinfo->comps_in_scan + 2 + 1 + 3); /* length */ + + emit_byte(cinfo, cinfo->comps_in_scan); + + for (i = 0; i < cinfo->comps_in_scan; i++) { + compptr = cinfo->cur_comp_info[i]; + emit_byte(cinfo, compptr->component_id); + td = compptr->dc_tbl_no; + ta = compptr->ac_tbl_no; + if (cinfo->progressive_mode) { + /* Progressive mode: only DC or only AC tables are used in one scan; + * furthermore, Huffman coding of DC refinement uses no table at all. + * We emit 0 for unused field(s); this is recommended by the P&M text + * but does not seem to be specified in the standard. + */ + if (cinfo->Ss == 0) { + ta = 0; /* DC scan */ + if (cinfo->Ah != 0 && !cinfo->arith_code) + td = 0; /* no DC table either */ + } else { + td = 0; /* AC scan */ + } + } + emit_byte(cinfo, (td << 4) + ta); + } + + emit_byte(cinfo, cinfo->Ss); + emit_byte(cinfo, cinfo->Se); + emit_byte(cinfo, (cinfo->Ah << 4) + cinfo->Al); +} + + +LOCAL(void) +emit_jfif_app0 (j_compress_ptr cinfo) +/* Emit a JFIF-compliant APP0 marker */ +{ + /* + * Length of APP0 block (2 bytes) + * Block ID (4 bytes - ASCII "JFIF") + * Zero byte (1 byte to terminate the ID string) + * Version Major, Minor (2 bytes - major first) + * Units (1 byte - 0x00 = none, 0x01 = inch, 0x02 = cm) + * Xdpu (2 bytes - dots per unit horizontal) + * Ydpu (2 bytes - dots per unit vertical) + * Thumbnail X size (1 byte) + * Thumbnail Y size (1 byte) + */ + + emit_marker(cinfo, M_APP0); + + emit_2bytes(cinfo, 2 + 4 + 1 + 2 + 1 + 2 + 2 + 1 + 1); /* length */ + + emit_byte(cinfo, 0x4A); /* Identifier: ASCII "JFIF" */ + emit_byte(cinfo, 0x46); + emit_byte(cinfo, 0x49); + emit_byte(cinfo, 0x46); + emit_byte(cinfo, 0); + emit_byte(cinfo, cinfo->JFIF_major_version); /* Version fields */ + emit_byte(cinfo, cinfo->JFIF_minor_version); + emit_byte(cinfo, cinfo->density_unit); /* Pixel size information */ + emit_2bytes(cinfo, (int) cinfo->X_density); + emit_2bytes(cinfo, (int) cinfo->Y_density); + emit_byte(cinfo, 0); /* No thumbnail image */ + emit_byte(cinfo, 0); +} + + +LOCAL(void) +emit_adobe_app14 (j_compress_ptr cinfo) +/* Emit an Adobe APP14 marker */ +{ + /* + * Length of APP14 block (2 bytes) + * Block ID (5 bytes - ASCII "Adobe") + * Version Number (2 bytes - currently 100) + * Flags0 (2 bytes - currently 0) + * Flags1 (2 bytes - currently 0) + * Color transform (1 byte) + * + * Although Adobe TN 5116 mentions Version = 101, all the Adobe files + * now in circulation seem to use Version = 100, so that's what we write. + * + * We write the color transform byte as 1 if the JPEG color space is + * YCbCr, 2 if it's YCCK, 0 otherwise. Adobe's definition has to do with + * whether the encoder performed a transformation, which is pretty useless. + */ + + emit_marker(cinfo, M_APP14); + + emit_2bytes(cinfo, 2 + 5 + 2 + 2 + 2 + 1); /* length */ + + emit_byte(cinfo, 0x41); /* Identifier: ASCII "Adobe" */ + emit_byte(cinfo, 0x64); + emit_byte(cinfo, 0x6F); + emit_byte(cinfo, 0x62); + emit_byte(cinfo, 0x65); + emit_2bytes(cinfo, 100); /* Version */ + emit_2bytes(cinfo, 0); /* Flags0 */ + emit_2bytes(cinfo, 0); /* Flags1 */ + switch (cinfo->jpeg_color_space) { + case JCS_YCbCr: + emit_byte(cinfo, 1); /* Color transform = 1 */ + break; + case JCS_YCCK: + emit_byte(cinfo, 2); /* Color transform = 2 */ + break; + default: + emit_byte(cinfo, 0); /* Color transform = 0 */ + break; + } +} + + +/* + * These routines allow writing an arbitrary marker with parameters. + * The only intended use is to emit COM or APPn markers after calling + * write_file_header and before calling write_frame_header. + * Other uses are not guaranteed to produce desirable results. + * Counting the parameter bytes properly is the caller's responsibility. + */ + +METHODDEF(void) +write_marker_header (j_compress_ptr cinfo, int marker, unsigned int datalen) +/* Emit an arbitrary marker header */ +{ + if (datalen > (unsigned int) 65533) /* safety check */ + ERREXIT(cinfo, JERR_BAD_LENGTH); + + emit_marker(cinfo, (JPEG_MARKER) marker); + + emit_2bytes(cinfo, (int) (datalen + 2)); /* total length */ +} + +METHODDEF(void) +write_marker_byte (j_compress_ptr cinfo, int val) +/* Emit one byte of marker parameters following write_marker_header */ +{ + emit_byte(cinfo, val); +} + + +/* + * Write datastream header. + * This consists of an SOI and optional APPn markers. + * We recommend use of the JFIF marker, but not the Adobe marker, + * when using YCbCr or grayscale data. The JFIF marker should NOT + * be used for any other JPEG colorspace. The Adobe marker is helpful + * to distinguish RGB, CMYK, and YCCK colorspaces. + * Note that an application can write additional header markers after + * jpeg_start_compress returns. + */ + +METHODDEF(void) +write_file_header (j_compress_ptr cinfo) +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + + emit_marker(cinfo, M_SOI); /* first the SOI */ + + /* SOI is defined to reset restart interval to 0 */ + marker->last_restart_interval = 0; + + if (cinfo->write_JFIF_header) /* next an optional JFIF APP0 */ + emit_jfif_app0(cinfo); + if (cinfo->write_Adobe_marker) /* next an optional Adobe APP14 */ + emit_adobe_app14(cinfo); +} + + +/* + * Write frame header. + * This consists of DQT and SOFn markers. + * Note that we do not emit the SOF until we have emitted the DQT(s). + * This avoids compatibility problems with incorrect implementations that + * try to error-check the quant table numbers as soon as they see the SOF. + */ + +METHODDEF(void) +write_frame_header (j_compress_ptr cinfo) +{ + int ci, prec; + boolean is_baseline; + jpeg_component_info *compptr; + + /* Emit DQT for each quantization table. + * Note that emit_dqt() suppresses any duplicate tables. + */ + prec = 0; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + prec += emit_dqt(cinfo, compptr->quant_tbl_no); + } + /* now prec is nonzero iff there are any 16-bit quant tables. */ + + /* Check for a non-baseline specification. + * Note we assume that Huffman table numbers won't be changed later. + */ + if (cinfo->arith_code || cinfo->progressive_mode || + cinfo->data_precision != 8) { + is_baseline = FALSE; + } else { + is_baseline = TRUE; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + if (compptr->dc_tbl_no > 1 || compptr->ac_tbl_no > 1) + is_baseline = FALSE; + } + if (prec && is_baseline) { + is_baseline = FALSE; + /* If it's baseline except for quantizer size, warn the user */ + TRACEMS(cinfo, 0, JTRC_16BIT_TABLES); + } + } + + /* Emit the proper SOF marker */ + if (cinfo->arith_code) { + emit_sof(cinfo, M_SOF9); /* SOF code for arithmetic coding */ + } else { + if (cinfo->progressive_mode) + emit_sof(cinfo, M_SOF2); /* SOF code for progressive Huffman */ + else if (is_baseline) + emit_sof(cinfo, M_SOF0); /* SOF code for baseline implementation */ + else + emit_sof(cinfo, M_SOF1); /* SOF code for non-baseline Huffman file */ + } +} + + +/* + * Write scan header. + * This consists of DHT or DAC markers, optional DRI, and SOS. + * Compressed data will be written following the SOS. + */ + +METHODDEF(void) +write_scan_header (j_compress_ptr cinfo) +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + int i; + jpeg_component_info *compptr; + + if (cinfo->arith_code) { + /* Emit arith conditioning info. We may have some duplication + * if the file has multiple scans, but it's so small it's hardly + * worth worrying about. + */ + emit_dac(cinfo); + } else { + /* Emit Huffman tables. + * Note that emit_dht() suppresses any duplicate tables. + */ + for (i = 0; i < cinfo->comps_in_scan; i++) { + compptr = cinfo->cur_comp_info[i]; + if (cinfo->progressive_mode) { + /* Progressive mode: only DC or only AC tables are used in one scan */ + if (cinfo->Ss == 0) { + if (cinfo->Ah == 0) /* DC needs no table for refinement scan */ + emit_dht(cinfo, compptr->dc_tbl_no, FALSE); + } else { + emit_dht(cinfo, compptr->ac_tbl_no, TRUE); + } + } else { + /* Sequential mode: need both DC and AC tables */ + emit_dht(cinfo, compptr->dc_tbl_no, FALSE); + emit_dht(cinfo, compptr->ac_tbl_no, TRUE); + } + } + } + + /* Emit DRI if required --- note that DRI value could change for each scan. + * We avoid wasting space with unnecessary DRIs, however. + */ + if (cinfo->restart_interval != marker->last_restart_interval) { + emit_dri(cinfo); + marker->last_restart_interval = cinfo->restart_interval; + } + + emit_sos(cinfo); +} + + +/* + * Write datastream trailer. + */ + +METHODDEF(void) +write_file_trailer (j_compress_ptr cinfo) +{ + emit_marker(cinfo, M_EOI); +} + + +/* + * Write an abbreviated table-specification datastream. + * This consists of SOI, DQT and DHT tables, and EOI. + * Any table that is defined and not marked sent_table = TRUE will be + * emitted. Note that all tables will be marked sent_table = TRUE at exit. + */ + +METHODDEF(void) +write_tables_only (j_compress_ptr cinfo) +{ + int i; + + emit_marker(cinfo, M_SOI); + + for (i = 0; i < NUM_QUANT_TBLS; i++) { + if (cinfo->quant_tbl_ptrs[i] != NULL) + (void) emit_dqt(cinfo, i); + } + + if (! cinfo->arith_code) { + for (i = 0; i < NUM_HUFF_TBLS; i++) { + if (cinfo->dc_huff_tbl_ptrs[i] != NULL) + emit_dht(cinfo, i, FALSE); + if (cinfo->ac_huff_tbl_ptrs[i] != NULL) + emit_dht(cinfo, i, TRUE); + } + } + + emit_marker(cinfo, M_EOI); +} + + +/* + * Initialize the marker writer module. + */ + +GLOBAL(void) +jinit_marker_writer (j_compress_ptr cinfo) +{ + my_marker_ptr marker; + + /* Create the subobject */ + marker = (my_marker_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_marker_writer)); + cinfo->marker = (struct jpeg_marker_writer *) marker; + /* Initialize method pointers */ + marker->pub.write_file_header = write_file_header; + marker->pub.write_frame_header = write_frame_header; + marker->pub.write_scan_header = write_scan_header; + marker->pub.write_file_trailer = write_file_trailer; + marker->pub.write_tables_only = write_tables_only; + marker->pub.write_marker_header = write_marker_header; + marker->pub.write_marker_byte = write_marker_byte; + /* Initialize private state */ + marker->last_restart_interval = 0; +} diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jcmaster.c b/lc-continuity/mk4/modimage/jpeg-6b/jcmaster.c new file mode 100644 index 0000000000000000000000000000000000000000..aab4020b8796ab29492aa1780898f3ccacc45413 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jcmaster.c @@ -0,0 +1,590 @@ +/* + * jcmaster.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains master control logic for the JPEG compressor. + * These routines are concerned with parameter validation, initial setup, + * and inter-pass control (determining the number of passes and the work + * to be done in each pass). + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Private state */ + +typedef enum { + main_pass, /* input data, also do first output step */ + huff_opt_pass, /* Huffman code optimization pass */ + output_pass /* data output pass */ +} c_pass_type; + +typedef struct { + struct jpeg_comp_master pub; /* public fields */ + + c_pass_type pass_type; /* the type of the current pass */ + + int pass_number; /* # of passes completed */ + int total_passes; /* total # of passes needed */ + + int scan_number; /* current index in scan_info[] */ +} my_comp_master; + +typedef my_comp_master * my_master_ptr; + + +/* + * Support routines that do various essential calculations. + */ + +LOCAL(void) +initial_setup (j_compress_ptr cinfo) +/* Do computations that are needed before master selection phase */ +{ + int ci; + jpeg_component_info *compptr; + long samplesperrow; + JDIMENSION jd_samplesperrow; + + /* Sanity check on image dimensions */ + if (cinfo->image_height <= 0 || cinfo->image_width <= 0 + || cinfo->num_components <= 0 || cinfo->input_components <= 0) + ERREXIT(cinfo, JERR_EMPTY_IMAGE); + + /* Make sure image isn't bigger than I can handle */ + if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION || + (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION) + ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION); + + /* Width of an input scanline must be representable as JDIMENSION. */ + samplesperrow = (long) cinfo->image_width * (long) cinfo->input_components; + jd_samplesperrow = (JDIMENSION) samplesperrow; + if ((long) jd_samplesperrow != samplesperrow) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + + /* For now, precision must match compiled-in value... */ + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + + /* Check that number of components won't exceed internal array sizes */ + if (cinfo->num_components > MAX_COMPONENTS) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, + MAX_COMPONENTS); + + /* Compute maximum sampling factors; check factor validity */ + cinfo->max_h_samp_factor = 1; + cinfo->max_v_samp_factor = 1; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR || + compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR) + ERREXIT(cinfo, JERR_BAD_SAMPLING); + cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor, + compptr->h_samp_factor); + cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor, + compptr->v_samp_factor); + } + + /* Compute dimensions of components */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Fill in the correct component_index value; don't rely on application */ + compptr->component_index = ci; + /* For compression, we never do DCT scaling. */ + compptr->DCT_scaled_size = DCTSIZE; + /* Size in DCT blocks */ + compptr->width_in_blocks = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, + (long) (cinfo->max_h_samp_factor * DCTSIZE)); + compptr->height_in_blocks = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, + (long) (cinfo->max_v_samp_factor * DCTSIZE)); + /* Size in samples */ + compptr->downsampled_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, + (long) cinfo->max_h_samp_factor); + compptr->downsampled_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, + (long) cinfo->max_v_samp_factor); + /* Mark component needed (this flag isn't actually used for compression) */ + compptr->component_needed = TRUE; + } + + /* Compute number of fully interleaved MCU rows (number of times that + * main controller will call coefficient controller). + */ + cinfo->total_iMCU_rows = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, + (long) (cinfo->max_v_samp_factor*DCTSIZE)); +} + + +#ifdef C_MULTISCAN_FILES_SUPPORTED + +LOCAL(void) +validate_script (j_compress_ptr cinfo) +/* Verify that the scan script in cinfo->scan_info[] is valid; also + * determine whether it uses progressive JPEG, and set cinfo->progressive_mode. + */ +{ + const jpeg_scan_info * scanptr; + int scanno, ncomps, ci, coefi, thisi; + int Ss, Se, Ah, Al; + boolean component_sent[MAX_COMPONENTS]; +#ifdef C_PROGRESSIVE_SUPPORTED + int * last_bitpos_ptr; + int last_bitpos[MAX_COMPONENTS][DCTSIZE2]; + /* -1 until that coefficient has been seen; then last Al for it */ +#endif + + if (cinfo->num_scans <= 0) + ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, 0); + + /* For sequential JPEG, all scans must have Ss=0, Se=DCTSIZE2-1; + * for progressive JPEG, no scan can have this. + */ + scanptr = cinfo->scan_info; + if (scanptr->Ss != 0 || scanptr->Se != DCTSIZE2-1) { +#ifdef C_PROGRESSIVE_SUPPORTED + cinfo->progressive_mode = TRUE; + last_bitpos_ptr = & last_bitpos[0][0]; + for (ci = 0; ci < cinfo->num_components; ci++) + for (coefi = 0; coefi < DCTSIZE2; coefi++) + *last_bitpos_ptr++ = -1; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + cinfo->progressive_mode = FALSE; + for (ci = 0; ci < cinfo->num_components; ci++) + component_sent[ci] = FALSE; + } + + for (scanno = 1; scanno <= cinfo->num_scans; scanptr++, scanno++) { + /* Validate component indexes */ + ncomps = scanptr->comps_in_scan; + if (ncomps <= 0 || ncomps > MAX_COMPS_IN_SCAN) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, ncomps, MAX_COMPS_IN_SCAN); + for (ci = 0; ci < ncomps; ci++) { + thisi = scanptr->component_index[ci]; + if (thisi < 0 || thisi >= cinfo->num_components) + ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); + /* Components must appear in SOF order within each scan */ + if (ci > 0 && thisi <= scanptr->component_index[ci-1]) + ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); + } + /* Validate progression parameters */ + Ss = scanptr->Ss; + Se = scanptr->Se; + Ah = scanptr->Ah; + Al = scanptr->Al; + if (cinfo->progressive_mode) { +#ifdef C_PROGRESSIVE_SUPPORTED + /* The JPEG spec simply gives the ranges 0..13 for Ah and Al, but that + * seems wrong: the upper bound ought to depend on data precision. + * Perhaps they really meant 0..N+1 for N-bit precision. + * Here we allow 0..10 for 8-bit data; Al larger than 10 results in + * out-of-range reconstructed DC values during the first DC scan, + * which might cause problems for some decoders. + */ +#if BITS_IN_JSAMPLE == 8 +#define MAX_AH_AL 10 +#else +#define MAX_AH_AL 13 +#endif + if (Ss < 0 || Ss >= DCTSIZE2 || Se < Ss || Se >= DCTSIZE2 || + Ah < 0 || Ah > MAX_AH_AL || Al < 0 || Al > MAX_AH_AL) + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + if (Ss == 0) { + if (Se != 0) /* DC and AC together not OK */ + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + } else { + if (ncomps != 1) /* AC scans must be for only one component */ + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + } + for (ci = 0; ci < ncomps; ci++) { + last_bitpos_ptr = & last_bitpos[scanptr->component_index[ci]][0]; + if (Ss != 0 && last_bitpos_ptr[0] < 0) /* AC without prior DC scan */ + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + for (coefi = Ss; coefi <= Se; coefi++) { + if (last_bitpos_ptr[coefi] < 0) { + /* first scan of this coefficient */ + if (Ah != 0) + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + } else { + /* not first scan */ + if (Ah != last_bitpos_ptr[coefi] || Al != Ah-1) + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + } + last_bitpos_ptr[coefi] = Al; + } + } +#endif + } else { + /* For sequential JPEG, all progression parameters must be these: */ + if (Ss != 0 || Se != DCTSIZE2-1 || Ah != 0 || Al != 0) + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + /* Make sure components are not sent twice */ + for (ci = 0; ci < ncomps; ci++) { + thisi = scanptr->component_index[ci]; + if (component_sent[thisi]) + ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); + component_sent[thisi] = TRUE; + } + } + } + + /* Now verify that everything got sent. */ + if (cinfo->progressive_mode) { +#ifdef C_PROGRESSIVE_SUPPORTED + /* For progressive mode, we only check that at least some DC data + * got sent for each component; the spec does not require that all bits + * of all coefficients be transmitted. Would it be wiser to enforce + * transmission of all coefficient bits?? + */ + for (ci = 0; ci < cinfo->num_components; ci++) { + if (last_bitpos[ci][0] < 0) + ERREXIT(cinfo, JERR_MISSING_DATA); + } +#endif + } else { + for (ci = 0; ci < cinfo->num_components; ci++) { + if (! component_sent[ci]) + ERREXIT(cinfo, JERR_MISSING_DATA); + } + } +} + +#endif /* C_MULTISCAN_FILES_SUPPORTED */ + + +LOCAL(void) +select_scan_parameters (j_compress_ptr cinfo) +/* Set up the scan parameters for the current scan */ +{ + int ci; + +#ifdef C_MULTISCAN_FILES_SUPPORTED + if (cinfo->scan_info != NULL) { + /* Prepare for current scan --- the script is already validated */ + my_master_ptr master = (my_master_ptr) cinfo->master; + const jpeg_scan_info * scanptr = cinfo->scan_info + master->scan_number; + + cinfo->comps_in_scan = scanptr->comps_in_scan; + for (ci = 0; ci < scanptr->comps_in_scan; ci++) { + cinfo->cur_comp_info[ci] = + &cinfo->comp_info[scanptr->component_index[ci]]; + } + cinfo->Ss = scanptr->Ss; + cinfo->Se = scanptr->Se; + cinfo->Ah = scanptr->Ah; + cinfo->Al = scanptr->Al; + } + else +#endif + { + /* Prepare for single sequential-JPEG scan containing all components */ + if (cinfo->num_components > MAX_COMPS_IN_SCAN) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, + MAX_COMPS_IN_SCAN); + cinfo->comps_in_scan = cinfo->num_components; + for (ci = 0; ci < cinfo->num_components; ci++) { + cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci]; + } + cinfo->Ss = 0; + cinfo->Se = DCTSIZE2-1; + cinfo->Ah = 0; + cinfo->Al = 0; + } +} + + +LOCAL(void) +per_scan_setup (j_compress_ptr cinfo) +/* Do computations that are needed before processing a JPEG scan */ +/* cinfo->comps_in_scan and cinfo->cur_comp_info[] are already set */ +{ + int ci, mcublks, tmp; + jpeg_component_info *compptr; + + if (cinfo->comps_in_scan == 1) { + + /* Noninterleaved (single-component) scan */ + compptr = cinfo->cur_comp_info[0]; + + /* Overall image size in MCUs */ + cinfo->MCUs_per_row = compptr->width_in_blocks; + cinfo->MCU_rows_in_scan = compptr->height_in_blocks; + + /* For noninterleaved scan, always one block per MCU */ + compptr->MCU_width = 1; + compptr->MCU_height = 1; + compptr->MCU_blocks = 1; + compptr->MCU_sample_width = DCTSIZE; + compptr->last_col_width = 1; + /* For noninterleaved scans, it is convenient to define last_row_height + * as the number of block rows present in the last iMCU row. + */ + tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor); + if (tmp == 0) tmp = compptr->v_samp_factor; + compptr->last_row_height = tmp; + + /* Prepare array describing MCU composition */ + cinfo->blocks_in_MCU = 1; + cinfo->MCU_membership[0] = 0; + + } else { + + /* Interleaved (multi-component) scan */ + if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan, + MAX_COMPS_IN_SCAN); + + /* Overall image size in MCUs */ + cinfo->MCUs_per_row = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, + (long) (cinfo->max_h_samp_factor*DCTSIZE)); + cinfo->MCU_rows_in_scan = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, + (long) (cinfo->max_v_samp_factor*DCTSIZE)); + + cinfo->blocks_in_MCU = 0; + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* Sampling factors give # of blocks of component in each MCU */ + compptr->MCU_width = compptr->h_samp_factor; + compptr->MCU_height = compptr->v_samp_factor; + compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height; + compptr->MCU_sample_width = compptr->MCU_width * DCTSIZE; + /* Figure number of non-dummy blocks in last MCU column & row */ + tmp = (int) (compptr->width_in_blocks % compptr->MCU_width); + if (tmp == 0) tmp = compptr->MCU_width; + compptr->last_col_width = tmp; + tmp = (int) (compptr->height_in_blocks % compptr->MCU_height); + if (tmp == 0) tmp = compptr->MCU_height; + compptr->last_row_height = tmp; + /* Prepare array describing MCU composition */ + mcublks = compptr->MCU_blocks; + if (cinfo->blocks_in_MCU + mcublks > C_MAX_BLOCKS_IN_MCU) + ERREXIT(cinfo, JERR_BAD_MCU_SIZE); + while (mcublks-- > 0) { + cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci; + } + } + + } + + /* Convert restart specified in rows to actual MCU count. */ + /* Note that count must fit in 16 bits, so we provide limiting. */ + if (cinfo->restart_in_rows > 0) { + long nominal = (long) cinfo->restart_in_rows * (long) cinfo->MCUs_per_row; + cinfo->restart_interval = (unsigned int) MIN(nominal, 65535L); + } +} + + +/* + * Per-pass setup. + * This is called at the beginning of each pass. We determine which modules + * will be active during this pass and give them appropriate start_pass calls. + * We also set is_last_pass to indicate whether any more passes will be + * required. + */ + +METHODDEF(void) +prepare_for_pass (j_compress_ptr cinfo) +{ + my_master_ptr master = (my_master_ptr) cinfo->master; + + switch (master->pass_type) { + case main_pass: + /* Initial pass: will collect input data, and do either Huffman + * optimization or data output for the first scan. + */ + select_scan_parameters(cinfo); + per_scan_setup(cinfo); + if (! cinfo->raw_data_in) { + (*cinfo->cconvert->start_pass) (cinfo); + (*cinfo->downsample->start_pass) (cinfo); + (*cinfo->prep->start_pass) (cinfo, JBUF_PASS_THRU); + } + (*cinfo->fdct->start_pass) (cinfo); + (*cinfo->entropy->start_pass) (cinfo, cinfo->optimize_coding); + (*cinfo->coef->start_pass) (cinfo, + (master->total_passes > 1 ? + JBUF_SAVE_AND_PASS : JBUF_PASS_THRU)); + (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU); + if (cinfo->optimize_coding) { + /* No immediate data output; postpone writing frame/scan headers */ + master->pub.call_pass_startup = FALSE; + } else { + /* Will write frame/scan headers at first jpeg_write_scanlines call */ + master->pub.call_pass_startup = TRUE; + } + break; +#ifdef ENTROPY_OPT_SUPPORTED + case huff_opt_pass: + /* Do Huffman optimization for a scan after the first one. */ + select_scan_parameters(cinfo); + per_scan_setup(cinfo); + if (cinfo->Ss != 0 || cinfo->Ah == 0 || cinfo->arith_code) { + (*cinfo->entropy->start_pass) (cinfo, TRUE); + (*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST); + master->pub.call_pass_startup = FALSE; + break; + } + /* Special case: Huffman DC refinement scans need no Huffman table + * and therefore we can skip the optimization pass for them. + */ + master->pass_type = output_pass; + master->pass_number++; + /*FALLTHROUGH*/ +#endif + case output_pass: + /* Do a data-output pass. */ + /* We need not repeat per-scan setup if prior optimization pass did it. */ + if (! cinfo->optimize_coding) { + select_scan_parameters(cinfo); + per_scan_setup(cinfo); + } + (*cinfo->entropy->start_pass) (cinfo, FALSE); + (*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST); + /* We emit frame/scan headers now */ + if (master->scan_number == 0) + (*cinfo->marker->write_frame_header) (cinfo); + (*cinfo->marker->write_scan_header) (cinfo); + master->pub.call_pass_startup = FALSE; + break; + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + } + + master->pub.is_last_pass = (master->pass_number == master->total_passes-1); + + /* Set up progress monitor's pass info if present */ + if (cinfo->progress != NULL) { + cinfo->progress->completed_passes = master->pass_number; + cinfo->progress->total_passes = master->total_passes; + } +} + + +/* + * Special start-of-pass hook. + * This is called by jpeg_write_scanlines if call_pass_startup is TRUE. + * In single-pass processing, we need this hook because we don't want to + * write frame/scan headers during jpeg_start_compress; we want to let the + * application write COM markers etc. between jpeg_start_compress and the + * jpeg_write_scanlines loop. + * In multi-pass processing, this routine is not used. + */ + +METHODDEF(void) +pass_startup (j_compress_ptr cinfo) +{ + cinfo->master->call_pass_startup = FALSE; /* reset flag so call only once */ + + (*cinfo->marker->write_frame_header) (cinfo); + (*cinfo->marker->write_scan_header) (cinfo); +} + + +/* + * Finish up at end of pass. + */ + +METHODDEF(void) +finish_pass_master (j_compress_ptr cinfo) +{ + my_master_ptr master = (my_master_ptr) cinfo->master; + + /* The entropy coder always needs an end-of-pass call, + * either to analyze statistics or to flush its output buffer. + */ + (*cinfo->entropy->finish_pass) (cinfo); + + /* Update state for next pass */ + switch (master->pass_type) { + case main_pass: + /* next pass is either output of scan 0 (after optimization) + * or output of scan 1 (if no optimization). + */ + master->pass_type = output_pass; + if (! cinfo->optimize_coding) + master->scan_number++; + break; + case huff_opt_pass: + /* next pass is always output of current scan */ + master->pass_type = output_pass; + break; + case output_pass: + /* next pass is either optimization or output of next scan */ + if (cinfo->optimize_coding) + master->pass_type = huff_opt_pass; + master->scan_number++; + break; + } + + master->pass_number++; +} + + +/* + * Initialize master compression control. + */ + +GLOBAL(void) +jinit_c_master_control (j_compress_ptr cinfo, boolean transcode_only) +{ + my_master_ptr master; + + master = (my_master_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_comp_master)); + cinfo->master = (struct jpeg_comp_master *) master; + master->pub.prepare_for_pass = prepare_for_pass; + master->pub.pass_startup = pass_startup; + master->pub.finish_pass = finish_pass_master; + master->pub.is_last_pass = FALSE; + + /* Validate parameters, determine derived values */ + initial_setup(cinfo); + + if (cinfo->scan_info != NULL) { +#ifdef C_MULTISCAN_FILES_SUPPORTED + validate_script(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + cinfo->progressive_mode = FALSE; + cinfo->num_scans = 1; + } + + if (cinfo->progressive_mode) /* TEMPORARY HACK ??? */ + cinfo->optimize_coding = TRUE; /* assume default tables no good for progressive mode */ + + /* Initialize my private state */ + if (transcode_only) { + /* no main pass in transcoding */ + if (cinfo->optimize_coding) + master->pass_type = huff_opt_pass; + else + master->pass_type = output_pass; + } else { + /* for normal compression, first pass is always this type: */ + master->pass_type = main_pass; + } + master->scan_number = 0; + master->pass_number = 0; + if (cinfo->optimize_coding) + master->total_passes = cinfo->num_scans * 2; + else + master->total_passes = cinfo->num_scans; +} diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jcomapi.c b/lc-continuity/mk4/modimage/jpeg-6b/jcomapi.c new file mode 100644 index 0000000000000000000000000000000000000000..9b1fa7568a67a7c25a599976ada93c53db665c57 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jcomapi.c @@ -0,0 +1,106 @@ +/* + * jcomapi.c + * + * Copyright (C) 1994-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains application interface routines that are used for both + * compression and decompression. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* + * Abort processing of a JPEG compression or decompression operation, + * but don't destroy the object itself. + * + * For this, we merely clean up all the nonpermanent memory pools. + * Note that temp files (virtual arrays) are not allowed to belong to + * the permanent pool, so we will be able to close all temp files here. + * Closing a data source or destination, if necessary, is the application's + * responsibility. + */ + +GLOBAL(void) +jpeg_abort (j_common_ptr cinfo) +{ + int pool; + + /* Do nothing if called on a not-initialized or destroyed JPEG object. */ + if (cinfo->mem == NULL) + return; + + /* Releasing pools in reverse order might help avoid fragmentation + * with some (brain-damaged) malloc libraries. + */ + for (pool = JPOOL_NUMPOOLS-1; pool > JPOOL_PERMANENT; pool--) { + (*cinfo->mem->free_pool) (cinfo, pool); + } + + /* Reset overall state for possible reuse of object */ + if (cinfo->is_decompressor) { + cinfo->global_state = DSTATE_START; + /* Try to keep application from accessing now-deleted marker list. + * A bit kludgy to do it here, but this is the most central place. + */ + ((j_decompress_ptr) cinfo)->marker_list = NULL; + } else { + cinfo->global_state = CSTATE_START; + } +} + + +/* + * Destruction of a JPEG object. + * + * Everything gets deallocated except the master jpeg_compress_struct itself + * and the error manager struct. Both of these are supplied by the application + * and must be freed, if necessary, by the application. (Often they are on + * the stack and so don't need to be freed anyway.) + * Closing a data source or destination, if necessary, is the application's + * responsibility. + */ + +GLOBAL(void) +jpeg_destroy (j_common_ptr cinfo) +{ + /* We need only tell the memory manager to release everything. */ + /* NB: mem pointer is NULL if memory mgr failed to initialize. */ + if (cinfo->mem != NULL) + (*cinfo->mem->self_destruct) (cinfo); + cinfo->mem = NULL; /* be safe if jpeg_destroy is called twice */ + cinfo->global_state = 0; /* mark it destroyed */ +} + + +/* + * Convenience routines for allocating quantization and Huffman tables. + * (Would jutils.c be a more reasonable place to put these?) + */ + +GLOBAL(JQUANT_TBL *) +jpeg_alloc_quant_table (j_common_ptr cinfo) +{ + JQUANT_TBL *tbl; + + tbl = (JQUANT_TBL *) + (*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JQUANT_TBL)); + tbl->sent_table = FALSE; /* make sure this is false in any new table */ + return tbl; +} + + +GLOBAL(JHUFF_TBL *) +jpeg_alloc_huff_table (j_common_ptr cinfo) +{ + JHUFF_TBL *tbl; + + tbl = (JHUFF_TBL *) + (*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JHUFF_TBL)); + tbl->sent_table = FALSE; /* make sure this is false in any new table */ + return tbl; +} diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jconfig.bcc b/lc-continuity/mk4/modimage/jpeg-6b/jconfig.bcc new file mode 100644 index 0000000000000000000000000000000000000000..c6c53ff63a7602c68c3f687a528caa3457857ab9 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jconfig.bcc @@ -0,0 +1,48 @@ +/* jconfig.bcc --- jconfig.h for Borland C (Turbo C) on MS-DOS or OS/2. */ +/* see jconfig.doc for explanations */ + +#define HAVE_PROTOTYPES +#define HAVE_UNSIGNED_CHAR +#define HAVE_UNSIGNED_SHORT +/* #define void char */ +/* #define const */ +#undef CHAR_IS_UNSIGNED +#define HAVE_STDDEF_H +#define HAVE_STDLIB_H +#undef NEED_BSD_STRINGS +#undef NEED_SYS_TYPES_H +#ifdef __MSDOS__ +#define NEED_FAR_POINTERS /* for small or medium memory model */ +#endif +#undef NEED_SHORT_EXTERNAL_NAMES +#undef INCOMPLETE_TYPES_BROKEN /* this assumes you have -w-stu in CFLAGS */ + +#ifdef JPEG_INTERNALS + +#undef RIGHT_SHIFT_IS_UNSIGNED + +#ifdef __MSDOS__ +#define USE_MSDOS_MEMMGR /* Define this if you use jmemdos.c */ +#define MAX_ALLOC_CHUNK 65520L /* Maximum request to malloc() */ +#define USE_FMEM /* Borland has _fmemcpy() and _fmemset() */ +#endif + +#endif /* JPEG_INTERNALS */ + +#ifdef JPEG_CJPEG_DJPEG + +#define BMP_SUPPORTED /* BMP image file format */ +#define GIF_SUPPORTED /* GIF image file format */ +#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ +#undef RLE_SUPPORTED /* Utah RLE image file format */ +#define TARGA_SUPPORTED /* Targa image file format */ + +#define TWO_FILE_COMMANDLINE +#define USE_SETMODE /* Borland has setmode() */ +#ifdef __MSDOS__ +#define NEED_SIGNAL_CATCHER /* Define this if you use jmemdos.c */ +#endif +#undef DONT_USE_B_MODE +#undef PROGRESS_REPORT /* optional */ + +#endif /* JPEG_CJPEG_DJPEG */ diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jconfig.cfg b/lc-continuity/mk4/modimage/jpeg-6b/jconfig.cfg new file mode 100644 index 0000000000000000000000000000000000000000..36a04fa8402f54a98ad62d1368ac584ac40e706f --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jconfig.cfg @@ -0,0 +1,44 @@ +/* jconfig.cfg --- source file edited by configure script */ +/* see jconfig.doc for explanations */ + +#undef HAVE_PROTOTYPES +#undef HAVE_UNSIGNED_CHAR +#undef HAVE_UNSIGNED_SHORT +#undef void +#undef const +#undef CHAR_IS_UNSIGNED +#undef HAVE_STDDEF_H +#undef HAVE_STDLIB_H +#undef NEED_BSD_STRINGS +#undef NEED_SYS_TYPES_H +#undef NEED_FAR_POINTERS +#undef NEED_SHORT_EXTERNAL_NAMES +/* Define this if you get warnings about undefined structures. */ +#undef INCOMPLETE_TYPES_BROKEN + +#ifdef JPEG_INTERNALS + +#undef RIGHT_SHIFT_IS_UNSIGNED +#undef INLINE +/* These are for configuring the JPEG memory manager. */ +#undef DEFAULT_MAX_MEM +#undef NO_MKTEMP + +#endif /* JPEG_INTERNALS */ + +#ifdef JPEG_CJPEG_DJPEG + +#define BMP_SUPPORTED /* BMP image file format */ +#define GIF_SUPPORTED /* GIF image file format */ +#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ +#undef RLE_SUPPORTED /* Utah RLE image file format */ +#define TARGA_SUPPORTED /* Targa image file format */ + +#undef TWO_FILE_COMMANDLINE +#undef NEED_SIGNAL_CATCHER +#undef DONT_USE_B_MODE + +/* Define this if you want percent-done progress reports from cjpeg/djpeg. */ +#undef PROGRESS_REPORT + +#endif /* JPEG_CJPEG_DJPEG */ diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jconfig.dj b/lc-continuity/mk4/modimage/jpeg-6b/jconfig.dj new file mode 100644 index 0000000000000000000000000000000000000000..f759a9dbd6b18fc97171ca66a94e085a2821cde7 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jconfig.dj @@ -0,0 +1,38 @@ +/* jconfig.dj --- jconfig.h for DJGPP (Delorie's GNU C port) on MS-DOS. */ +/* see jconfig.doc for explanations */ + +#define HAVE_PROTOTYPES +#define HAVE_UNSIGNED_CHAR +#define HAVE_UNSIGNED_SHORT +/* #define void char */ +/* #define const */ +#undef CHAR_IS_UNSIGNED +#define HAVE_STDDEF_H +#define HAVE_STDLIB_H +#undef NEED_BSD_STRINGS +#undef NEED_SYS_TYPES_H +#undef NEED_FAR_POINTERS /* DJGPP uses flat 32-bit addressing */ +#undef NEED_SHORT_EXTERNAL_NAMES +#undef INCOMPLETE_TYPES_BROKEN + +#ifdef JPEG_INTERNALS + +#undef RIGHT_SHIFT_IS_UNSIGNED + +#endif /* JPEG_INTERNALS */ + +#ifdef JPEG_CJPEG_DJPEG + +#define BMP_SUPPORTED /* BMP image file format */ +#define GIF_SUPPORTED /* GIF image file format */ +#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ +#undef RLE_SUPPORTED /* Utah RLE image file format */ +#define TARGA_SUPPORTED /* Targa image file format */ + +#undef TWO_FILE_COMMANDLINE /* optional */ +#define USE_SETMODE /* Needed to make one-file style work in DJGPP */ +#undef NEED_SIGNAL_CATCHER /* Define this if you use jmemname.c */ +#undef DONT_USE_B_MODE +#undef PROGRESS_REPORT /* optional */ + +#endif /* JPEG_CJPEG_DJPEG */ diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jconfig.doc b/lc-continuity/mk4/modimage/jpeg-6b/jconfig.doc new file mode 100644 index 0000000000000000000000000000000000000000..c18d1c064b77287209ab5d5d6b83e591b702df9f --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jconfig.doc @@ -0,0 +1,155 @@ +/* + * jconfig.doc + * + * Copyright (C) 1991-1994, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file documents the configuration options that are required to + * customize the JPEG software for a particular system. + * + * The actual configuration options for a particular installation are stored + * in jconfig.h. On many machines, jconfig.h can be generated automatically + * or copied from one of the "canned" jconfig files that we supply. But if + * you need to generate a jconfig.h file by hand, this file tells you how. + * + * DO NOT EDIT THIS FILE --- IT WON'T ACCOMPLISH ANYTHING. + * EDIT A COPY NAMED JCONFIG.H. + */ + + +/* + * These symbols indicate the properties of your machine or compiler. + * #define the symbol if yes, #undef it if no. + */ + +/* Does your compiler support function prototypes? + * (If not, you also need to use ansi2knr, see install.doc) + */ +#define HAVE_PROTOTYPES + +/* Does your compiler support the declaration "unsigned char" ? + * How about "unsigned short" ? + */ +#define HAVE_UNSIGNED_CHAR +#define HAVE_UNSIGNED_SHORT + +/* Define "void" as "char" if your compiler doesn't know about type void. + * NOTE: be sure to define void such that "void *" represents the most general + * pointer type, e.g., that returned by malloc(). + */ +/* #define void char */ + +/* Define "const" as empty if your compiler doesn't know the "const" keyword. + */ +/* #define const */ + +/* Define this if an ordinary "char" type is unsigned. + * If you're not sure, leaving it undefined will work at some cost in speed. + * If you defined HAVE_UNSIGNED_CHAR then the speed difference is minimal. + */ +#undef CHAR_IS_UNSIGNED + +/* Define this if your system has an ANSI-conforming file. + */ +#define HAVE_STDDEF_H + +/* Define this if your system has an ANSI-conforming file. + */ +#define HAVE_STDLIB_H + +/* Define this if your system does not have an ANSI/SysV , + * but does have a BSD-style . + */ +#undef NEED_BSD_STRINGS + +/* Define this if your system does not provide typedef size_t in any of the + * ANSI-standard places (stddef.h, stdlib.h, or stdio.h), but places it in + * instead. + */ +#undef NEED_SYS_TYPES_H + +/* For 80x86 machines, you need to define NEED_FAR_POINTERS, + * unless you are using a large-data memory model or 80386 flat-memory mode. + * On less brain-damaged CPUs this symbol must not be defined. + * (Defining this symbol causes large data structures to be referenced through + * "far" pointers and to be allocated with a special version of malloc.) + */ +#undef NEED_FAR_POINTERS + +/* Define this if your linker needs global names to be unique in less + * than the first 15 characters. + */ +#undef NEED_SHORT_EXTERNAL_NAMES + +/* Although a real ANSI C compiler can deal perfectly well with pointers to + * unspecified structures (see "incomplete types" in the spec), a few pre-ANSI + * and pseudo-ANSI compilers get confused. To keep one of these bozos happy, + * define INCOMPLETE_TYPES_BROKEN. This is not recommended unless you + * actually get "missing structure definition" warnings or errors while + * compiling the JPEG code. + */ +#undef INCOMPLETE_TYPES_BROKEN + + +/* + * The following options affect code selection within the JPEG library, + * but they don't need to be visible to applications using the library. + * To minimize application namespace pollution, the symbols won't be + * defined unless JPEG_INTERNALS has been defined. + */ + +#ifdef JPEG_INTERNALS + +/* Define this if your compiler implements ">>" on signed values as a logical + * (unsigned) shift; leave it undefined if ">>" is a signed (arithmetic) shift, + * which is the normal and rational definition. + */ +#undef RIGHT_SHIFT_IS_UNSIGNED + + +#endif /* JPEG_INTERNALS */ + + +/* + * The remaining options do not affect the JPEG library proper, + * but only the sample applications cjpeg/djpeg (see cjpeg.c, djpeg.c). + * Other applications can ignore these. + */ + +#ifdef JPEG_CJPEG_DJPEG + +/* These defines indicate which image (non-JPEG) file formats are allowed. */ + +#define BMP_SUPPORTED /* BMP image file format */ +#define GIF_SUPPORTED /* GIF image file format */ +#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ +#undef RLE_SUPPORTED /* Utah RLE image file format */ +#define TARGA_SUPPORTED /* Targa image file format */ + +/* Define this if you want to name both input and output files on the command + * line, rather than using stdout and optionally stdin. You MUST do this if + * your system can't cope with binary I/O to stdin/stdout. See comments at + * head of cjpeg.c or djpeg.c. + */ +#undef TWO_FILE_COMMANDLINE + +/* Define this if your system needs explicit cleanup of temporary files. + * This is crucial under MS-DOS, where the temporary "files" may be areas + * of extended memory; on most other systems it's not as important. + */ +#undef NEED_SIGNAL_CATCHER + +/* By default, we open image files with fopen(...,"rb") or fopen(...,"wb"). + * This is necessary on systems that distinguish text files from binary files, + * and is harmless on most systems that don't. If you have one of the rare + * systems that complains about the "b" spec, define this symbol. + */ +#undef DONT_USE_B_MODE + +/* Define this if you want percent-done progress reports from cjpeg/djpeg. + */ +#undef PROGRESS_REPORT + + +#endif /* JPEG_CJPEG_DJPEG */ diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jconfig.mac b/lc-continuity/mk4/modimage/jpeg-6b/jconfig.mac new file mode 100644 index 0000000000000000000000000000000000000000..0de3efe24d7d57505d88201b96de963c82803a3f --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jconfig.mac @@ -0,0 +1,43 @@ +/* jconfig.mac --- jconfig.h for CodeWarrior on Apple Macintosh */ +/* see jconfig.doc for explanations */ + +#define HAVE_PROTOTYPES +#define HAVE_UNSIGNED_CHAR +#define HAVE_UNSIGNED_SHORT +/* #define void char */ +/* #define const */ +#undef CHAR_IS_UNSIGNED +#define HAVE_STDDEF_H +#define HAVE_STDLIB_H +#undef NEED_BSD_STRINGS +#undef NEED_SYS_TYPES_H +#undef NEED_FAR_POINTERS +#undef NEED_SHORT_EXTERNAL_NAMES +#undef INCOMPLETE_TYPES_BROKEN + +#ifdef JPEG_INTERNALS + +#undef RIGHT_SHIFT_IS_UNSIGNED + +#define USE_MAC_MEMMGR /* Define this if you use jmemmac.c */ + +#define ALIGN_TYPE long /* Needed for 680x0 Macs */ + +#endif /* JPEG_INTERNALS */ + +#ifdef JPEG_CJPEG_DJPEG + +#define BMP_SUPPORTED /* BMP image file format */ +#define GIF_SUPPORTED /* GIF image file format */ +#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ +#undef RLE_SUPPORTED /* Utah RLE image file format */ +#define TARGA_SUPPORTED /* Targa image file format */ + +#define USE_CCOMMAND /* Command line reader for Macintosh */ +#define TWO_FILE_COMMANDLINE /* Binary I/O thru stdin/stdout doesn't work */ + +#undef NEED_SIGNAL_CATCHER +#undef DONT_USE_B_MODE +#undef PROGRESS_REPORT /* optional */ + +#endif /* JPEG_CJPEG_DJPEG */ diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jconfig.manx b/lc-continuity/mk4/modimage/jpeg-6b/jconfig.manx new file mode 100644 index 0000000000000000000000000000000000000000..6dd0d008ea8126e6a1ec29e9b01e97201f63b05c --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jconfig.manx @@ -0,0 +1,43 @@ +/* jconfig.manx --- jconfig.h for Amiga systems using Manx Aztec C ver 5.x. */ +/* see jconfig.doc for explanations */ + +#define HAVE_PROTOTYPES +#define HAVE_UNSIGNED_CHAR +#define HAVE_UNSIGNED_SHORT +/* #define void char */ +/* #define const */ +#undef CHAR_IS_UNSIGNED +#define HAVE_STDDEF_H +#define HAVE_STDLIB_H +#undef NEED_BSD_STRINGS +#undef NEED_SYS_TYPES_H +#undef NEED_FAR_POINTERS +#undef NEED_SHORT_EXTERNAL_NAMES +#undef INCOMPLETE_TYPES_BROKEN + +#ifdef JPEG_INTERNALS + +#undef RIGHT_SHIFT_IS_UNSIGNED + +#define TEMP_DIRECTORY "JPEGTMP:" /* recommended setting for Amiga */ + +#define SHORTxSHORT_32 /* produces better DCT code with Aztec C */ + +#endif /* JPEG_INTERNALS */ + +#ifdef JPEG_CJPEG_DJPEG + +#define BMP_SUPPORTED /* BMP image file format */ +#define GIF_SUPPORTED /* GIF image file format */ +#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ +#undef RLE_SUPPORTED /* Utah RLE image file format */ +#define TARGA_SUPPORTED /* Targa image file format */ + +#define TWO_FILE_COMMANDLINE +#define NEED_SIGNAL_CATCHER +#undef DONT_USE_B_MODE +#undef PROGRESS_REPORT /* optional */ + +#define signal_catcher _abort /* hack for Aztec C naming requirements */ + +#endif /* JPEG_CJPEG_DJPEG */ diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jconfig.mc6 b/lc-continuity/mk4/modimage/jpeg-6b/jconfig.mc6 new file mode 100644 index 0000000000000000000000000000000000000000..c55082df43544733891ca0009a5d9d57a13035c9 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jconfig.mc6 @@ -0,0 +1,52 @@ +/* jconfig.mc6 --- jconfig.h for Microsoft C on MS-DOS, version 6.00A & up. */ +/* see jconfig.doc for explanations */ + +#define HAVE_PROTOTYPES +#define HAVE_UNSIGNED_CHAR +#define HAVE_UNSIGNED_SHORT +/* #define void char */ +/* #define const */ +#undef CHAR_IS_UNSIGNED +#define HAVE_STDDEF_H +#define HAVE_STDLIB_H +#undef NEED_BSD_STRINGS +#undef NEED_SYS_TYPES_H +#define NEED_FAR_POINTERS /* for small or medium memory model */ +#undef NEED_SHORT_EXTERNAL_NAMES +#undef INCOMPLETE_TYPES_BROKEN + +#ifdef JPEG_INTERNALS + +#undef RIGHT_SHIFT_IS_UNSIGNED + +#define USE_MSDOS_MEMMGR /* Define this if you use jmemdos.c */ + +#define MAX_ALLOC_CHUNK 65520L /* Maximum request to malloc() */ + +#define USE_FMEM /* Microsoft has _fmemcpy() and _fmemset() */ + +#define NEED_FHEAPMIN /* far heap management routines are broken */ + +#define SHORTxLCONST_32 /* enable compiler-specific DCT optimization */ +/* Note: the above define is known to improve the code with Microsoft C 6.00A. + * I do not know whether it is good for later compiler versions. + * Please report any info on this point to jpeg-info@uunet.uu.net. + */ + +#endif /* JPEG_INTERNALS */ + +#ifdef JPEG_CJPEG_DJPEG + +#define BMP_SUPPORTED /* BMP image file format */ +#define GIF_SUPPORTED /* GIF image file format */ +#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ +#undef RLE_SUPPORTED /* Utah RLE image file format */ +#define TARGA_SUPPORTED /* Targa image file format */ + +#define TWO_FILE_COMMANDLINE +#define USE_SETMODE /* Microsoft has setmode() */ +#define NEED_SIGNAL_CATCHER /* Define this if you use jmemdos.c */ +#undef DONT_USE_B_MODE +#undef PROGRESS_REPORT /* optional */ + +#endif /* JPEG_CJPEG_DJPEG */ diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jconfig.sas b/lc-continuity/mk4/modimage/jpeg-6b/jconfig.sas new file mode 100644 index 0000000000000000000000000000000000000000..efdac22294fa6b84fe5e29218ffc0d645871bd35 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jconfig.sas @@ -0,0 +1,43 @@ +/* jconfig.sas --- jconfig.h for Amiga systems using SAS C 6.0 and up. */ +/* see jconfig.doc for explanations */ + +#define HAVE_PROTOTYPES +#define HAVE_UNSIGNED_CHAR +#define HAVE_UNSIGNED_SHORT +/* #define void char */ +/* #define const */ +#undef CHAR_IS_UNSIGNED +#define HAVE_STDDEF_H +#define HAVE_STDLIB_H +#undef NEED_BSD_STRINGS +#undef NEED_SYS_TYPES_H +#undef NEED_FAR_POINTERS +#undef NEED_SHORT_EXTERNAL_NAMES +#undef INCOMPLETE_TYPES_BROKEN + +#ifdef JPEG_INTERNALS + +#undef RIGHT_SHIFT_IS_UNSIGNED + +#define TEMP_DIRECTORY "JPEGTMP:" /* recommended setting for Amiga */ + +#define NO_MKTEMP /* SAS C doesn't have mktemp() */ + +#define SHORTxSHORT_32 /* produces better DCT code with SAS C */ + +#endif /* JPEG_INTERNALS */ + +#ifdef JPEG_CJPEG_DJPEG + +#define BMP_SUPPORTED /* BMP image file format */ +#define GIF_SUPPORTED /* GIF image file format */ +#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ +#undef RLE_SUPPORTED /* Utah RLE image file format */ +#define TARGA_SUPPORTED /* Targa image file format */ + +#define TWO_FILE_COMMANDLINE +#define NEED_SIGNAL_CATCHER +#undef DONT_USE_B_MODE +#undef PROGRESS_REPORT /* optional */ + +#endif /* JPEG_CJPEG_DJPEG */ diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jconfig.st b/lc-continuity/mk4/modimage/jpeg-6b/jconfig.st new file mode 100644 index 0000000000000000000000000000000000000000..4421b7a1a678ba7aa870b9ce32136c3be5fd4fb8 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jconfig.st @@ -0,0 +1,42 @@ +/* jconfig.st --- jconfig.h for Atari ST/STE/TT using Pure C or Turbo C. */ +/* see jconfig.doc for explanations */ + +#define HAVE_PROTOTYPES +#define HAVE_UNSIGNED_CHAR +#define HAVE_UNSIGNED_SHORT +/* #define void char */ +/* #define const */ +#undef CHAR_IS_UNSIGNED +#define HAVE_STDDEF_H +#define HAVE_STDLIB_H +#undef NEED_BSD_STRINGS +#undef NEED_SYS_TYPES_H +#undef NEED_FAR_POINTERS +#undef NEED_SHORT_EXTERNAL_NAMES +#define INCOMPLETE_TYPES_BROKEN /* suppress undefined-structure warnings */ + +#ifdef JPEG_INTERNALS + +#undef RIGHT_SHIFT_IS_UNSIGNED + +#define ALIGN_TYPE long /* apparently double is a weird size? */ + +#endif /* JPEG_INTERNALS */ + +#ifdef JPEG_CJPEG_DJPEG + +#define BMP_SUPPORTED /* BMP image file format */ +#define GIF_SUPPORTED /* GIF image file format */ +#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ +#undef RLE_SUPPORTED /* Utah RLE image file format */ +#define TARGA_SUPPORTED /* Targa image file format */ + +#define TWO_FILE_COMMANDLINE /* optional -- undef if you like Unix style */ +/* Note: if you undef TWO_FILE_COMMANDLINE, you may need to define + * USE_SETMODE. Some Atari compilers require it, some do not. + */ +#define NEED_SIGNAL_CATCHER /* needed if you use jmemname.c */ +#undef DONT_USE_B_MODE +#undef PROGRESS_REPORT /* optional */ + +#endif /* JPEG_CJPEG_DJPEG */ diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jconfig.vc b/lc-continuity/mk4/modimage/jpeg-6b/jconfig.vc new file mode 100644 index 0000000000000000000000000000000000000000..7e291c75bd4ce2e5586c9bcf21bd0306d36caa5f --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jconfig.vc @@ -0,0 +1,45 @@ +/* jconfig.vc --- jconfig.h for Microsoft Visual C++ on Windows 95 or NT. */ +/* see jconfig.doc for explanations */ + +#define HAVE_PROTOTYPES +#define HAVE_UNSIGNED_CHAR +#define HAVE_UNSIGNED_SHORT +/* #define void char */ +/* #define const */ +#undef CHAR_IS_UNSIGNED +#define HAVE_STDDEF_H +#define HAVE_STDLIB_H +#undef NEED_BSD_STRINGS +#undef NEED_SYS_TYPES_H +#undef NEED_FAR_POINTERS /* we presume a 32-bit flat memory model */ +#undef NEED_SHORT_EXTERNAL_NAMES +#undef INCOMPLETE_TYPES_BROKEN + +/* Define "boolean" as unsigned char, not int, per Windows custom */ +#ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */ +typedef unsigned char boolean; +#endif +#define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */ + + +#ifdef JPEG_INTERNALS + +#undef RIGHT_SHIFT_IS_UNSIGNED + +#endif /* JPEG_INTERNALS */ + +#ifdef JPEG_CJPEG_DJPEG + +#define BMP_SUPPORTED /* BMP image file format */ +#define GIF_SUPPORTED /* GIF image file format */ +#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ +#undef RLE_SUPPORTED /* Utah RLE image file format */ +#define TARGA_SUPPORTED /* Targa image file format */ + +#define TWO_FILE_COMMANDLINE /* optional */ +#define USE_SETMODE /* Microsoft has setmode() */ +#undef NEED_SIGNAL_CATCHER +#undef DONT_USE_B_MODE +#undef PROGRESS_REPORT /* optional */ + +#endif /* JPEG_CJPEG_DJPEG */ diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jconfig.vms b/lc-continuity/mk4/modimage/jpeg-6b/jconfig.vms new file mode 100644 index 0000000000000000000000000000000000000000..55a6ffba5cd830e183c9114a5b7cf87169abe3c4 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jconfig.vms @@ -0,0 +1,37 @@ +/* jconfig.vms --- jconfig.h for use on Digital VMS. */ +/* see jconfig.doc for explanations */ + +#define HAVE_PROTOTYPES +#define HAVE_UNSIGNED_CHAR +#define HAVE_UNSIGNED_SHORT +/* #define void char */ +/* #define const */ +#undef CHAR_IS_UNSIGNED +#define HAVE_STDDEF_H +#define HAVE_STDLIB_H +#undef NEED_BSD_STRINGS +#undef NEED_SYS_TYPES_H +#undef NEED_FAR_POINTERS +#undef NEED_SHORT_EXTERNAL_NAMES +#undef INCOMPLETE_TYPES_BROKEN + +#ifdef JPEG_INTERNALS + +#undef RIGHT_SHIFT_IS_UNSIGNED + +#endif /* JPEG_INTERNALS */ + +#ifdef JPEG_CJPEG_DJPEG + +#define BMP_SUPPORTED /* BMP image file format */ +#define GIF_SUPPORTED /* GIF image file format */ +#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ +#undef RLE_SUPPORTED /* Utah RLE image file format */ +#define TARGA_SUPPORTED /* Targa image file format */ + +#define TWO_FILE_COMMANDLINE /* Needed on VMS */ +#undef NEED_SIGNAL_CATCHER +#undef DONT_USE_B_MODE +#undef PROGRESS_REPORT /* optional */ + +#endif /* JPEG_CJPEG_DJPEG */ diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jconfig.wat b/lc-continuity/mk4/modimage/jpeg-6b/jconfig.wat new file mode 100644 index 0000000000000000000000000000000000000000..6cc545baeead446a9bb96476b9d4870373f1eb3f --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jconfig.wat @@ -0,0 +1,38 @@ +/* jconfig.wat --- jconfig.h for Watcom C/C++ on MS-DOS or OS/2. */ +/* see jconfig.doc for explanations */ + +#define HAVE_PROTOTYPES +#define HAVE_UNSIGNED_CHAR +#define HAVE_UNSIGNED_SHORT +/* #define void char */ +/* #define const */ +#define CHAR_IS_UNSIGNED +#define HAVE_STDDEF_H +#define HAVE_STDLIB_H +#undef NEED_BSD_STRINGS +#undef NEED_SYS_TYPES_H +#undef NEED_FAR_POINTERS /* Watcom uses flat 32-bit addressing */ +#undef NEED_SHORT_EXTERNAL_NAMES +#undef INCOMPLETE_TYPES_BROKEN + +#ifdef JPEG_INTERNALS + +#undef RIGHT_SHIFT_IS_UNSIGNED + +#endif /* JPEG_INTERNALS */ + +#ifdef JPEG_CJPEG_DJPEG + +#define BMP_SUPPORTED /* BMP image file format */ +#define GIF_SUPPORTED /* GIF image file format */ +#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ +#undef RLE_SUPPORTED /* Utah RLE image file format */ +#define TARGA_SUPPORTED /* Targa image file format */ + +#undef TWO_FILE_COMMANDLINE /* optional */ +#define USE_SETMODE /* Needed to make one-file style work in Watcom */ +#undef NEED_SIGNAL_CATCHER /* Define this if you use jmemname.c */ +#undef DONT_USE_B_MODE +#undef PROGRESS_REPORT /* optional */ + +#endif /* JPEG_CJPEG_DJPEG */ diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jcparam.c b/lc-continuity/mk4/modimage/jpeg-6b/jcparam.c new file mode 100644 index 0000000000000000000000000000000000000000..6fc48f53653315537ffd098d83c25c0d3db502b5 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jcparam.c @@ -0,0 +1,610 @@ +/* + * jcparam.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains optional default-setting code for the JPEG compressor. + * Applications do not have to use this file, but those that don't use it + * must know a lot more about the innards of the JPEG code. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* + * Quantization table setup routines + */ + +GLOBAL(void) +jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl, + const unsigned int *basic_table, + int scale_factor, boolean force_baseline) +/* Define a quantization table equal to the basic_table times + * a scale factor (given as a percentage). + * If force_baseline is TRUE, the computed quantization table entries + * are limited to 1..255 for JPEG baseline compatibility. + */ +{ + JQUANT_TBL ** qtblptr; + int i; + long temp; + + /* Safety check to ensure start_compress not called yet. */ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + if (which_tbl < 0 || which_tbl >= NUM_QUANT_TBLS) + ERREXIT1(cinfo, JERR_DQT_INDEX, which_tbl); + + qtblptr = & cinfo->quant_tbl_ptrs[which_tbl]; + + if (*qtblptr == NULL) + *qtblptr = jpeg_alloc_quant_table((j_common_ptr) cinfo); + + for (i = 0; i < DCTSIZE2; i++) { + temp = ((long) basic_table[i] * scale_factor + 50L) / 100L; + /* limit the values to the valid range */ + if (temp <= 0L) temp = 1L; + if (temp > 32767L) temp = 32767L; /* max quantizer needed for 12 bits */ + if (force_baseline && temp > 255L) + temp = 255L; /* limit to baseline range if requested */ + (*qtblptr)->quantval[i] = (UINT16) temp; + } + + /* Initialize sent_table FALSE so table will be written to JPEG file. */ + (*qtblptr)->sent_table = FALSE; +} + + +GLOBAL(void) +jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor, + boolean force_baseline) +/* Set or change the 'quality' (quantization) setting, using default tables + * and a straight percentage-scaling quality scale. In most cases it's better + * to use jpeg_set_quality (below); this entry point is provided for + * applications that insist on a linear percentage scaling. + */ +{ + /* These are the sample quantization tables given in JPEG spec section K.1. + * The spec says that the values given produce "good" quality, and + * when divided by 2, "very good" quality. + */ + static const unsigned int std_luminance_quant_tbl[DCTSIZE2] = { + 16, 11, 10, 16, 24, 40, 51, 61, + 12, 12, 14, 19, 26, 58, 60, 55, + 14, 13, 16, 24, 40, 57, 69, 56, + 14, 17, 22, 29, 51, 87, 80, 62, + 18, 22, 37, 56, 68, 109, 103, 77, + 24, 35, 55, 64, 81, 104, 113, 92, + 49, 64, 78, 87, 103, 121, 120, 101, + 72, 92, 95, 98, 112, 100, 103, 99 + }; + static const unsigned int std_chrominance_quant_tbl[DCTSIZE2] = { + 17, 18, 24, 47, 99, 99, 99, 99, + 18, 21, 26, 66, 99, 99, 99, 99, + 24, 26, 56, 99, 99, 99, 99, 99, + 47, 66, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99 + }; + + /* Set up two quantization tables using the specified scaling */ + jpeg_add_quant_table(cinfo, 0, std_luminance_quant_tbl, + scale_factor, force_baseline); + jpeg_add_quant_table(cinfo, 1, std_chrominance_quant_tbl, + scale_factor, force_baseline); +} + + +GLOBAL(int) +jpeg_quality_scaling (int quality) +/* Convert a user-specified quality rating to a percentage scaling factor + * for an underlying quantization table, using our recommended scaling curve. + * The input 'quality' factor should be 0 (terrible) to 100 (very good). + */ +{ + /* Safety limit on quality factor. Convert 0 to 1 to avoid zero divide. */ + if (quality <= 0) quality = 1; + if (quality > 100) quality = 100; + + /* The basic table is used as-is (scaling 100) for a quality of 50. + * Qualities 50..100 are converted to scaling percentage 200 - 2*Q; + * note that at Q=100 the scaling is 0, which will cause jpeg_add_quant_table + * to make all the table entries 1 (hence, minimum quantization loss). + * Qualities 1..50 are converted to scaling percentage 5000/Q. + */ + if (quality < 50) + quality = 5000 / quality; + else + quality = 200 - quality*2; + + return quality; +} + + +GLOBAL(void) +jpeg_set_quality (j_compress_ptr cinfo, int quality, boolean force_baseline) +/* Set or change the 'quality' (quantization) setting, using default tables. + * This is the standard quality-adjusting entry point for typical user + * interfaces; only those who want detailed control over quantization tables + * would use the preceding three routines directly. + */ +{ + /* Convert user 0-100 rating to percentage scaling */ + quality = jpeg_quality_scaling(quality); + + /* Set up standard quality tables */ + jpeg_set_linear_quality(cinfo, quality, force_baseline); +} + + +/* + * Huffman table setup routines + */ + +LOCAL(void) +add_huff_table (j_compress_ptr cinfo, + JHUFF_TBL **htblptr, const UINT8 *bits, const UINT8 *val) +/* Define a Huffman table */ +{ + int nsymbols, len; + + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + + /* Copy the number-of-symbols-of-each-code-length counts */ + MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits)); + + /* Validate the counts. We do this here mainly so we can copy the right + * number of symbols from the val[] array, without risking marching off + * the end of memory. jchuff.c will do a more thorough test later. + */ + nsymbols = 0; + for (len = 1; len <= 16; len++) + nsymbols += bits[len]; + if (nsymbols < 1 || nsymbols > 256) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + + MEMCOPY((*htblptr)->huffval, val, nsymbols * SIZEOF(UINT8)); + + /* Initialize sent_table FALSE so table will be written to JPEG file. */ + (*htblptr)->sent_table = FALSE; +} + + +LOCAL(void) +std_huff_tables (j_compress_ptr cinfo) +/* Set up the standard Huffman tables (cf. JPEG standard section K.3) */ +/* IMPORTANT: these are only valid for 8-bit data precision! */ +{ + static const UINT8 bits_dc_luminance[17] = + { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }; + static const UINT8 val_dc_luminance[] = + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; + + static const UINT8 bits_dc_chrominance[17] = + { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }; + static const UINT8 val_dc_chrominance[] = + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; + + static const UINT8 bits_ac_luminance[17] = + { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d }; + static const UINT8 val_ac_luminance[] = + { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, + 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, + 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, + 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, + 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, + 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, + 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, + 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, + 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, + 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, + 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, + 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, + 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, + 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, + 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, + 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, + 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, + 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa }; + + static const UINT8 bits_ac_chrominance[17] = + { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 }; + static const UINT8 val_ac_chrominance[] = + { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, + 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, + 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, + 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, + 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, + 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, + 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, + 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, + 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, + 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, + 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, + 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, + 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, + 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, + 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, + 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, + 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa }; + + add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[0], + bits_dc_luminance, val_dc_luminance); + add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[0], + bits_ac_luminance, val_ac_luminance); + add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[1], + bits_dc_chrominance, val_dc_chrominance); + add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[1], + bits_ac_chrominance, val_ac_chrominance); +} + + +/* + * Default parameter setup for compression. + * + * Applications that don't choose to use this routine must do their + * own setup of all these parameters. Alternately, you can call this + * to establish defaults and then alter parameters selectively. This + * is the recommended approach since, if we add any new parameters, + * your code will still work (they'll be set to reasonable defaults). + */ + +GLOBAL(void) +jpeg_set_defaults (j_compress_ptr cinfo) +{ + int i; + + /* Safety check to ensure start_compress not called yet. */ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + /* Allocate comp_info array large enough for maximum component count. + * Array is made permanent in case application wants to compress + * multiple images at same param settings. + */ + if (cinfo->comp_info == NULL) + cinfo->comp_info = (jpeg_component_info *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + MAX_COMPONENTS * SIZEOF(jpeg_component_info)); + + /* Initialize everything not dependent on the color space */ + + cinfo->data_precision = BITS_IN_JSAMPLE; + /* Set up two quantization tables using default quality of 75 */ + jpeg_set_quality(cinfo, 75, TRUE); + /* Set up two Huffman tables */ + std_huff_tables(cinfo); + + /* Initialize default arithmetic coding conditioning */ + for (i = 0; i < NUM_ARITH_TBLS; i++) { + cinfo->arith_dc_L[i] = 0; + cinfo->arith_dc_U[i] = 1; + cinfo->arith_ac_K[i] = 5; + } + + /* Default is no multiple-scan output */ + cinfo->scan_info = NULL; + cinfo->num_scans = 0; + + /* Expect normal source image, not raw downsampled data */ + cinfo->raw_data_in = FALSE; + + /* Use Huffman coding, not arithmetic coding, by default */ + cinfo->arith_code = FALSE; + + /* By default, don't do extra passes to optimize entropy coding */ + cinfo->optimize_coding = FALSE; + /* The standard Huffman tables are only valid for 8-bit data precision. + * If the precision is higher, force optimization on so that usable + * tables will be computed. This test can be removed if default tables + * are supplied that are valid for the desired precision. + */ + if (cinfo->data_precision > 8) + cinfo->optimize_coding = TRUE; + + /* By default, use the simpler non-cosited sampling alignment */ + cinfo->CCIR601_sampling = FALSE; + + /* No input smoothing */ + cinfo->smoothing_factor = 0; + + /* DCT algorithm preference */ + cinfo->dct_method = JDCT_DEFAULT; + + /* No restart markers */ + cinfo->restart_interval = 0; + cinfo->restart_in_rows = 0; + + /* Fill in default JFIF marker parameters. Note that whether the marker + * will actually be written is determined by jpeg_set_colorspace. + * + * By default, the library emits JFIF version code 1.01. + * An application that wants to emit JFIF 1.02 extension markers should set + * JFIF_minor_version to 2. We could probably get away with just defaulting + * to 1.02, but there may still be some decoders in use that will complain + * about that; saying 1.01 should minimize compatibility problems. + */ + cinfo->JFIF_major_version = 1; /* Default JFIF version = 1.01 */ + cinfo->JFIF_minor_version = 1; + cinfo->density_unit = 0; /* Pixel size is unknown by default */ + cinfo->X_density = 1; /* Pixel aspect ratio is square by default */ + cinfo->Y_density = 1; + + /* Choose JPEG colorspace based on input space, set defaults accordingly */ + + jpeg_default_colorspace(cinfo); +} + + +/* + * Select an appropriate JPEG colorspace for in_color_space. + */ + +GLOBAL(void) +jpeg_default_colorspace (j_compress_ptr cinfo) +{ + switch (cinfo->in_color_space) { + case JCS_GRAYSCALE: + jpeg_set_colorspace(cinfo, JCS_GRAYSCALE); + break; + case JCS_RGB: + jpeg_set_colorspace(cinfo, JCS_YCbCr); + break; + case JCS_YCbCr: + jpeg_set_colorspace(cinfo, JCS_YCbCr); + break; + case JCS_CMYK: + jpeg_set_colorspace(cinfo, JCS_CMYK); /* By default, no translation */ + break; + case JCS_YCCK: + jpeg_set_colorspace(cinfo, JCS_YCCK); + break; + case JCS_UNKNOWN: + jpeg_set_colorspace(cinfo, JCS_UNKNOWN); + break; + default: + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + } +} + + +/* + * Set the JPEG colorspace, and choose colorspace-dependent default values. + */ + +GLOBAL(void) +jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace) +{ + jpeg_component_info * compptr; + int ci; + +#define SET_COMP(index,id,hsamp,vsamp,quant,dctbl,actbl) \ + (compptr = &cinfo->comp_info[index], \ + compptr->component_id = (id), \ + compptr->h_samp_factor = (hsamp), \ + compptr->v_samp_factor = (vsamp), \ + compptr->quant_tbl_no = (quant), \ + compptr->dc_tbl_no = (dctbl), \ + compptr->ac_tbl_no = (actbl) ) + + /* Safety check to ensure start_compress not called yet. */ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + /* For all colorspaces, we use Q and Huff tables 0 for luminance components, + * tables 1 for chrominance components. + */ + + cinfo->jpeg_color_space = colorspace; + + cinfo->write_JFIF_header = FALSE; /* No marker for non-JFIF colorspaces */ + cinfo->write_Adobe_marker = FALSE; /* write no Adobe marker by default */ + + switch (colorspace) { + case JCS_GRAYSCALE: + cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */ + cinfo->num_components = 1; + /* JFIF specifies component ID 1 */ + SET_COMP(0, 1, 1,1, 0, 0,0); + break; + case JCS_RGB: + cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag RGB */ + cinfo->num_components = 3; + SET_COMP(0, 0x52 /* 'R' */, 1,1, 0, 0,0); + SET_COMP(1, 0x47 /* 'G' */, 1,1, 0, 0,0); + SET_COMP(2, 0x42 /* 'B' */, 1,1, 0, 0,0); + break; + case JCS_YCbCr: + cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */ + cinfo->num_components = 3; + /* JFIF specifies component IDs 1,2,3 */ + /* We default to 2x2 subsamples of chrominance */ + SET_COMP(0, 1, 2,2, 0, 0,0); + SET_COMP(1, 2, 1,1, 1, 1,1); + SET_COMP(2, 3, 1,1, 1, 1,1); + break; + case JCS_CMYK: + cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag CMYK */ + cinfo->num_components = 4; + SET_COMP(0, 0x43 /* 'C' */, 1,1, 0, 0,0); + SET_COMP(1, 0x4D /* 'M' */, 1,1, 0, 0,0); + SET_COMP(2, 0x59 /* 'Y' */, 1,1, 0, 0,0); + SET_COMP(3, 0x4B /* 'K' */, 1,1, 0, 0,0); + break; + case JCS_YCCK: + cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag YCCK */ + cinfo->num_components = 4; + SET_COMP(0, 1, 2,2, 0, 0,0); + SET_COMP(1, 2, 1,1, 1, 1,1); + SET_COMP(2, 3, 1,1, 1, 1,1); + SET_COMP(3, 4, 2,2, 0, 0,0); + break; + case JCS_UNKNOWN: + cinfo->num_components = cinfo->input_components; + if (cinfo->num_components < 1 || cinfo->num_components > MAX_COMPONENTS) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, + MAX_COMPONENTS); + for (ci = 0; ci < cinfo->num_components; ci++) { + SET_COMP(ci, ci, 1,1, 0, 0,0); + } + break; + default: + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + } +} + + +#ifdef C_PROGRESSIVE_SUPPORTED + +LOCAL(jpeg_scan_info *) +fill_a_scan (jpeg_scan_info * scanptr, int ci, + int Ss, int Se, int Ah, int Al) +/* Support routine: generate one scan for specified component */ +{ + scanptr->comps_in_scan = 1; + scanptr->component_index[0] = ci; + scanptr->Ss = Ss; + scanptr->Se = Se; + scanptr->Ah = Ah; + scanptr->Al = Al; + scanptr++; + return scanptr; +} + +LOCAL(jpeg_scan_info *) +fill_scans (jpeg_scan_info * scanptr, int ncomps, + int Ss, int Se, int Ah, int Al) +/* Support routine: generate one scan for each component */ +{ + int ci; + + for (ci = 0; ci < ncomps; ci++) { + scanptr->comps_in_scan = 1; + scanptr->component_index[0] = ci; + scanptr->Ss = Ss; + scanptr->Se = Se; + scanptr->Ah = Ah; + scanptr->Al = Al; + scanptr++; + } + return scanptr; +} + +LOCAL(jpeg_scan_info *) +fill_dc_scans (jpeg_scan_info * scanptr, int ncomps, int Ah, int Al) +/* Support routine: generate interleaved DC scan if possible, else N scans */ +{ + int ci; + + if (ncomps <= MAX_COMPS_IN_SCAN) { + /* Single interleaved DC scan */ + scanptr->comps_in_scan = ncomps; + for (ci = 0; ci < ncomps; ci++) + scanptr->component_index[ci] = ci; + scanptr->Ss = scanptr->Se = 0; + scanptr->Ah = Ah; + scanptr->Al = Al; + scanptr++; + } else { + /* Noninterleaved DC scan for each component */ + scanptr = fill_scans(scanptr, ncomps, 0, 0, Ah, Al); + } + return scanptr; +} + + +/* + * Create a recommended progressive-JPEG script. + * cinfo->num_components and cinfo->jpeg_color_space must be correct. + */ + +GLOBAL(void) +jpeg_simple_progression (j_compress_ptr cinfo) +{ + int ncomps = cinfo->num_components; + int nscans; + jpeg_scan_info * scanptr; + + /* Safety check to ensure start_compress not called yet. */ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + /* Figure space needed for script. Calculation must match code below! */ + if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) { + /* Custom script for YCbCr color images. */ + nscans = 10; + } else { + /* All-purpose script for other color spaces. */ + if (ncomps > MAX_COMPS_IN_SCAN) + nscans = 6 * ncomps; /* 2 DC + 4 AC scans per component */ + else + nscans = 2 + 4 * ncomps; /* 2 DC scans; 4 AC scans per component */ + } + + /* Allocate space for script. + * We need to put it in the permanent pool in case the application performs + * multiple compressions without changing the settings. To avoid a memory + * leak if jpeg_simple_progression is called repeatedly for the same JPEG + * object, we try to re-use previously allocated space, and we allocate + * enough space to handle YCbCr even if initially asked for grayscale. + */ + if (cinfo->script_space == NULL || cinfo->script_space_size < nscans) { + cinfo->script_space_size = MAX(nscans, 10); + cinfo->script_space = (jpeg_scan_info *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + cinfo->script_space_size * SIZEOF(jpeg_scan_info)); + } + scanptr = cinfo->script_space; + cinfo->scan_info = scanptr; + cinfo->num_scans = nscans; + + if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) { + /* Custom script for YCbCr color images. */ + /* Initial DC scan */ + scanptr = fill_dc_scans(scanptr, ncomps, 0, 1); + /* Initial AC scan: get some luma data out in a hurry */ + scanptr = fill_a_scan(scanptr, 0, 1, 5, 0, 2); + /* Chroma data is too small to be worth expending many scans on */ + scanptr = fill_a_scan(scanptr, 2, 1, 63, 0, 1); + scanptr = fill_a_scan(scanptr, 1, 1, 63, 0, 1); + /* Complete spectral selection for luma AC */ + scanptr = fill_a_scan(scanptr, 0, 6, 63, 0, 2); + /* Refine next bit of luma AC */ + scanptr = fill_a_scan(scanptr, 0, 1, 63, 2, 1); + /* Finish DC successive approximation */ + scanptr = fill_dc_scans(scanptr, ncomps, 1, 0); + /* Finish AC successive approximation */ + scanptr = fill_a_scan(scanptr, 2, 1, 63, 1, 0); + scanptr = fill_a_scan(scanptr, 1, 1, 63, 1, 0); + /* Luma bottom bit comes last since it's usually largest scan */ + scanptr = fill_a_scan(scanptr, 0, 1, 63, 1, 0); + } else { + /* All-purpose script for other color spaces. */ + /* Successive approximation first pass */ + scanptr = fill_dc_scans(scanptr, ncomps, 0, 1); + scanptr = fill_scans(scanptr, ncomps, 1, 5, 0, 2); + scanptr = fill_scans(scanptr, ncomps, 6, 63, 0, 2); + /* Successive approximation second pass */ + scanptr = fill_scans(scanptr, ncomps, 1, 63, 2, 1); + /* Successive approximation final pass */ + scanptr = fill_dc_scans(scanptr, ncomps, 1, 0); + scanptr = fill_scans(scanptr, ncomps, 1, 63, 1, 0); + } +} + +#endif /* C_PROGRESSIVE_SUPPORTED */ diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jcphuff.c b/lc-continuity/mk4/modimage/jpeg-6b/jcphuff.c new file mode 100644 index 0000000000000000000000000000000000000000..07f9178b01c885820889cf377c0e73d444f5dd1b --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jcphuff.c @@ -0,0 +1,833 @@ +/* + * jcphuff.c + * + * Copyright (C) 1995-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains Huffman entropy encoding routines for progressive JPEG. + * + * We do not support output suspension in this module, since the library + * currently does not allow multiple-scan files to be written with output + * suspension. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jchuff.h" /* Declarations shared with jchuff.c */ + +#ifdef C_PROGRESSIVE_SUPPORTED + +/* Expanded entropy encoder object for progressive Huffman encoding. */ + +typedef struct { + struct jpeg_entropy_encoder pub; /* public fields */ + + /* Mode flag: TRUE for optimization, FALSE for actual data output */ + boolean gather_statistics; + + /* Bit-level coding status. + * next_output_byte/free_in_buffer are local copies of cinfo->dest fields. + */ + JOCTET * next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + INT32 put_buffer; /* current bit-accumulation buffer */ + int put_bits; /* # of bits now in it */ + j_compress_ptr cinfo; /* link to cinfo (needed for dump_buffer) */ + + /* Coding status for DC components */ + int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ + + /* Coding status for AC components */ + int ac_tbl_no; /* the table number of the single component */ + unsigned int EOBRUN; /* run length of EOBs */ + unsigned int BE; /* # of buffered correction bits before MCU */ + char * bit_buffer; /* buffer for correction bits (1 per char) */ + /* packing correction bits tightly would save some space but cost time... */ + + unsigned int restarts_to_go; /* MCUs left in this restart interval */ + int next_restart_num; /* next restart number to write (0-7) */ + + /* Pointers to derived tables (these workspaces have image lifespan). + * Since any one scan codes only DC or only AC, we only need one set + * of tables, not one for DC and one for AC. + */ + c_derived_tbl * derived_tbls[NUM_HUFF_TBLS]; + + /* Statistics tables for optimization; again, one set is enough */ + long * count_ptrs[NUM_HUFF_TBLS]; +} phuff_entropy_encoder; + +typedef phuff_entropy_encoder * phuff_entropy_ptr; + +/* MAX_CORR_BITS is the number of bits the AC refinement correction-bit + * buffer can hold. Larger sizes may slightly improve compression, but + * 1000 is already well into the realm of overkill. + * The minimum safe size is 64 bits. + */ + +#define MAX_CORR_BITS 1000 /* Max # of correction bits I can buffer */ + +/* IRIGHT_SHIFT is like RIGHT_SHIFT, but works on int rather than INT32. + * We assume that int right shift is unsigned if INT32 right shift is, + * which should be safe. + */ + +#ifdef RIGHT_SHIFT_IS_UNSIGNED +#define ISHIFT_TEMPS int ishift_temp; +#define IRIGHT_SHIFT(x,shft) \ + ((ishift_temp = (x)) < 0 ? \ + (ishift_temp >> (shft)) | ((~0) << (16-(shft))) : \ + (ishift_temp >> (shft))) +#else +#define ISHIFT_TEMPS +#define IRIGHT_SHIFT(x,shft) ((x) >> (shft)) +#endif + +/* Forward declarations */ +METHODDEF(boolean) encode_mcu_DC_first JPP((j_compress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(boolean) encode_mcu_AC_first JPP((j_compress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(boolean) encode_mcu_DC_refine JPP((j_compress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(boolean) encode_mcu_AC_refine JPP((j_compress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(void) finish_pass_phuff JPP((j_compress_ptr cinfo)); +METHODDEF(void) finish_pass_gather_phuff JPP((j_compress_ptr cinfo)); + + +/* + * Initialize for a Huffman-compressed scan using progressive JPEG. + */ + +METHODDEF(void) +start_pass_phuff (j_compress_ptr cinfo, boolean gather_statistics) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + boolean is_DC_band; + int ci, tbl; + jpeg_component_info * compptr; + + entropy->cinfo = cinfo; + entropy->gather_statistics = gather_statistics; + + is_DC_band = (cinfo->Ss == 0); + + /* We assume jcmaster.c already validated the scan parameters. */ + + /* Select execution routines */ + if (cinfo->Ah == 0) { + if (is_DC_band) + entropy->pub.encode_mcu = encode_mcu_DC_first; + else + entropy->pub.encode_mcu = encode_mcu_AC_first; + } else { + if (is_DC_band) + entropy->pub.encode_mcu = encode_mcu_DC_refine; + else { + entropy->pub.encode_mcu = encode_mcu_AC_refine; + /* AC refinement needs a correction bit buffer */ + if (entropy->bit_buffer == NULL) + entropy->bit_buffer = (char *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + MAX_CORR_BITS * SIZEOF(char)); + } + } + if (gather_statistics) + entropy->pub.finish_pass = finish_pass_gather_phuff; + else + entropy->pub.finish_pass = finish_pass_phuff; + + /* Only DC coefficients may be interleaved, so cinfo->comps_in_scan = 1 + * for AC coefficients. + */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* Initialize DC predictions to 0 */ + entropy->last_dc_val[ci] = 0; + /* Get table index */ + if (is_DC_band) { + if (cinfo->Ah != 0) /* DC refinement needs no table */ + continue; + tbl = compptr->dc_tbl_no; + } else { + entropy->ac_tbl_no = tbl = compptr->ac_tbl_no; + } + if (gather_statistics) { + /* Check for invalid table index */ + /* (make_c_derived_tbl does this in the other path) */ + if (tbl < 0 || tbl >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tbl); + /* Allocate and zero the statistics tables */ + /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */ + if (entropy->count_ptrs[tbl] == NULL) + entropy->count_ptrs[tbl] = (long *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + 257 * SIZEOF(long)); + MEMZERO(entropy->count_ptrs[tbl], 257 * SIZEOF(long)); + } else { + /* Compute derived values for Huffman table */ + /* We may do this more than once for a table, but it's not expensive */ + jpeg_make_c_derived_tbl(cinfo, is_DC_band, tbl, + & entropy->derived_tbls[tbl]); + } + } + + /* Initialize AC stuff */ + entropy->EOBRUN = 0; + entropy->BE = 0; + + /* Initialize bit buffer to empty */ + entropy->put_buffer = 0; + entropy->put_bits = 0; + + /* Initialize restart stuff */ + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num = 0; +} + + +/* Outputting bytes to the file. + * NB: these must be called only when actually outputting, + * that is, entropy->gather_statistics == FALSE. + */ + +/* Emit a byte */ +#define emit_byte(entropy,val) \ + { *(entropy)->next_output_byte++ = (JOCTET) (val); \ + if (--(entropy)->free_in_buffer == 0) \ + dump_buffer(entropy); } + + +LOCAL(void) +dump_buffer (phuff_entropy_ptr entropy) +/* Empty the output buffer; we do not support suspension in this module. */ +{ + struct jpeg_destination_mgr * dest = entropy->cinfo->dest; + + if (! (*dest->empty_output_buffer) (entropy->cinfo)) + ERREXIT(entropy->cinfo, JERR_CANT_SUSPEND); + /* After a successful buffer dump, must reset buffer pointers */ + entropy->next_output_byte = dest->next_output_byte; + entropy->free_in_buffer = dest->free_in_buffer; +} + + +/* Outputting bits to the file */ + +/* Only the right 24 bits of put_buffer are used; the valid bits are + * left-justified in this part. At most 16 bits can be passed to emit_bits + * in one call, and we never retain more than 7 bits in put_buffer + * between calls, so 24 bits are sufficient. + */ + +INLINE +LOCAL(void) +emit_bits (phuff_entropy_ptr entropy, unsigned int code, int size) +/* Emit some bits, unless we are in gather mode */ +{ + /* This routine is heavily used, so it's worth coding tightly. */ + register INT32 put_buffer = (INT32) code; + register int put_bits = entropy->put_bits; + + /* if size is 0, caller used an invalid Huffman table entry */ + if (size == 0) + ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE); + + if (entropy->gather_statistics) + return; /* do nothing if we're only getting stats */ + + put_buffer &= (((INT32) 1)<put_buffer; /* and merge with old buffer contents */ + + while (put_bits >= 8) { + int c = (int) ((put_buffer >> 16) & 0xFF); + + emit_byte(entropy, c); + if (c == 0xFF) { /* need to stuff a zero byte? */ + emit_byte(entropy, 0); + } + put_buffer <<= 8; + put_bits -= 8; + } + + entropy->put_buffer = put_buffer; /* update variables */ + entropy->put_bits = put_bits; +} + + +LOCAL(void) +flush_bits (phuff_entropy_ptr entropy) +{ + emit_bits(entropy, 0x7F, 7); /* fill any partial byte with ones */ + entropy->put_buffer = 0; /* and reset bit-buffer to empty */ + entropy->put_bits = 0; +} + + +/* + * Emit (or just count) a Huffman symbol. + */ + +INLINE +LOCAL(void) +emit_symbol (phuff_entropy_ptr entropy, int tbl_no, int symbol) +{ + if (entropy->gather_statistics) + entropy->count_ptrs[tbl_no][symbol]++; + else { + c_derived_tbl * tbl = entropy->derived_tbls[tbl_no]; + emit_bits(entropy, tbl->ehufco[symbol], tbl->ehufsi[symbol]); + } +} + + +/* + * Emit bits from a correction bit buffer. + */ + +LOCAL(void) +emit_buffered_bits (phuff_entropy_ptr entropy, char * bufstart, + unsigned int nbits) +{ + if (entropy->gather_statistics) + return; /* no real work */ + + while (nbits > 0) { + emit_bits(entropy, (unsigned int) (*bufstart), 1); + bufstart++; + nbits--; + } +} + + +/* + * Emit any pending EOBRUN symbol. + */ + +LOCAL(void) +emit_eobrun (phuff_entropy_ptr entropy) +{ + register int temp, nbits; + + if (entropy->EOBRUN > 0) { /* if there is any pending EOBRUN */ + temp = entropy->EOBRUN; + nbits = 0; + while ((temp >>= 1)) + nbits++; + /* safety check: shouldn't happen given limited correction-bit buffer */ + if (nbits > 14) + ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE); + + emit_symbol(entropy, entropy->ac_tbl_no, nbits << 4); + if (nbits) + emit_bits(entropy, entropy->EOBRUN, nbits); + + entropy->EOBRUN = 0; + + /* Emit any buffered correction bits */ + emit_buffered_bits(entropy, entropy->bit_buffer, entropy->BE); + entropy->BE = 0; + } +} + + +/* + * Emit a restart marker & resynchronize predictions. + */ + +LOCAL(void) +emit_restart (phuff_entropy_ptr entropy, int restart_num) +{ + int ci; + + emit_eobrun(entropy); + + if (! entropy->gather_statistics) { + flush_bits(entropy); + emit_byte(entropy, 0xFF); + emit_byte(entropy, JPEG_RST0 + restart_num); + } + + if (entropy->cinfo->Ss == 0) { + /* Re-initialize DC predictions to 0 */ + for (ci = 0; ci < entropy->cinfo->comps_in_scan; ci++) + entropy->last_dc_val[ci] = 0; + } else { + /* Re-initialize all AC-related fields to 0 */ + entropy->EOBRUN = 0; + entropy->BE = 0; + } +} + + +/* + * MCU encoding for DC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + register int temp, temp2; + register int nbits; + int blkn, ci; + int Al = cinfo->Al; + JBLOCKROW block; + jpeg_component_info * compptr; + ISHIFT_TEMPS + + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) + if (entropy->restarts_to_go == 0) + emit_restart(entropy, entropy->next_restart_num); + + /* Encode the MCU data blocks */ + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + block = MCU_data[blkn]; + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + + /* Compute the DC value after the required point transform by Al. + * This is simply an arithmetic right shift. + */ + temp2 = IRIGHT_SHIFT((int) ((*block)[0]), Al); + + /* DC differences are figured on the point-transformed values. */ + temp = temp2 - entropy->last_dc_val[ci]; + entropy->last_dc_val[ci] = temp2; + + /* Encode the DC coefficient difference per section G.1.2.1 */ + temp2 = temp; + if (temp < 0) { + temp = -temp; /* temp is abs value of input */ + /* For a negative input, want temp2 = bitwise complement of abs(input) */ + /* This code assumes we are on a two's complement machine */ + temp2--; + } + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 0; + while (temp) { + nbits++; + temp >>= 1; + } + /* Check for out-of-range coefficient values. + * Since we're encoding a difference, the range limit is twice as much. + */ + if (nbits > MAX_COEF_BITS+1) + ERREXIT(cinfo, JERR_BAD_DCT_COEF); + + /* Count/emit the Huffman-coded symbol for the number of bits */ + emit_symbol(entropy, compptr->dc_tbl_no, nbits); + + /* Emit that number of bits of the value, if positive, */ + /* or the complement of its magnitude, if negative. */ + if (nbits) /* emit_bits rejects calls with size 0 */ + emit_bits(entropy, (unsigned int) temp2, nbits); + } + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* + * MCU encoding for AC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + register int temp, temp2; + register int nbits; + register int r, k; + int Se = cinfo->Se; + int Al = cinfo->Al; + JBLOCKROW block; + + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) + if (entropy->restarts_to_go == 0) + emit_restart(entropy, entropy->next_restart_num); + + /* Encode the MCU data block */ + block = MCU_data[0]; + + /* Encode the AC coefficients per section G.1.2.2, fig. G.3 */ + + r = 0; /* r = run length of zeros */ + + for (k = cinfo->Ss; k <= Se; k++) { + if ((temp = (*block)[jpeg_natural_order[k]]) == 0) { + r++; + continue; + } + /* We must apply the point transform by Al. For AC coefficients this + * is an integer division with rounding towards 0. To do this portably + * in C, we shift after obtaining the absolute value; so the code is + * interwoven with finding the abs value (temp) and output bits (temp2). + */ + if (temp < 0) { + temp = -temp; /* temp is abs value of input */ + temp >>= Al; /* apply the point transform */ + /* For a negative coef, want temp2 = bitwise complement of abs(coef) */ + temp2 = ~temp; + } else { + temp >>= Al; /* apply the point transform */ + temp2 = temp; + } + /* Watch out for case that nonzero coef is zero after point transform */ + if (temp == 0) { + r++; + continue; + } + + /* Emit any pending EOBRUN */ + if (entropy->EOBRUN > 0) + emit_eobrun(entropy); + /* if run length > 15, must emit special run-length-16 codes (0xF0) */ + while (r > 15) { + emit_symbol(entropy, entropy->ac_tbl_no, 0xF0); + r -= 16; + } + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 1; /* there must be at least one 1 bit */ + while ((temp >>= 1)) + nbits++; + /* Check for out-of-range coefficient values */ + if (nbits > MAX_COEF_BITS) + ERREXIT(cinfo, JERR_BAD_DCT_COEF); + + /* Count/emit Huffman symbol for run length / number of bits */ + emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + nbits); + + /* Emit that number of bits of the value, if positive, */ + /* or the complement of its magnitude, if negative. */ + emit_bits(entropy, (unsigned int) temp2, nbits); + + r = 0; /* reset zero run length */ + } + + if (r > 0) { /* If there are trailing zeroes, */ + entropy->EOBRUN++; /* count an EOB */ + if (entropy->EOBRUN == 0x7FFF) + emit_eobrun(entropy); /* force it out to avoid overflow */ + } + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* + * MCU encoding for DC successive approximation refinement scan. + * Note: we assume such scans can be multi-component, although the spec + * is not very clear on the point. + */ + +METHODDEF(boolean) +encode_mcu_DC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + register int temp; + int blkn; + int Al = cinfo->Al; + JBLOCKROW block; + + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) + if (entropy->restarts_to_go == 0) + emit_restart(entropy, entropy->next_restart_num); + + /* Encode the MCU data blocks */ + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + block = MCU_data[blkn]; + + /* We simply emit the Al'th bit of the DC coefficient value. */ + temp = (*block)[0]; + emit_bits(entropy, (unsigned int) (temp >> Al), 1); + } + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* + * MCU encoding for AC successive approximation refinement scan. + */ + +METHODDEF(boolean) +encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + register int temp; + register int r, k; + int EOB; + char *BR_buffer; + unsigned int BR; + int Se = cinfo->Se; + int Al = cinfo->Al; + JBLOCKROW block; + int absvalues[DCTSIZE2]; + + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) + if (entropy->restarts_to_go == 0) + emit_restart(entropy, entropy->next_restart_num); + + /* Encode the MCU data block */ + block = MCU_data[0]; + + /* It is convenient to make a pre-pass to determine the transformed + * coefficients' absolute values and the EOB position. + */ + EOB = 0; + for (k = cinfo->Ss; k <= Se; k++) { + temp = (*block)[jpeg_natural_order[k]]; + /* We must apply the point transform by Al. For AC coefficients this + * is an integer division with rounding towards 0. To do this portably + * in C, we shift after obtaining the absolute value. + */ + if (temp < 0) + temp = -temp; /* temp is abs value of input */ + temp >>= Al; /* apply the point transform */ + absvalues[k] = temp; /* save abs value for main pass */ + if (temp == 1) + EOB = k; /* EOB = index of last newly-nonzero coef */ + } + + /* Encode the AC coefficients per section G.1.2.3, fig. G.7 */ + + r = 0; /* r = run length of zeros */ + BR = 0; /* BR = count of buffered bits added now */ + BR_buffer = entropy->bit_buffer + entropy->BE; /* Append bits to buffer */ + + for (k = cinfo->Ss; k <= Se; k++) { + if ((temp = absvalues[k]) == 0) { + r++; + continue; + } + + /* Emit any required ZRLs, but not if they can be folded into EOB */ + while (r > 15 && k <= EOB) { + /* emit any pending EOBRUN and the BE correction bits */ + emit_eobrun(entropy); + /* Emit ZRL */ + emit_symbol(entropy, entropy->ac_tbl_no, 0xF0); + r -= 16; + /* Emit buffered correction bits that must be associated with ZRL */ + emit_buffered_bits(entropy, BR_buffer, BR); + BR_buffer = entropy->bit_buffer; /* BE bits are gone now */ + BR = 0; + } + + /* If the coef was previously nonzero, it only needs a correction bit. + * NOTE: a straight translation of the spec's figure G.7 would suggest + * that we also need to test r > 15. But if r > 15, we can only get here + * if k > EOB, which implies that this coefficient is not 1. + */ + if (temp > 1) { + /* The correction bit is the next bit of the absolute value. */ + BR_buffer[BR++] = (char) (temp & 1); + continue; + } + + /* Emit any pending EOBRUN and the BE correction bits */ + emit_eobrun(entropy); + + /* Count/emit Huffman symbol for run length / number of bits */ + emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + 1); + + /* Emit output bit for newly-nonzero coef */ + temp = ((*block)[jpeg_natural_order[k]] < 0) ? 0 : 1; + emit_bits(entropy, (unsigned int) temp, 1); + + /* Emit buffered correction bits that must be associated with this code */ + emit_buffered_bits(entropy, BR_buffer, BR); + BR_buffer = entropy->bit_buffer; /* BE bits are gone now */ + BR = 0; + r = 0; /* reset zero run length */ + } + + if (r > 0 || BR > 0) { /* If there are trailing zeroes, */ + entropy->EOBRUN++; /* count an EOB */ + entropy->BE += BR; /* concat my correction bits to older ones */ + /* We force out the EOB if we risk either: + * 1. overflow of the EOB counter; + * 2. overflow of the correction bit buffer during the next MCU. + */ + if (entropy->EOBRUN == 0x7FFF || entropy->BE > (MAX_CORR_BITS-DCTSIZE2+1)) + emit_eobrun(entropy); + } + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* + * Finish up at the end of a Huffman-compressed progressive scan. + */ + +METHODDEF(void) +finish_pass_phuff (j_compress_ptr cinfo) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Flush out any buffered data */ + emit_eobrun(entropy); + flush_bits(entropy); + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; +} + + +/* + * Finish up a statistics-gathering pass and create the new Huffman tables. + */ + +METHODDEF(void) +finish_pass_gather_phuff (j_compress_ptr cinfo) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + boolean is_DC_band; + int ci, tbl; + jpeg_component_info * compptr; + JHUFF_TBL **htblptr; + boolean did[NUM_HUFF_TBLS]; + + /* Flush out buffered data (all we care about is counting the EOB symbol) */ + emit_eobrun(entropy); + + is_DC_band = (cinfo->Ss == 0); + + /* It's important not to apply jpeg_gen_optimal_table more than once + * per table, because it clobbers the input frequency counts! + */ + MEMZERO(did, SIZEOF(did)); + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + if (is_DC_band) { + if (cinfo->Ah != 0) /* DC refinement needs no table */ + continue; + tbl = compptr->dc_tbl_no; + } else { + tbl = compptr->ac_tbl_no; + } + if (! did[tbl]) { + if (is_DC_band) + htblptr = & cinfo->dc_huff_tbl_ptrs[tbl]; + else + htblptr = & cinfo->ac_huff_tbl_ptrs[tbl]; + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + jpeg_gen_optimal_table(cinfo, *htblptr, entropy->count_ptrs[tbl]); + did[tbl] = TRUE; + } + } +} + + +/* + * Module initialization routine for progressive Huffman entropy encoding. + */ + +GLOBAL(void) +jinit_phuff_encoder (j_compress_ptr cinfo) +{ + phuff_entropy_ptr entropy; + int i; + + entropy = (phuff_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(phuff_entropy_encoder)); + cinfo->entropy = (struct jpeg_entropy_encoder *) entropy; + entropy->pub.start_pass = start_pass_phuff; + + /* Mark tables unallocated */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + entropy->derived_tbls[i] = NULL; + entropy->count_ptrs[i] = NULL; + } + entropy->bit_buffer = NULL; /* needed only in AC refinement scan */ +} + +#endif /* C_PROGRESSIVE_SUPPORTED */ diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jcprepct.c b/lc-continuity/mk4/modimage/jpeg-6b/jcprepct.c new file mode 100644 index 0000000000000000000000000000000000000000..fa93333db20f74cbcc3b660523b7dc26688d06ef --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jcprepct.c @@ -0,0 +1,354 @@ +/* + * jcprepct.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the compression preprocessing controller. + * This controller manages the color conversion, downsampling, + * and edge expansion steps. + * + * Most of the complexity here is associated with buffering input rows + * as required by the downsampler. See the comments at the head of + * jcsample.c for the downsampler's needs. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* At present, jcsample.c can request context rows only for smoothing. + * In the future, we might also need context rows for CCIR601 sampling + * or other more-complex downsampling procedures. The code to support + * context rows should be compiled only if needed. + */ +#ifdef INPUT_SMOOTHING_SUPPORTED +#define CONTEXT_ROWS_SUPPORTED +#endif + + +/* + * For the simple (no-context-row) case, we just need to buffer one + * row group's worth of pixels for the downsampling step. At the bottom of + * the image, we pad to a full row group by replicating the last pixel row. + * The downsampler's last output row is then replicated if needed to pad + * out to a full iMCU row. + * + * When providing context rows, we must buffer three row groups' worth of + * pixels. Three row groups are physically allocated, but the row pointer + * arrays are made five row groups high, with the extra pointers above and + * below "wrapping around" to point to the last and first real row groups. + * This allows the downsampler to access the proper context rows. + * At the top and bottom of the image, we create dummy context rows by + * copying the first or last real pixel row. This copying could be avoided + * by pointer hacking as is done in jdmainct.c, but it doesn't seem worth the + * trouble on the compression side. + */ + + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_c_prep_controller pub; /* public fields */ + + /* Downsampling input buffer. This buffer holds color-converted data + * until we have enough to do a downsample step. + */ + JSAMPARRAY color_buf[MAX_COMPONENTS]; + + JDIMENSION rows_to_go; /* counts rows remaining in source image */ + int next_buf_row; /* index of next row to store in color_buf */ + +#ifdef CONTEXT_ROWS_SUPPORTED /* only needed for context case */ + int this_row_group; /* starting row index of group to process */ + int next_buf_stop; /* downsample when we reach this index */ +#endif +} my_prep_controller; + +typedef my_prep_controller * my_prep_ptr; + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_prep (j_compress_ptr cinfo, J_BUF_MODE pass_mode) +{ + my_prep_ptr prep = (my_prep_ptr) cinfo->prep; + + if (pass_mode != JBUF_PASS_THRU) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + + /* Initialize total-height counter for detecting bottom of image */ + prep->rows_to_go = cinfo->image_height; + /* Mark the conversion buffer empty */ + prep->next_buf_row = 0; +#ifdef CONTEXT_ROWS_SUPPORTED + /* Preset additional state variables for context mode. + * These aren't used in non-context mode, so we needn't test which mode. + */ + prep->this_row_group = 0; + /* Set next_buf_stop to stop after two row groups have been read in. */ + prep->next_buf_stop = 2 * cinfo->max_v_samp_factor; +#endif +} + + +/* + * Expand an image vertically from height input_rows to height output_rows, + * by duplicating the bottom row. + */ + +LOCAL(void) +expand_bottom_edge (JSAMPARRAY image_data, JDIMENSION num_cols, + int input_rows, int output_rows) +{ + register int row; + + for (row = input_rows; row < output_rows; row++) { + jcopy_sample_rows(image_data, input_rows-1, image_data, row, + 1, num_cols); + } +} + + +/* + * Process some data in the simple no-context case. + * + * Preprocessor output data is counted in "row groups". A row group + * is defined to be v_samp_factor sample rows of each component. + * Downsampling will produce this much data from each max_v_samp_factor + * input rows. + */ + +METHODDEF(void) +pre_process_data (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail, + JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, + JDIMENSION out_row_groups_avail) +{ + my_prep_ptr prep = (my_prep_ptr) cinfo->prep; + int numrows, ci; + JDIMENSION inrows; + jpeg_component_info * compptr; + + while (*in_row_ctr < in_rows_avail && + *out_row_group_ctr < out_row_groups_avail) { + /* Do color conversion to fill the conversion buffer. */ + inrows = in_rows_avail - *in_row_ctr; + numrows = cinfo->max_v_samp_factor - prep->next_buf_row; + numrows = (int) MIN((JDIMENSION) numrows, inrows); + (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr, + prep->color_buf, + (JDIMENSION) prep->next_buf_row, + numrows); + *in_row_ctr += numrows; + prep->next_buf_row += numrows; + prep->rows_to_go -= numrows; + /* If at bottom of image, pad to fill the conversion buffer. */ + if (prep->rows_to_go == 0 && + prep->next_buf_row < cinfo->max_v_samp_factor) { + for (ci = 0; ci < cinfo->num_components; ci++) { + expand_bottom_edge(prep->color_buf[ci], cinfo->image_width, + prep->next_buf_row, cinfo->max_v_samp_factor); + } + prep->next_buf_row = cinfo->max_v_samp_factor; + } + /* If we've filled the conversion buffer, empty it. */ + if (prep->next_buf_row == cinfo->max_v_samp_factor) { + (*cinfo->downsample->downsample) (cinfo, + prep->color_buf, (JDIMENSION) 0, + output_buf, *out_row_group_ctr); + prep->next_buf_row = 0; + (*out_row_group_ctr)++; + } + /* If at bottom of image, pad the output to a full iMCU height. + * Note we assume the caller is providing a one-iMCU-height output buffer! + */ + if (prep->rows_to_go == 0 && + *out_row_group_ctr < out_row_groups_avail) { + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + expand_bottom_edge(output_buf[ci], + compptr->width_in_blocks * DCTSIZE, + (int) (*out_row_group_ctr * compptr->v_samp_factor), + (int) (out_row_groups_avail * compptr->v_samp_factor)); + } + *out_row_group_ctr = out_row_groups_avail; + break; /* can exit outer loop without test */ + } + } +} + + +#ifdef CONTEXT_ROWS_SUPPORTED + +/* + * Process some data in the context case. + */ + +METHODDEF(void) +pre_process_context (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail, + JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, + JDIMENSION out_row_groups_avail) +{ + my_prep_ptr prep = (my_prep_ptr) cinfo->prep; + int numrows, ci; + int buf_height = cinfo->max_v_samp_factor * 3; + JDIMENSION inrows; + + while (*out_row_group_ctr < out_row_groups_avail) { + if (*in_row_ctr < in_rows_avail) { + /* Do color conversion to fill the conversion buffer. */ + inrows = in_rows_avail - *in_row_ctr; + numrows = prep->next_buf_stop - prep->next_buf_row; + numrows = (int) MIN((JDIMENSION) numrows, inrows); + (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr, + prep->color_buf, + (JDIMENSION) prep->next_buf_row, + numrows); + /* Pad at top of image, if first time through */ + if (prep->rows_to_go == cinfo->image_height) { + for (ci = 0; ci < cinfo->num_components; ci++) { + int row; + for (row = 1; row <= cinfo->max_v_samp_factor; row++) { + jcopy_sample_rows(prep->color_buf[ci], 0, + prep->color_buf[ci], -row, + 1, cinfo->image_width); + } + } + } + *in_row_ctr += numrows; + prep->next_buf_row += numrows; + prep->rows_to_go -= numrows; + } else { + /* Return for more data, unless we are at the bottom of the image. */ + if (prep->rows_to_go != 0) + break; + /* When at bottom of image, pad to fill the conversion buffer. */ + if (prep->next_buf_row < prep->next_buf_stop) { + for (ci = 0; ci < cinfo->num_components; ci++) { + expand_bottom_edge(prep->color_buf[ci], cinfo->image_width, + prep->next_buf_row, prep->next_buf_stop); + } + prep->next_buf_row = prep->next_buf_stop; + } + } + /* If we've gotten enough data, downsample a row group. */ + if (prep->next_buf_row == prep->next_buf_stop) { + (*cinfo->downsample->downsample) (cinfo, + prep->color_buf, + (JDIMENSION) prep->this_row_group, + output_buf, *out_row_group_ctr); + (*out_row_group_ctr)++; + /* Advance pointers with wraparound as necessary. */ + prep->this_row_group += cinfo->max_v_samp_factor; + if (prep->this_row_group >= buf_height) + prep->this_row_group = 0; + if (prep->next_buf_row >= buf_height) + prep->next_buf_row = 0; + prep->next_buf_stop = prep->next_buf_row + cinfo->max_v_samp_factor; + } + } +} + + +/* + * Create the wrapped-around downsampling input buffer needed for context mode. + */ + +LOCAL(void) +create_context_buffer (j_compress_ptr cinfo) +{ + my_prep_ptr prep = (my_prep_ptr) cinfo->prep; + int rgroup_height = cinfo->max_v_samp_factor; + int ci, i; + jpeg_component_info * compptr; + JSAMPARRAY true_buffer, fake_buffer; + + /* Grab enough space for fake row pointers for all the components; + * we need five row groups' worth of pointers for each component. + */ + fake_buffer = (JSAMPARRAY) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (cinfo->num_components * 5 * rgroup_height) * + SIZEOF(JSAMPROW)); + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Allocate the actual buffer space (3 row groups) for this component. + * We make the buffer wide enough to allow the downsampler to edge-expand + * horizontally within the buffer, if it so chooses. + */ + true_buffer = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE * + cinfo->max_h_samp_factor) / compptr->h_samp_factor), + (JDIMENSION) (3 * rgroup_height)); + /* Copy true buffer row pointers into the middle of the fake row array */ + MEMCOPY(fake_buffer + rgroup_height, true_buffer, + 3 * rgroup_height * SIZEOF(JSAMPROW)); + /* Fill in the above and below wraparound pointers */ + for (i = 0; i < rgroup_height; i++) { + fake_buffer[i] = true_buffer[2 * rgroup_height + i]; + fake_buffer[4 * rgroup_height + i] = true_buffer[i]; + } + prep->color_buf[ci] = fake_buffer + rgroup_height; + fake_buffer += 5 * rgroup_height; /* point to space for next component */ + } +} + +#endif /* CONTEXT_ROWS_SUPPORTED */ + + +/* + * Initialize preprocessing controller. + */ + +GLOBAL(void) +jinit_c_prep_controller (j_compress_ptr cinfo, boolean need_full_buffer) +{ + my_prep_ptr prep; + int ci; + jpeg_component_info * compptr; + + if (need_full_buffer) /* safety check */ + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + + prep = (my_prep_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_prep_controller)); + cinfo->prep = (struct jpeg_c_prep_controller *) prep; + prep->pub.start_pass = start_pass_prep; + + /* Allocate the color conversion buffer. + * We make the buffer wide enough to allow the downsampler to edge-expand + * horizontally within the buffer, if it so chooses. + */ + if (cinfo->downsample->need_context_rows) { + /* Set up to provide context rows */ +#ifdef CONTEXT_ROWS_SUPPORTED + prep->pub.pre_process_data = pre_process_context; + create_context_buffer(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + /* No context, just make it tall enough for one row group */ + prep->pub.pre_process_data = pre_process_data; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + prep->color_buf[ci] = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE * + cinfo->max_h_samp_factor) / compptr->h_samp_factor), + (JDIMENSION) cinfo->max_v_samp_factor); + } + } +} diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jcsample.c b/lc-continuity/mk4/modimage/jpeg-6b/jcsample.c new file mode 100644 index 0000000000000000000000000000000000000000..212ec8757c4ca865eba34a80530d42e8d371dec7 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jcsample.c @@ -0,0 +1,519 @@ +/* + * jcsample.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains downsampling routines. + * + * Downsampling input data is counted in "row groups". A row group + * is defined to be max_v_samp_factor pixel rows of each component, + * from which the downsampler produces v_samp_factor sample rows. + * A single row group is processed in each call to the downsampler module. + * + * The downsampler is responsible for edge-expansion of its output data + * to fill an integral number of DCT blocks horizontally. The source buffer + * may be modified if it is helpful for this purpose (the source buffer is + * allocated wide enough to correspond to the desired output width). + * The caller (the prep controller) is responsible for vertical padding. + * + * The downsampler may request "context rows" by setting need_context_rows + * during startup. In this case, the input arrays will contain at least + * one row group's worth of pixels above and below the passed-in data; + * the caller will create dummy rows at image top and bottom by replicating + * the first or last real pixel row. + * + * An excellent reference for image resampling is + * Digital Image Warping, George Wolberg, 1990. + * Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7. + * + * The downsampling algorithm used here is a simple average of the source + * pixels covered by the output pixel. The hi-falutin sampling literature + * refers to this as a "box filter". In general the characteristics of a box + * filter are not very good, but for the specific cases we normally use (1:1 + * and 2:1 ratios) the box is equivalent to a "triangle filter" which is not + * nearly so bad. If you intend to use other sampling ratios, you'd be well + * advised to improve this code. + * + * A simple input-smoothing capability is provided. This is mainly intended + * for cleaning up color-dithered GIF input files (if you find it inadequate, + * we suggest using an external filtering program such as pnmconvol). When + * enabled, each input pixel P is replaced by a weighted sum of itself and its + * eight neighbors. P's weight is 1-8*SF and each neighbor's weight is SF, + * where SF = (smoothing_factor / 1024). + * Currently, smoothing is only supported for 2h2v sampling factors. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Pointer to routine to downsample a single component */ +typedef JMETHOD(void, downsample1_ptr, + (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data)); + +/* Private subobject */ + +typedef struct { + struct jpeg_downsampler pub; /* public fields */ + + /* Downsampling method pointers, one per component */ + downsample1_ptr methods[MAX_COMPONENTS]; +} my_downsampler; + +typedef my_downsampler * my_downsample_ptr; + + +/* + * Initialize for a downsampling pass. + */ + +METHODDEF(void) +start_pass_downsample (j_compress_ptr cinfo) +{ + /* no work for now */ +} + + +/* + * Expand a component horizontally from width input_cols to width output_cols, + * by duplicating the rightmost samples. + */ + +LOCAL(void) +expand_right_edge (JSAMPARRAY image_data, int num_rows, + JDIMENSION input_cols, JDIMENSION output_cols) +{ + register JSAMPROW ptr; + register JSAMPLE pixval; + register int count; + int row; + int numcols = (int) (output_cols - input_cols); + + if (numcols > 0) { + for (row = 0; row < num_rows; row++) { + ptr = image_data[row] + input_cols; + pixval = ptr[-1]; /* don't need GETJSAMPLE() here */ + for (count = numcols; count > 0; count--) + *ptr++ = pixval; + } + } +} + + +/* + * Do downsampling for a whole row group (all components). + * + * In this version we simply downsample each component independently. + */ + +METHODDEF(void) +sep_downsample (j_compress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION in_row_index, + JSAMPIMAGE output_buf, JDIMENSION out_row_group_index) +{ + my_downsample_ptr downsample = (my_downsample_ptr) cinfo->downsample; + int ci; + jpeg_component_info * compptr; + JSAMPARRAY in_ptr, out_ptr; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + in_ptr = input_buf[ci] + in_row_index; + out_ptr = output_buf[ci] + (out_row_group_index * compptr->v_samp_factor); + (*downsample->methods[ci]) (cinfo, compptr, in_ptr, out_ptr); + } +} + + +/* + * Downsample pixel values of a single component. + * One row group is processed per call. + * This version handles arbitrary integral sampling ratios, without smoothing. + * Note that this version is not actually used for customary sampling ratios. + */ + +METHODDEF(void) +int_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v; + JDIMENSION outcol, outcol_h; /* outcol_h == outcol*h_expand */ + JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; + JSAMPROW inptr, outptr; + INT32 outvalue; + + h_expand = cinfo->max_h_samp_factor / compptr->h_samp_factor; + v_expand = cinfo->max_v_samp_factor / compptr->v_samp_factor; + numpix = h_expand * v_expand; + numpix2 = numpix/2; + + /* Expand input data enough to let all the output samples be generated + * by the standard loop. Special-casing padded output would be more + * efficient. + */ + expand_right_edge(input_data, cinfo->max_v_samp_factor, + cinfo->image_width, output_cols * h_expand); + + inrow = 0; + for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { + outptr = output_data[outrow]; + for (outcol = 0, outcol_h = 0; outcol < output_cols; + outcol++, outcol_h += h_expand) { + outvalue = 0; + for (v = 0; v < v_expand; v++) { + inptr = input_data[inrow+v] + outcol_h; + for (h = 0; h < h_expand; h++) { + outvalue += (INT32) GETJSAMPLE(*inptr++); + } + } + *outptr++ = (JSAMPLE) ((outvalue + numpix2) / numpix); + } + inrow += v_expand; + } +} + + +/* + * Downsample pixel values of a single component. + * This version handles the special case of a full-size component, + * without smoothing. + */ + +METHODDEF(void) +fullsize_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + /* Copy the data */ + jcopy_sample_rows(input_data, 0, output_data, 0, + cinfo->max_v_samp_factor, cinfo->image_width); + /* Edge-expand */ + expand_right_edge(output_data, cinfo->max_v_samp_factor, + cinfo->image_width, compptr->width_in_blocks * DCTSIZE); +} + + +/* + * Downsample pixel values of a single component. + * This version handles the common case of 2:1 horizontal and 1:1 vertical, + * without smoothing. + * + * A note about the "bias" calculations: when rounding fractional values to + * integer, we do not want to always round 0.5 up to the next integer. + * If we did that, we'd introduce a noticeable bias towards larger values. + * Instead, this code is arranged so that 0.5 will be rounded up or down at + * alternate pixel locations (a simple ordered dither pattern). + */ + +METHODDEF(void) +h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + int outrow; + JDIMENSION outcol; + JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; + register JSAMPROW inptr, outptr; + register int bias; + + /* Expand input data enough to let all the output samples be generated + * by the standard loop. Special-casing padded output would be more + * efficient. + */ + expand_right_edge(input_data, cinfo->max_v_samp_factor, + cinfo->image_width, output_cols * 2); + + for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { + outptr = output_data[outrow]; + inptr = input_data[outrow]; + bias = 0; /* bias = 0,1,0,1,... for successive samples */ + for (outcol = 0; outcol < output_cols; outcol++) { + *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr) + GETJSAMPLE(inptr[1]) + + bias) >> 1); + bias ^= 1; /* 0=>1, 1=>0 */ + inptr += 2; + } + } +} + + +/* + * Downsample pixel values of a single component. + * This version handles the standard case of 2:1 horizontal and 2:1 vertical, + * without smoothing. + */ + +METHODDEF(void) +h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + int inrow, outrow; + JDIMENSION outcol; + JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; + register JSAMPROW inptr0, inptr1, outptr; + register int bias; + + /* Expand input data enough to let all the output samples be generated + * by the standard loop. Special-casing padded output would be more + * efficient. + */ + expand_right_edge(input_data, cinfo->max_v_samp_factor, + cinfo->image_width, output_cols * 2); + + inrow = 0; + for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { + outptr = output_data[outrow]; + inptr0 = input_data[inrow]; + inptr1 = input_data[inrow+1]; + bias = 1; /* bias = 1,2,1,2,... for successive samples */ + for (outcol = 0; outcol < output_cols; outcol++) { + *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]) + + bias) >> 2); + bias ^= 3; /* 1=>2, 2=>1 */ + inptr0 += 2; inptr1 += 2; + } + inrow += 2; + } +} + + +#ifdef INPUT_SMOOTHING_SUPPORTED + +/* + * Downsample pixel values of a single component. + * This version handles the standard case of 2:1 horizontal and 2:1 vertical, + * with smoothing. One row of context is required. + */ + +METHODDEF(void) +h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + int inrow, outrow; + JDIMENSION colctr; + JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; + register JSAMPROW inptr0, inptr1, above_ptr, below_ptr, outptr; + INT32 membersum, neighsum, memberscale, neighscale; + + /* Expand input data enough to let all the output samples be generated + * by the standard loop. Special-casing padded output would be more + * efficient. + */ + expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2, + cinfo->image_width, output_cols * 2); + + /* We don't bother to form the individual "smoothed" input pixel values; + * we can directly compute the output which is the average of the four + * smoothed values. Each of the four member pixels contributes a fraction + * (1-8*SF) to its own smoothed image and a fraction SF to each of the three + * other smoothed pixels, therefore a total fraction (1-5*SF)/4 to the final + * output. The four corner-adjacent neighbor pixels contribute a fraction + * SF to just one smoothed pixel, or SF/4 to the final output; while the + * eight edge-adjacent neighbors contribute SF to each of two smoothed + * pixels, or SF/2 overall. In order to use integer arithmetic, these + * factors are scaled by 2^16 = 65536. + * Also recall that SF = smoothing_factor / 1024. + */ + + memberscale = 16384 - cinfo->smoothing_factor * 80; /* scaled (1-5*SF)/4 */ + neighscale = cinfo->smoothing_factor * 16; /* scaled SF/4 */ + + inrow = 0; + for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { + outptr = output_data[outrow]; + inptr0 = input_data[inrow]; + inptr1 = input_data[inrow+1]; + above_ptr = input_data[inrow-1]; + below_ptr = input_data[inrow+2]; + + /* Special case for first column: pretend column -1 is same as column 0 */ + membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); + neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + + GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[2]) + + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[2]); + neighsum += neighsum; + neighsum += GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[2]) + + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[2]); + membersum = membersum * memberscale + neighsum * neighscale; + *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); + inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2; + + for (colctr = output_cols - 2; colctr > 0; colctr--) { + /* sum of pixels directly mapped to this output element */ + membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); + /* sum of edge-neighbor pixels */ + neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + + GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[2]) + + GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[2]); + /* The edge-neighbors count twice as much as corner-neighbors */ + neighsum += neighsum; + /* Add in the corner-neighbors */ + neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[2]) + + GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[2]); + /* form final output scaled up by 2^16 */ + membersum = membersum * memberscale + neighsum * neighscale; + /* round, descale and output it */ + *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); + inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2; + } + + /* Special case for last column */ + membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); + neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + + GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[1]) + + GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[1]); + neighsum += neighsum; + neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[1]) + + GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[1]); + membersum = membersum * memberscale + neighsum * neighscale; + *outptr = (JSAMPLE) ((membersum + 32768) >> 16); + + inrow += 2; + } +} + + +/* + * Downsample pixel values of a single component. + * This version handles the special case of a full-size component, + * with smoothing. One row of context is required. + */ + +METHODDEF(void) +fullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + int outrow; + JDIMENSION colctr; + JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; + register JSAMPROW inptr, above_ptr, below_ptr, outptr; + INT32 membersum, neighsum, memberscale, neighscale; + int colsum, lastcolsum, nextcolsum; + + /* Expand input data enough to let all the output samples be generated + * by the standard loop. Special-casing padded output would be more + * efficient. + */ + expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2, + cinfo->image_width, output_cols); + + /* Each of the eight neighbor pixels contributes a fraction SF to the + * smoothed pixel, while the main pixel contributes (1-8*SF). In order + * to use integer arithmetic, these factors are multiplied by 2^16 = 65536. + * Also recall that SF = smoothing_factor / 1024. + */ + + memberscale = 65536L - cinfo->smoothing_factor * 512L; /* scaled 1-8*SF */ + neighscale = cinfo->smoothing_factor * 64; /* scaled SF */ + + for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { + outptr = output_data[outrow]; + inptr = input_data[outrow]; + above_ptr = input_data[outrow-1]; + below_ptr = input_data[outrow+1]; + + /* Special case for first column */ + colsum = GETJSAMPLE(*above_ptr++) + GETJSAMPLE(*below_ptr++) + + GETJSAMPLE(*inptr); + membersum = GETJSAMPLE(*inptr++); + nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) + + GETJSAMPLE(*inptr); + neighsum = colsum + (colsum - membersum) + nextcolsum; + membersum = membersum * memberscale + neighsum * neighscale; + *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); + lastcolsum = colsum; colsum = nextcolsum; + + for (colctr = output_cols - 2; colctr > 0; colctr--) { + membersum = GETJSAMPLE(*inptr++); + above_ptr++; below_ptr++; + nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) + + GETJSAMPLE(*inptr); + neighsum = lastcolsum + (colsum - membersum) + nextcolsum; + membersum = membersum * memberscale + neighsum * neighscale; + *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); + lastcolsum = colsum; colsum = nextcolsum; + } + + /* Special case for last column */ + membersum = GETJSAMPLE(*inptr); + neighsum = lastcolsum + (colsum - membersum) + colsum; + membersum = membersum * memberscale + neighsum * neighscale; + *outptr = (JSAMPLE) ((membersum + 32768) >> 16); + + } +} + +#endif /* INPUT_SMOOTHING_SUPPORTED */ + + +/* + * Module initialization routine for downsampling. + * Note that we must select a routine for each component. + */ + +GLOBAL(void) +jinit_downsampler (j_compress_ptr cinfo) +{ + my_downsample_ptr downsample; + int ci; + jpeg_component_info * compptr; + boolean smoothok = TRUE; + + downsample = (my_downsample_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_downsampler)); + cinfo->downsample = (struct jpeg_downsampler *) downsample; + downsample->pub.start_pass = start_pass_downsample; + downsample->pub.downsample = sep_downsample; + downsample->pub.need_context_rows = FALSE; + + if (cinfo->CCIR601_sampling) + ERREXIT(cinfo, JERR_CCIR601_NOTIMPL); + + /* Verify we can handle the sampling factors, and set up method pointers */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + if (compptr->h_samp_factor == cinfo->max_h_samp_factor && + compptr->v_samp_factor == cinfo->max_v_samp_factor) { +#ifdef INPUT_SMOOTHING_SUPPORTED + if (cinfo->smoothing_factor) { + downsample->methods[ci] = fullsize_smooth_downsample; + downsample->pub.need_context_rows = TRUE; + } else +#endif + downsample->methods[ci] = fullsize_downsample; + } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor && + compptr->v_samp_factor == cinfo->max_v_samp_factor) { + smoothok = FALSE; + downsample->methods[ci] = h2v1_downsample; + } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor && + compptr->v_samp_factor * 2 == cinfo->max_v_samp_factor) { +#ifdef INPUT_SMOOTHING_SUPPORTED + if (cinfo->smoothing_factor) { + downsample->methods[ci] = h2v2_smooth_downsample; + downsample->pub.need_context_rows = TRUE; + } else +#endif + downsample->methods[ci] = h2v2_downsample; + } else if ((cinfo->max_h_samp_factor % compptr->h_samp_factor) == 0 && + (cinfo->max_v_samp_factor % compptr->v_samp_factor) == 0) { + smoothok = FALSE; + downsample->methods[ci] = int_downsample; + } else + ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL); + } + +#ifdef INPUT_SMOOTHING_SUPPORTED + if (cinfo->smoothing_factor && !smoothok) + TRACEMS(cinfo, 0, JTRC_SMOOTH_NOTIMPL); +#endif +} diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jctrans.c b/lc-continuity/mk4/modimage/jpeg-6b/jctrans.c new file mode 100644 index 0000000000000000000000000000000000000000..0e6d70769df543d84cd5a2bec154443648e5c61a --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jctrans.c @@ -0,0 +1,388 @@ +/* + * jctrans.c + * + * Copyright (C) 1995-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains library routines for transcoding compression, + * that is, writing raw DCT coefficient arrays to an output JPEG file. + * The routines in jcapimin.c will also be needed by a transcoder. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Forward declarations */ +LOCAL(void) transencode_master_selection + JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)); +LOCAL(void) transencode_coef_controller + JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)); + + +/* + * Compression initialization for writing raw-coefficient data. + * Before calling this, all parameters and a data destination must be set up. + * Call jpeg_finish_compress() to actually write the data. + * + * The number of passed virtual arrays must match cinfo->num_components. + * Note that the virtual arrays need not be filled or even realized at + * the time write_coefficients is called; indeed, if the virtual arrays + * were requested from this compression object's memory manager, they + * typically will be realized during this routine and filled afterwards. + */ + +GLOBAL(void) +jpeg_write_coefficients (j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays) +{ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + /* Mark all tables to be written */ + jpeg_suppress_tables(cinfo, FALSE); + /* (Re)initialize error mgr and destination modules */ + (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); + (*cinfo->dest->init_destination) (cinfo); + /* Perform master selection of active modules */ + transencode_master_selection(cinfo, coef_arrays); + /* Wait for jpeg_finish_compress() call */ + cinfo->next_scanline = 0; /* so jpeg_write_marker works */ + cinfo->global_state = CSTATE_WRCOEFS; +} + + +/* + * Initialize the compression object with default parameters, + * then copy from the source object all parameters needed for lossless + * transcoding. Parameters that can be varied without loss (such as + * scan script and Huffman optimization) are left in their default states. + */ + +GLOBAL(void) +jpeg_copy_critical_parameters (j_decompress_ptr srcinfo, + j_compress_ptr dstinfo) +{ + JQUANT_TBL ** qtblptr; + jpeg_component_info *incomp, *outcomp; + JQUANT_TBL *c_quant, *slot_quant; + int tblno, ci, coefi; + + /* Safety check to ensure start_compress not called yet. */ + if (dstinfo->global_state != CSTATE_START) + ERREXIT1(dstinfo, JERR_BAD_STATE, dstinfo->global_state); + /* Copy fundamental image dimensions */ + dstinfo->image_width = srcinfo->image_width; + dstinfo->image_height = srcinfo->image_height; + dstinfo->input_components = srcinfo->num_components; + dstinfo->in_color_space = srcinfo->jpeg_color_space; + /* Initialize all parameters to default values */ + jpeg_set_defaults(dstinfo); + /* jpeg_set_defaults may choose wrong colorspace, eg YCbCr if input is RGB. + * Fix it to get the right header markers for the image colorspace. + */ + jpeg_set_colorspace(dstinfo, srcinfo->jpeg_color_space); + dstinfo->data_precision = srcinfo->data_precision; + dstinfo->CCIR601_sampling = srcinfo->CCIR601_sampling; + /* Copy the source's quantization tables. */ + for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) { + if (srcinfo->quant_tbl_ptrs[tblno] != NULL) { + qtblptr = & dstinfo->quant_tbl_ptrs[tblno]; + if (*qtblptr == NULL) + *qtblptr = jpeg_alloc_quant_table((j_common_ptr) dstinfo); + MEMCOPY((*qtblptr)->quantval, + srcinfo->quant_tbl_ptrs[tblno]->quantval, + SIZEOF((*qtblptr)->quantval)); + (*qtblptr)->sent_table = FALSE; + } + } + /* Copy the source's per-component info. + * Note we assume jpeg_set_defaults has allocated the dest comp_info array. + */ + dstinfo->num_components = srcinfo->num_components; + if (dstinfo->num_components < 1 || dstinfo->num_components > MAX_COMPONENTS) + ERREXIT2(dstinfo, JERR_COMPONENT_COUNT, dstinfo->num_components, + MAX_COMPONENTS); + for (ci = 0, incomp = srcinfo->comp_info, outcomp = dstinfo->comp_info; + ci < dstinfo->num_components; ci++, incomp++, outcomp++) { + outcomp->component_id = incomp->component_id; + outcomp->h_samp_factor = incomp->h_samp_factor; + outcomp->v_samp_factor = incomp->v_samp_factor; + outcomp->quant_tbl_no = incomp->quant_tbl_no; + /* Make sure saved quantization table for component matches the qtable + * slot. If not, the input file re-used this qtable slot. + * IJG encoder currently cannot duplicate this. + */ + tblno = outcomp->quant_tbl_no; + if (tblno < 0 || tblno >= NUM_QUANT_TBLS || + srcinfo->quant_tbl_ptrs[tblno] == NULL) + ERREXIT1(dstinfo, JERR_NO_QUANT_TABLE, tblno); + slot_quant = srcinfo->quant_tbl_ptrs[tblno]; + c_quant = incomp->quant_table; + if (c_quant != NULL) { + for (coefi = 0; coefi < DCTSIZE2; coefi++) { + if (c_quant->quantval[coefi] != slot_quant->quantval[coefi]) + ERREXIT1(dstinfo, JERR_MISMATCHED_QUANT_TABLE, tblno); + } + } + /* Note: we do not copy the source's Huffman table assignments; + * instead we rely on jpeg_set_colorspace to have made a suitable choice. + */ + } + /* Also copy JFIF version and resolution information, if available. + * Strictly speaking this isn't "critical" info, but it's nearly + * always appropriate to copy it if available. In particular, + * if the application chooses to copy JFIF 1.02 extension markers from + * the source file, we need to copy the version to make sure we don't + * emit a file that has 1.02 extensions but a claimed version of 1.01. + * We will *not*, however, copy version info from mislabeled "2.01" files. + */ + if (srcinfo->saw_JFIF_marker) { + if (srcinfo->JFIF_major_version == 1) { + dstinfo->JFIF_major_version = srcinfo->JFIF_major_version; + dstinfo->JFIF_minor_version = srcinfo->JFIF_minor_version; + } + dstinfo->density_unit = srcinfo->density_unit; + dstinfo->X_density = srcinfo->X_density; + dstinfo->Y_density = srcinfo->Y_density; + } +} + + +/* + * Master selection of compression modules for transcoding. + * This substitutes for jcinit.c's initialization of the full compressor. + */ + +LOCAL(void) +transencode_master_selection (j_compress_ptr cinfo, + jvirt_barray_ptr * coef_arrays) +{ + /* Although we don't actually use input_components for transcoding, + * jcmaster.c's initial_setup will complain if input_components is 0. + */ + cinfo->input_components = 1; + /* Initialize master control (includes parameter checking/processing) */ + jinit_c_master_control(cinfo, TRUE /* transcode only */); + + /* Entropy encoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) { + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); + } else { + if (cinfo->progressive_mode) { +#ifdef C_PROGRESSIVE_SUPPORTED + jinit_phuff_encoder(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else + jinit_huff_encoder(cinfo); + } + + /* We need a special coefficient buffer controller. */ + transencode_coef_controller(cinfo, coef_arrays); + + jinit_marker_writer(cinfo); + + /* We can now tell the memory manager to allocate virtual arrays. */ + (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); + + /* Write the datastream header (SOI, JFIF) immediately. + * Frame and scan headers are postponed till later. + * This lets application insert special markers after the SOI. + */ + (*cinfo->marker->write_file_header) (cinfo); +} + + +/* + * The rest of this file is a special implementation of the coefficient + * buffer controller. This is similar to jccoefct.c, but it handles only + * output from presupplied virtual arrays. Furthermore, we generate any + * dummy padding blocks on-the-fly rather than expecting them to be present + * in the arrays. + */ + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_c_coef_controller pub; /* public fields */ + + JDIMENSION iMCU_row_num; /* iMCU row # within image */ + JDIMENSION mcu_ctr; /* counts MCUs processed in current row */ + int MCU_vert_offset; /* counts MCU rows within iMCU row */ + int MCU_rows_per_iMCU_row; /* number of such rows needed */ + + /* Virtual block array for each component. */ + jvirt_barray_ptr * whole_image; + + /* Workspace for constructing dummy blocks at right/bottom edges. */ + JBLOCKROW dummy_buffer[C_MAX_BLOCKS_IN_MCU]; +} my_coef_controller; + +typedef my_coef_controller * my_coef_ptr; + + +LOCAL(void) +start_iMCU_row (j_compress_ptr cinfo) +/* Reset within-iMCU-row counters for a new row */ +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + + /* In an interleaved scan, an MCU row is the same as an iMCU row. + * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. + * But at the bottom of the image, process only what's left. + */ + if (cinfo->comps_in_scan > 1) { + coef->MCU_rows_per_iMCU_row = 1; + } else { + if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1)) + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; + else + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; + } + + coef->mcu_ctr = 0; + coef->MCU_vert_offset = 0; +} + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + + if (pass_mode != JBUF_CRANK_DEST) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + + coef->iMCU_row_num = 0; + start_iMCU_row(cinfo); +} + + +/* + * Process some data. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor block rows for each component in the scan. + * The data is obtained from the virtual arrays and fed to the entropy coder. + * Returns TRUE if the iMCU row is completed, FALSE if suspended. + * + * NB: input_buf is ignored; it is likely to be a NULL pointer. + */ + +METHODDEF(boolean) +compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + int blkn, ci, xindex, yindex, yoffset, blockcnt; + JDIMENSION start_col; + JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; + JBLOCKROW MCU_buffer[C_MAX_BLOCKS_IN_MCU]; + JBLOCKROW buffer_ptr; + jpeg_component_info *compptr; + + /* Align the virtual buffers for the components used in this scan. */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + buffer[ci] = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], + coef->iMCU_row_num * compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, FALSE); + } + + /* Loop to process one whole iMCU row */ + for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; + yoffset++) { + for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row; + MCU_col_num++) { + /* Construct list of pointers to DCT blocks belonging to this MCU */ + blkn = 0; /* index of current DCT block within MCU */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + start_col = MCU_col_num * compptr->MCU_width; + blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width + : compptr->last_col_width; + for (yindex = 0; yindex < compptr->MCU_height; yindex++) { + if (coef->iMCU_row_num < last_iMCU_row || + yindex+yoffset < compptr->last_row_height) { + /* Fill in pointers to real blocks in this row */ + buffer_ptr = buffer[ci][yindex+yoffset] + start_col; + for (xindex = 0; xindex < blockcnt; xindex++) + MCU_buffer[blkn++] = buffer_ptr++; + } else { + /* At bottom of image, need a whole row of dummy blocks */ + xindex = 0; + } + /* Fill in any dummy blocks needed in this row. + * Dummy blocks are filled in the same way as in jccoefct.c: + * all zeroes in the AC entries, DC entries equal to previous + * block's DC value. The init routine has already zeroed the + * AC entries, so we need only set the DC entries correctly. + */ + for (; xindex < compptr->MCU_width; xindex++) { + MCU_buffer[blkn] = coef->dummy_buffer[blkn]; + MCU_buffer[blkn][0][0] = MCU_buffer[blkn-1][0][0]; + blkn++; + } + } + } + /* Try to write the MCU. */ + if (! (*cinfo->entropy->encode_mcu) (cinfo, MCU_buffer)) { + /* Suspension forced; update state counters and exit */ + coef->MCU_vert_offset = yoffset; + coef->mcu_ctr = MCU_col_num; + return FALSE; + } + } + /* Completed an MCU row, but perhaps not an iMCU row */ + coef->mcu_ctr = 0; + } + /* Completed the iMCU row, advance counters for next one */ + coef->iMCU_row_num++; + start_iMCU_row(cinfo); + return TRUE; +} + + +/* + * Initialize coefficient buffer controller. + * + * Each passed coefficient array must be the right size for that + * coefficient: width_in_blocks wide and height_in_blocks high, + * with unitheight at least v_samp_factor. + */ + +LOCAL(void) +transencode_coef_controller (j_compress_ptr cinfo, + jvirt_barray_ptr * coef_arrays) +{ + my_coef_ptr coef; + JBLOCKROW buffer; + int i; + + coef = (my_coef_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_coef_controller)); + cinfo->coef = (struct jpeg_c_coef_controller *) coef; + coef->pub.start_pass = start_pass_coef; + coef->pub.compress_data = compress_output; + + /* Save pointer to virtual arrays */ + coef->whole_image = coef_arrays; + + /* Allocate and pre-zero space for dummy DCT blocks. */ + buffer = (JBLOCKROW) + (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, + C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); + jzero_far((void FAR *) buffer, C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); + for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) { + coef->dummy_buffer[i] = buffer + i; + } +} diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jdapimin.c b/lc-continuity/mk4/modimage/jpeg-6b/jdapimin.c new file mode 100644 index 0000000000000000000000000000000000000000..cadb59fce3aa1cc239e86c592774cc500e109613 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jdapimin.c @@ -0,0 +1,395 @@ +/* + * jdapimin.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains application interface code for the decompression half + * of the JPEG library. These are the "minimum" API routines that may be + * needed in either the normal full-decompression case or the + * transcoding-only case. + * + * Most of the routines intended to be called directly by an application + * are in this file or in jdapistd.c. But also see jcomapi.c for routines + * shared by compression and decompression, and jdtrans.c for the transcoding + * case. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* + * Initialization of a JPEG decompression object. + * The error manager must already be set up (in case memory manager fails). + */ + +GLOBAL(void) +jpeg_CreateDecompress (j_decompress_ptr cinfo, int version, size_t structsize) +{ + int i; + + /* Guard against version mismatches between library and caller. */ + cinfo->mem = NULL; /* so jpeg_destroy knows mem mgr not called */ + if (version != JPEG_LIB_VERSION) + ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version); + if (structsize != SIZEOF(struct jpeg_decompress_struct)) + ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE, + (int) SIZEOF(struct jpeg_decompress_struct), (int) structsize); + + /* For debugging purposes, we zero the whole master structure. + * But the application has already set the err pointer, and may have set + * client_data, so we have to save and restore those fields. + * Note: if application hasn't set client_data, tools like Purify may + * complain here. + */ + { + struct jpeg_error_mgr * err = cinfo->err; + void * client_data = cinfo->client_data; /* ignore Purify complaint here */ + MEMZERO(cinfo, SIZEOF(struct jpeg_decompress_struct)); + cinfo->err = err; + cinfo->client_data = client_data; + } + cinfo->is_decompressor = TRUE; + + /* Initialize a memory manager instance for this object */ + jinit_memory_mgr((j_common_ptr) cinfo); + + /* Zero out pointers to permanent structures. */ + cinfo->progress = NULL; + cinfo->src = NULL; + + for (i = 0; i < NUM_QUANT_TBLS; i++) + cinfo->quant_tbl_ptrs[i] = NULL; + + for (i = 0; i < NUM_HUFF_TBLS; i++) { + cinfo->dc_huff_tbl_ptrs[i] = NULL; + cinfo->ac_huff_tbl_ptrs[i] = NULL; + } + + /* Initialize marker processor so application can override methods + * for COM, APPn markers before calling jpeg_read_header. + */ + cinfo->marker_list = NULL; + jinit_marker_reader(cinfo); + + /* And initialize the overall input controller. */ + jinit_input_controller(cinfo); + + /* OK, I'm ready */ + cinfo->global_state = DSTATE_START; +} + + +/* + * Destruction of a JPEG decompression object + */ + +GLOBAL(void) +jpeg_destroy_decompress (j_decompress_ptr cinfo) +{ + jpeg_destroy((j_common_ptr) cinfo); /* use common routine */ +} + + +/* + * Abort processing of a JPEG decompression operation, + * but don't destroy the object itself. + */ + +GLOBAL(void) +jpeg_abort_decompress (j_decompress_ptr cinfo) +{ + jpeg_abort((j_common_ptr) cinfo); /* use common routine */ +} + + +/* + * Set default decompression parameters. + */ + +LOCAL(void) +default_decompress_parms (j_decompress_ptr cinfo) +{ + /* Guess the input colorspace, and set output colorspace accordingly. */ + /* (Wish JPEG committee had provided a real way to specify this...) */ + /* Note application may override our guesses. */ + switch (cinfo->num_components) { + case 1: + cinfo->jpeg_color_space = JCS_GRAYSCALE; + cinfo->out_color_space = JCS_GRAYSCALE; + break; + + case 3: + if (cinfo->saw_JFIF_marker) { + cinfo->jpeg_color_space = JCS_YCbCr; /* JFIF implies YCbCr */ + } else if (cinfo->saw_Adobe_marker) { + switch (cinfo->Adobe_transform) { + case 0: + cinfo->jpeg_color_space = JCS_RGB; + break; + case 1: + cinfo->jpeg_color_space = JCS_YCbCr; + break; + default: + WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform); + cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ + break; + } + } else { + /* Saw no special markers, try to guess from the component IDs */ + int cid0 = cinfo->comp_info[0].component_id; + int cid1 = cinfo->comp_info[1].component_id; + int cid2 = cinfo->comp_info[2].component_id; + + if (cid0 == 1 && cid1 == 2 && cid2 == 3) + cinfo->jpeg_color_space = JCS_YCbCr; /* assume JFIF w/out marker */ + else if (cid0 == 82 && cid1 == 71 && cid2 == 66) + cinfo->jpeg_color_space = JCS_RGB; /* ASCII 'R', 'G', 'B' */ + else { + TRACEMS3(cinfo, 1, JTRC_UNKNOWN_IDS, cid0, cid1, cid2); + cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ + } + } + /* Always guess RGB is proper output colorspace. */ + cinfo->out_color_space = JCS_RGB; + break; + + case 4: + if (cinfo->saw_Adobe_marker) { + switch (cinfo->Adobe_transform) { + case 0: + cinfo->jpeg_color_space = JCS_CMYK; + break; + case 2: + cinfo->jpeg_color_space = JCS_YCCK; + break; + default: + WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform); + cinfo->jpeg_color_space = JCS_YCCK; /* assume it's YCCK */ + break; + } + } else { + /* No special markers, assume straight CMYK. */ + cinfo->jpeg_color_space = JCS_CMYK; + } + cinfo->out_color_space = JCS_CMYK; + break; + + default: + cinfo->jpeg_color_space = JCS_UNKNOWN; + cinfo->out_color_space = JCS_UNKNOWN; + break; + } + + /* Set defaults for other decompression parameters. */ + cinfo->scale_num = 1; /* 1:1 scaling */ + cinfo->scale_denom = 1; + cinfo->output_gamma = 1.0; + cinfo->buffered_image = FALSE; + cinfo->raw_data_out = FALSE; + cinfo->dct_method = JDCT_DEFAULT; + cinfo->do_fancy_upsampling = TRUE; + cinfo->do_block_smoothing = TRUE; + cinfo->quantize_colors = FALSE; + /* We set these in case application only sets quantize_colors. */ + cinfo->dither_mode = JDITHER_FS; +#ifdef QUANT_2PASS_SUPPORTED + cinfo->two_pass_quantize = TRUE; +#else + cinfo->two_pass_quantize = FALSE; +#endif + cinfo->desired_number_of_colors = 256; + cinfo->colormap = NULL; + /* Initialize for no mode change in buffered-image mode. */ + cinfo->enable_1pass_quant = FALSE; + cinfo->enable_external_quant = FALSE; + cinfo->enable_2pass_quant = FALSE; +} + + +/* + * Decompression startup: read start of JPEG datastream to see what's there. + * Need only initialize JPEG object and supply a data source before calling. + * + * This routine will read as far as the first SOS marker (ie, actual start of + * compressed data), and will save all tables and parameters in the JPEG + * object. It will also initialize the decompression parameters to default + * values, and finally return JPEG_HEADER_OK. On return, the application may + * adjust the decompression parameters and then call jpeg_start_decompress. + * (Or, if the application only wanted to determine the image parameters, + * the data need not be decompressed. In that case, call jpeg_abort or + * jpeg_destroy to release any temporary space.) + * If an abbreviated (tables only) datastream is presented, the routine will + * return JPEG_HEADER_TABLES_ONLY upon reaching EOI. The application may then + * re-use the JPEG object to read the abbreviated image datastream(s). + * It is unnecessary (but OK) to call jpeg_abort in this case. + * The JPEG_SUSPENDED return code only occurs if the data source module + * requests suspension of the decompressor. In this case the application + * should load more source data and then re-call jpeg_read_header to resume + * processing. + * If a non-suspending data source is used and require_image is TRUE, then the + * return code need not be inspected since only JPEG_HEADER_OK is possible. + * + * This routine is now just a front end to jpeg_consume_input, with some + * extra error checking. + */ + +GLOBAL(int) +jpeg_read_header (j_decompress_ptr cinfo, boolean require_image) +{ + int retcode; + + if (cinfo->global_state != DSTATE_START && + cinfo->global_state != DSTATE_INHEADER) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + retcode = jpeg_consume_input(cinfo); + + switch (retcode) { + case JPEG_REACHED_SOS: + retcode = JPEG_HEADER_OK; + break; + case JPEG_REACHED_EOI: + if (require_image) /* Complain if application wanted an image */ + ERREXIT(cinfo, JERR_NO_IMAGE); + /* Reset to start state; it would be safer to require the application to + * call jpeg_abort, but we can't change it now for compatibility reasons. + * A side effect is to free any temporary memory (there shouldn't be any). + */ + jpeg_abort((j_common_ptr) cinfo); /* sets state = DSTATE_START */ + retcode = JPEG_HEADER_TABLES_ONLY; + break; + case JPEG_SUSPENDED: + /* no work */ + break; + } + + return retcode; +} + + +/* + * Consume data in advance of what the decompressor requires. + * This can be called at any time once the decompressor object has + * been created and a data source has been set up. + * + * This routine is essentially a state machine that handles a couple + * of critical state-transition actions, namely initial setup and + * transition from header scanning to ready-for-start_decompress. + * All the actual input is done via the input controller's consume_input + * method. + */ + +GLOBAL(int) +jpeg_consume_input (j_decompress_ptr cinfo) +{ + int retcode = JPEG_SUSPENDED; + + /* NB: every possible DSTATE value should be listed in this switch */ + switch (cinfo->global_state) { + case DSTATE_START: + /* Start-of-datastream actions: reset appropriate modules */ + (*cinfo->inputctl->reset_input_controller) (cinfo); + /* Initialize application's data source module */ + (*cinfo->src->init_source) (cinfo); + cinfo->global_state = DSTATE_INHEADER; + /*FALLTHROUGH*/ + case DSTATE_INHEADER: + retcode = (*cinfo->inputctl->consume_input) (cinfo); + if (retcode == JPEG_REACHED_SOS) { /* Found SOS, prepare to decompress */ + /* Set up default parameters based on header data */ + default_decompress_parms(cinfo); + /* Set global state: ready for start_decompress */ + cinfo->global_state = DSTATE_READY; + } + break; + case DSTATE_READY: + /* Can't advance past first SOS until start_decompress is called */ + retcode = JPEG_REACHED_SOS; + break; + case DSTATE_PRELOAD: + case DSTATE_PRESCAN: + case DSTATE_SCANNING: + case DSTATE_RAW_OK: + case DSTATE_BUFIMAGE: + case DSTATE_BUFPOST: + case DSTATE_STOPPING: + retcode = (*cinfo->inputctl->consume_input) (cinfo); + break; + default: + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + } + return retcode; +} + + +/* + * Have we finished reading the input file? + */ + +GLOBAL(boolean) +jpeg_input_complete (j_decompress_ptr cinfo) +{ + /* Check for valid jpeg object */ + if (cinfo->global_state < DSTATE_START || + cinfo->global_state > DSTATE_STOPPING) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + return cinfo->inputctl->eoi_reached; +} + + +/* + * Is there more than one scan? + */ + +GLOBAL(boolean) +jpeg_has_multiple_scans (j_decompress_ptr cinfo) +{ + /* Only valid after jpeg_read_header completes */ + if (cinfo->global_state < DSTATE_READY || + cinfo->global_state > DSTATE_STOPPING) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + return cinfo->inputctl->has_multiple_scans; +} + + +/* + * Finish JPEG decompression. + * + * This will normally just verify the file trailer and release temp storage. + * + * Returns FALSE if suspended. The return value need be inspected only if + * a suspending data source is used. + */ + +GLOBAL(boolean) +jpeg_finish_decompress (j_decompress_ptr cinfo) +{ + if ((cinfo->global_state == DSTATE_SCANNING || + cinfo->global_state == DSTATE_RAW_OK) && ! cinfo->buffered_image) { + /* Terminate final pass of non-buffered mode */ + if (cinfo->output_scanline < cinfo->output_height) + ERREXIT(cinfo, JERR_TOO_LITTLE_DATA); + (*cinfo->master->finish_output_pass) (cinfo); + cinfo->global_state = DSTATE_STOPPING; + } else if (cinfo->global_state == DSTATE_BUFIMAGE) { + /* Finishing after a buffered-image operation */ + cinfo->global_state = DSTATE_STOPPING; + } else if (cinfo->global_state != DSTATE_STOPPING) { + /* STOPPING = repeat call after a suspension, anything else is error */ + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + } + /* Read until EOI */ + while (! cinfo->inputctl->eoi_reached) { + if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED) + return FALSE; /* Suspend, come back later */ + } + /* Do final cleanup */ + (*cinfo->src->term_source) (cinfo); + /* We can use jpeg_abort to release memory and reset global_state */ + jpeg_abort((j_common_ptr) cinfo); + return TRUE; +} diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jdapistd.c b/lc-continuity/mk4/modimage/jpeg-6b/jdapistd.c new file mode 100644 index 0000000000000000000000000000000000000000..c8e3fa0c35d2cc0f7b63de5c3d4ab6aa4c68c030 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jdapistd.c @@ -0,0 +1,275 @@ +/* + * jdapistd.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains application interface code for the decompression half + * of the JPEG library. These are the "standard" API routines that are + * used in the normal full-decompression case. They are not used by a + * transcoding-only application. Note that if an application links in + * jpeg_start_decompress, it will end up linking in the entire decompressor. + * We thus must separate this file from jdapimin.c to avoid linking the + * whole decompression library into a transcoder. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Forward declarations */ +LOCAL(boolean) output_pass_setup JPP((j_decompress_ptr cinfo)); + + +/* + * Decompression initialization. + * jpeg_read_header must be completed before calling this. + * + * If a multipass operating mode was selected, this will do all but the + * last pass, and thus may take a great deal of time. + * + * Returns FALSE if suspended. The return value need be inspected only if + * a suspending data source is used. + */ + +GLOBAL(boolean) +jpeg_start_decompress (j_decompress_ptr cinfo) +{ + if (cinfo->global_state == DSTATE_READY) { + /* First call: initialize master control, select active modules */ + jinit_master_decompress(cinfo); + if (cinfo->buffered_image) { + /* No more work here; expecting jpeg_start_output next */ + cinfo->global_state = DSTATE_BUFIMAGE; + return TRUE; + } + cinfo->global_state = DSTATE_PRELOAD; + } + if (cinfo->global_state == DSTATE_PRELOAD) { + /* If file has multiple scans, absorb them all into the coef buffer */ + if (cinfo->inputctl->has_multiple_scans) { +#ifdef D_MULTISCAN_FILES_SUPPORTED + for (;;) { + int retcode; + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + /* Absorb some more input */ + retcode = (*cinfo->inputctl->consume_input) (cinfo); + if (retcode == JPEG_SUSPENDED) + return FALSE; + if (retcode == JPEG_REACHED_EOI) + break; + /* Advance progress counter if appropriate */ + if (cinfo->progress != NULL && + (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) { + if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) { + /* jdmaster underestimated number of scans; ratchet up one scan */ + cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows; + } + } + } +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif /* D_MULTISCAN_FILES_SUPPORTED */ + } + cinfo->output_scan_number = cinfo->input_scan_number; + } else if (cinfo->global_state != DSTATE_PRESCAN) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + /* Perform any dummy output passes, and set up for the final pass */ + return output_pass_setup(cinfo); +} + + +/* + * Set up for an output pass, and perform any dummy pass(es) needed. + * Common subroutine for jpeg_start_decompress and jpeg_start_output. + * Entry: global_state = DSTATE_PRESCAN only if previously suspended. + * Exit: If done, returns TRUE and sets global_state for proper output mode. + * If suspended, returns FALSE and sets global_state = DSTATE_PRESCAN. + */ + +LOCAL(boolean) +output_pass_setup (j_decompress_ptr cinfo) +{ + if (cinfo->global_state != DSTATE_PRESCAN) { + /* First call: do pass setup */ + (*cinfo->master->prepare_for_output_pass) (cinfo); + cinfo->output_scanline = 0; + cinfo->global_state = DSTATE_PRESCAN; + } + /* Loop over any required dummy passes */ + while (cinfo->master->is_dummy_pass) { +#ifdef QUANT_2PASS_SUPPORTED + /* Crank through the dummy pass */ + while (cinfo->output_scanline < cinfo->output_height) { + JDIMENSION last_scanline; + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) cinfo->output_scanline; + cinfo->progress->pass_limit = (long) cinfo->output_height; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + /* Process some data */ + last_scanline = cinfo->output_scanline; + (*cinfo->main->process_data) (cinfo, (JSAMPARRAY) NULL, + &cinfo->output_scanline, (JDIMENSION) 0); + if (cinfo->output_scanline == last_scanline) + return FALSE; /* No progress made, must suspend */ + } + /* Finish up dummy pass, and set up for another one */ + (*cinfo->master->finish_output_pass) (cinfo); + (*cinfo->master->prepare_for_output_pass) (cinfo); + cinfo->output_scanline = 0; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif /* QUANT_2PASS_SUPPORTED */ + } + /* Ready for application to drive output pass through + * jpeg_read_scanlines or jpeg_read_raw_data. + */ + cinfo->global_state = cinfo->raw_data_out ? DSTATE_RAW_OK : DSTATE_SCANNING; + return TRUE; +} + + +/* + * Read some scanlines of data from the JPEG decompressor. + * + * The return value will be the number of lines actually read. + * This may be less than the number requested in several cases, + * including bottom of image, data source suspension, and operating + * modes that emit multiple scanlines at a time. + * + * Note: we warn about excess calls to jpeg_read_scanlines() since + * this likely signals an application programmer error. However, + * an oversize buffer (max_lines > scanlines remaining) is not an error. + */ + +GLOBAL(JDIMENSION) +jpeg_read_scanlines (j_decompress_ptr cinfo, JSAMPARRAY scanlines, + JDIMENSION max_lines) +{ + JDIMENSION row_ctr; + + if (cinfo->global_state != DSTATE_SCANNING) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + if (cinfo->output_scanline >= cinfo->output_height) { + WARNMS(cinfo, JWRN_TOO_MUCH_DATA); + return 0; + } + + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) cinfo->output_scanline; + cinfo->progress->pass_limit = (long) cinfo->output_height; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + + /* Process some data */ + row_ctr = 0; + (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, max_lines); + cinfo->output_scanline += row_ctr; + return row_ctr; +} + + +/* + * Alternate entry point to read raw data. + * Processes exactly one iMCU row per call, unless suspended. + */ + +GLOBAL(JDIMENSION) +jpeg_read_raw_data (j_decompress_ptr cinfo, JSAMPIMAGE data, + JDIMENSION max_lines) +{ + JDIMENSION lines_per_iMCU_row; + + if (cinfo->global_state != DSTATE_RAW_OK) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + if (cinfo->output_scanline >= cinfo->output_height) { + WARNMS(cinfo, JWRN_TOO_MUCH_DATA); + return 0; + } + + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) cinfo->output_scanline; + cinfo->progress->pass_limit = (long) cinfo->output_height; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + + /* Verify that at least one iMCU row can be returned. */ + lines_per_iMCU_row = cinfo->max_v_samp_factor * cinfo->min_DCT_scaled_size; + if (max_lines < lines_per_iMCU_row) + ERREXIT(cinfo, JERR_BUFFER_SIZE); + + /* Decompress directly into user's buffer. */ + if (! (*cinfo->coef->decompress_data) (cinfo, data)) + return 0; /* suspension forced, can do nothing more */ + + /* OK, we processed one iMCU row. */ + cinfo->output_scanline += lines_per_iMCU_row; + return lines_per_iMCU_row; +} + + +/* Additional entry points for buffered-image mode. */ + +#ifdef D_MULTISCAN_FILES_SUPPORTED + +/* + * Initialize for an output pass in buffered-image mode. + */ + +GLOBAL(boolean) +jpeg_start_output (j_decompress_ptr cinfo, int scan_number) +{ + if (cinfo->global_state != DSTATE_BUFIMAGE && + cinfo->global_state != DSTATE_PRESCAN) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + /* Limit scan number to valid range */ + if (scan_number <= 0) + scan_number = 1; + if (cinfo->inputctl->eoi_reached && + scan_number > cinfo->input_scan_number) + scan_number = cinfo->input_scan_number; + cinfo->output_scan_number = scan_number; + /* Perform any dummy output passes, and set up for the real pass */ + return output_pass_setup(cinfo); +} + + +/* + * Finish up after an output pass in buffered-image mode. + * + * Returns FALSE if suspended. The return value need be inspected only if + * a suspending data source is used. + */ + +GLOBAL(boolean) +jpeg_finish_output (j_decompress_ptr cinfo) +{ + if ((cinfo->global_state == DSTATE_SCANNING || + cinfo->global_state == DSTATE_RAW_OK) && cinfo->buffered_image) { + /* Terminate this pass. */ + /* We do not require the whole pass to have been completed. */ + (*cinfo->master->finish_output_pass) (cinfo); + cinfo->global_state = DSTATE_BUFPOST; + } else if (cinfo->global_state != DSTATE_BUFPOST) { + /* BUFPOST = repeat call after a suspension, anything else is error */ + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + } + /* Read markers looking for SOS or EOI */ + while (cinfo->input_scan_number <= cinfo->output_scan_number && + ! cinfo->inputctl->eoi_reached) { + if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED) + return FALSE; /* Suspend, come back later */ + } + cinfo->global_state = DSTATE_BUFIMAGE; + return TRUE; +} + +#endif /* D_MULTISCAN_FILES_SUPPORTED */ diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jdatadst.c b/lc-continuity/mk4/modimage/jpeg-6b/jdatadst.c new file mode 100644 index 0000000000000000000000000000000000000000..a8f6fb0e025364eccfcb033dcf576560fc7c0fb3 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jdatadst.c @@ -0,0 +1,151 @@ +/* + * jdatadst.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains compression data destination routines for the case of + * emitting JPEG data to a file (or any stdio stream). While these routines + * are sufficient for most applications, some will want to use a different + * destination manager. + * IMPORTANT: we assume that fwrite() will correctly transcribe an array of + * JOCTETs into 8-bit-wide elements on external storage. If char is wider + * than 8 bits on your machine, you may need to do some tweaking. + */ + +/* this is not a core library module, so it doesn't define JPEG_INTERNALS */ +#include "jinclude.h" +#include "jpeglib.h" +#include "jerror.h" + + +/* Expanded data destination object for stdio output */ + +typedef struct { + struct jpeg_destination_mgr pub; /* public fields */ + + FILE * outfile; /* target stream */ + JOCTET * buffer; /* start of buffer */ +} my_destination_mgr; + +typedef my_destination_mgr * my_dest_ptr; + +#define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */ + + +/* + * Initialize destination --- called by jpeg_start_compress + * before any data is actually written. + */ + +METHODDEF(void) +init_destination (j_compress_ptr cinfo) +{ + my_dest_ptr dest = (my_dest_ptr) cinfo->dest; + + /* Allocate the output buffer --- it will be released when done with image */ + dest->buffer = (JOCTET *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + OUTPUT_BUF_SIZE * SIZEOF(JOCTET)); + + dest->pub.next_output_byte = dest->buffer; + dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; +} + + +/* + * Empty the output buffer --- called whenever buffer fills up. + * + * In typical applications, this should write the entire output buffer + * (ignoring the current state of next_output_byte & free_in_buffer), + * reset the pointer & count to the start of the buffer, and return TRUE + * indicating that the buffer has been dumped. + * + * In applications that need to be able to suspend compression due to output + * overrun, a FALSE return indicates that the buffer cannot be emptied now. + * In this situation, the compressor will return to its caller (possibly with + * an indication that it has not accepted all the supplied scanlines). The + * application should resume compression after it has made more room in the + * output buffer. Note that there are substantial restrictions on the use of + * suspension --- see the documentation. + * + * When suspending, the compressor will back up to a convenient restart point + * (typically the start of the current MCU). next_output_byte & free_in_buffer + * indicate where the restart point will be if the current call returns FALSE. + * Data beyond this point will be regenerated after resumption, so do not + * write it out when emptying the buffer externally. + */ + +METHODDEF(boolean) +empty_output_buffer (j_compress_ptr cinfo) +{ + my_dest_ptr dest = (my_dest_ptr) cinfo->dest; + + if (JFWRITE(dest->outfile, dest->buffer, OUTPUT_BUF_SIZE) != + (size_t) OUTPUT_BUF_SIZE) + ERREXIT(cinfo, JERR_FILE_WRITE); + + dest->pub.next_output_byte = dest->buffer; + dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; + + return TRUE; +} + + +/* + * Terminate destination --- called by jpeg_finish_compress + * after all data has been written. Usually needs to flush buffer. + * + * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding + * application must deal with any cleanup that should happen even + * for error exit. + */ + +METHODDEF(void) +term_destination (j_compress_ptr cinfo) +{ + my_dest_ptr dest = (my_dest_ptr) cinfo->dest; + size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer; + + /* Write any data remaining in the buffer */ + if (datacount > 0) { + if (JFWRITE(dest->outfile, dest->buffer, datacount) != datacount) + ERREXIT(cinfo, JERR_FILE_WRITE); + } + fflush(dest->outfile); + /* Make sure we wrote the output file OK */ + if (ferror(dest->outfile)) + ERREXIT(cinfo, JERR_FILE_WRITE); +} + + +/* + * Prepare for output to a stdio stream. + * The caller must have already opened the stream, and is responsible + * for closing it after finishing compression. + */ + +GLOBAL(void) +jpeg_stdio_dest (j_compress_ptr cinfo, FILE * outfile) +{ + my_dest_ptr dest; + + /* The destination object is made permanent so that multiple JPEG images + * can be written to the same file without re-executing jpeg_stdio_dest. + * This makes it dangerous to use this manager and a different destination + * manager serially with the same JPEG object, because their private object + * sizes may be different. Caveat programmer. + */ + if (cinfo->dest == NULL) { /* first time for this JPEG object? */ + cinfo->dest = (struct jpeg_destination_mgr *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(my_destination_mgr)); + } + + dest = (my_dest_ptr) cinfo->dest; + dest->pub.init_destination = init_destination; + dest->pub.empty_output_buffer = empty_output_buffer; + dest->pub.term_destination = term_destination; + dest->outfile = outfile; +} diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jdatasrc.c b/lc-continuity/mk4/modimage/jpeg-6b/jdatasrc.c new file mode 100644 index 0000000000000000000000000000000000000000..edc752bf5d8c233a6597ba6a46d48ec7e43c65c7 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jdatasrc.c @@ -0,0 +1,212 @@ +/* + * jdatasrc.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains decompression data source routines for the case of + * reading JPEG data from a file (or any stdio stream). While these routines + * are sufficient for most applications, some will want to use a different + * source manager. + * IMPORTANT: we assume that fread() will correctly transcribe an array of + * JOCTETs from 8-bit-wide elements on external storage. If char is wider + * than 8 bits on your machine, you may need to do some tweaking. + */ + +/* this is not a core library module, so it doesn't define JPEG_INTERNALS */ +#include "jinclude.h" +#include "jpeglib.h" +#include "jerror.h" + + +/* Expanded data source object for stdio input */ + +typedef struct { + struct jpeg_source_mgr pub; /* public fields */ + + FILE * infile; /* source stream */ + JOCTET * buffer; /* start of buffer */ + boolean start_of_file; /* have we gotten any data yet? */ +} my_source_mgr; + +typedef my_source_mgr * my_src_ptr; + +#define INPUT_BUF_SIZE 4096 /* choose an efficiently fread'able size */ + + +/* + * Initialize source --- called by jpeg_read_header + * before any data is actually read. + */ + +METHODDEF(void) +init_source (j_decompress_ptr cinfo) +{ + my_src_ptr src = (my_src_ptr) cinfo->src; + + /* We reset the empty-input-file flag for each image, + * but we don't clear the input buffer. + * This is correct behavior for reading a series of images from one source. + */ + src->start_of_file = TRUE; +} + + +/* + * Fill the input buffer --- called whenever buffer is emptied. + * + * In typical applications, this should read fresh data into the buffer + * (ignoring the current state of next_input_byte & bytes_in_buffer), + * reset the pointer & count to the start of the buffer, and return TRUE + * indicating that the buffer has been reloaded. It is not necessary to + * fill the buffer entirely, only to obtain at least one more byte. + * + * There is no such thing as an EOF return. If the end of the file has been + * reached, the routine has a choice of ERREXIT() or inserting fake data into + * the buffer. In most cases, generating a warning message and inserting a + * fake EOI marker is the best course of action --- this will allow the + * decompressor to output however much of the image is there. However, + * the resulting error message is misleading if the real problem is an empty + * input file, so we handle that case specially. + * + * In applications that need to be able to suspend compression due to input + * not being available yet, a FALSE return indicates that no more data can be + * obtained right now, but more may be forthcoming later. In this situation, + * the decompressor will return to its caller (with an indication of the + * number of scanlines it has read, if any). The application should resume + * decompression after it has loaded more data into the input buffer. Note + * that there are substantial restrictions on the use of suspension --- see + * the documentation. + * + * When suspending, the decompressor will back up to a convenient restart point + * (typically the start of the current MCU). next_input_byte & bytes_in_buffer + * indicate where the restart point will be if the current call returns FALSE. + * Data beyond this point must be rescanned after resumption, so move it to + * the front of the buffer rather than discarding it. + */ + +METHODDEF(boolean) +fill_input_buffer (j_decompress_ptr cinfo) +{ + my_src_ptr src = (my_src_ptr) cinfo->src; + size_t nbytes; + + nbytes = JFREAD(src->infile, src->buffer, INPUT_BUF_SIZE); + + if (nbytes <= 0) { + if (src->start_of_file) /* Treat empty input file as fatal error */ + ERREXIT(cinfo, JERR_INPUT_EMPTY); + WARNMS(cinfo, JWRN_JPEG_EOF); + /* Insert a fake EOI marker */ + src->buffer[0] = (JOCTET) 0xFF; + src->buffer[1] = (JOCTET) JPEG_EOI; + nbytes = 2; + } + + src->pub.next_input_byte = src->buffer; + src->pub.bytes_in_buffer = nbytes; + src->start_of_file = FALSE; + + return TRUE; +} + + +/* + * Skip data --- used to skip over a potentially large amount of + * uninteresting data (such as an APPn marker). + * + * Writers of suspendable-input applications must note that skip_input_data + * is not granted the right to give a suspension return. If the skip extends + * beyond the data currently in the buffer, the buffer can be marked empty so + * that the next read will cause a fill_input_buffer call that can suspend. + * Arranging for additional bytes to be discarded before reloading the input + * buffer is the application writer's problem. + */ + +METHODDEF(void) +skip_input_data (j_decompress_ptr cinfo, long num_bytes) +{ + my_src_ptr src = (my_src_ptr) cinfo->src; + + /* Just a dumb implementation for now. Could use fseek() except + * it doesn't work on pipes. Not clear that being smart is worth + * any trouble anyway --- large skips are infrequent. + */ + if (num_bytes > 0) { + while (num_bytes > (long) src->pub.bytes_in_buffer) { + num_bytes -= (long) src->pub.bytes_in_buffer; + (void) fill_input_buffer(cinfo); + /* note we assume that fill_input_buffer will never return FALSE, + * so suspension need not be handled. + */ + } + src->pub.next_input_byte += (size_t) num_bytes; + src->pub.bytes_in_buffer -= (size_t) num_bytes; + } +} + + +/* + * An additional method that can be provided by data source modules is the + * resync_to_restart method for error recovery in the presence of RST markers. + * For the moment, this source module just uses the default resync method + * provided by the JPEG library. That method assumes that no backtracking + * is possible. + */ + + +/* + * Terminate source --- called by jpeg_finish_decompress + * after all data has been read. Often a no-op. + * + * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding + * application must deal with any cleanup that should happen even + * for error exit. + */ + +METHODDEF(void) +term_source (j_decompress_ptr cinfo) +{ + /* no work necessary here */ +} + + +/* + * Prepare for input from a stdio stream. + * The caller must have already opened the stream, and is responsible + * for closing it after finishing decompression. + */ + +GLOBAL(void) +jpeg_stdio_src (j_decompress_ptr cinfo, FILE * infile) +{ + my_src_ptr src; + + /* The source object and input buffer are made permanent so that a series + * of JPEG images can be read from the same file by calling jpeg_stdio_src + * only before the first one. (If we discarded the buffer at the end of + * one image, we'd likely lose the start of the next one.) + * This makes it unsafe to use this manager and a different source + * manager serially with the same JPEG object. Caveat programmer. + */ + if (cinfo->src == NULL) { /* first time for this JPEG object? */ + cinfo->src = (struct jpeg_source_mgr *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(my_source_mgr)); + src = (my_src_ptr) cinfo->src; + src->buffer = (JOCTET *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + INPUT_BUF_SIZE * SIZEOF(JOCTET)); + } + + src = (my_src_ptr) cinfo->src; + src->pub.init_source = init_source; + src->pub.fill_input_buffer = fill_input_buffer; + src->pub.skip_input_data = skip_input_data; + src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */ + src->pub.term_source = term_source; + src->infile = infile; + src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */ + src->pub.next_input_byte = NULL; /* until buffer loaded */ +} diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jdcoefct.c b/lc-continuity/mk4/modimage/jpeg-6b/jdcoefct.c new file mode 100644 index 0000000000000000000000000000000000000000..4938d20fcb655632d640534ba19e73f0c8fdccbc --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jdcoefct.c @@ -0,0 +1,736 @@ +/* + * jdcoefct.c + * + * Copyright (C) 1994-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the coefficient buffer controller for decompression. + * This controller is the top level of the JPEG decompressor proper. + * The coefficient buffer lies between entropy decoding and inverse-DCT steps. + * + * In buffered-image mode, this controller is the interface between + * input-oriented processing and output-oriented processing. + * Also, the input side (only) is used when reading a file for transcoding. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + +/* Block smoothing is only applicable for progressive JPEG, so: */ +#ifndef D_PROGRESSIVE_SUPPORTED +#undef BLOCK_SMOOTHING_SUPPORTED +#endif + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_d_coef_controller pub; /* public fields */ + + /* These variables keep track of the current location of the input side. */ + /* cinfo->input_iMCU_row is also used for this. */ + JDIMENSION MCU_ctr; /* counts MCUs processed in current row */ + int MCU_vert_offset; /* counts MCU rows within iMCU row */ + int MCU_rows_per_iMCU_row; /* number of such rows needed */ + + /* The output side's location is represented by cinfo->output_iMCU_row. */ + + /* In single-pass modes, it's sufficient to buffer just one MCU. + * We allocate a workspace of D_MAX_BLOCKS_IN_MCU coefficient blocks, + * and let the entropy decoder write into that workspace each time. + * (On 80x86, the workspace is FAR even though it's not really very big; + * this is to keep the module interfaces unchanged when a large coefficient + * buffer is necessary.) + * In multi-pass modes, this array points to the current MCU's blocks + * within the virtual arrays; it is used only by the input side. + */ + JBLOCKROW MCU_buffer[D_MAX_BLOCKS_IN_MCU]; + +#ifdef D_MULTISCAN_FILES_SUPPORTED + /* In multi-pass modes, we need a virtual block array for each component. */ + jvirt_barray_ptr whole_image[MAX_COMPONENTS]; +#endif + +#ifdef BLOCK_SMOOTHING_SUPPORTED + /* When doing block smoothing, we latch coefficient Al values here */ + int * coef_bits_latch; +#define SAVED_COEFS 6 /* we save coef_bits[0..5] */ +#endif +} my_coef_controller; + +typedef my_coef_controller * my_coef_ptr; + +/* Forward declarations */ +METHODDEF(int) decompress_onepass + JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); +#ifdef D_MULTISCAN_FILES_SUPPORTED +METHODDEF(int) decompress_data + JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); +#endif +#ifdef BLOCK_SMOOTHING_SUPPORTED +LOCAL(boolean) smoothing_ok JPP((j_decompress_ptr cinfo)); +METHODDEF(int) decompress_smooth_data + JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); +#endif + + +LOCAL(void) +start_iMCU_row (j_decompress_ptr cinfo) +/* Reset within-iMCU-row counters for a new row (input side) */ +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + + /* In an interleaved scan, an MCU row is the same as an iMCU row. + * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. + * But at the bottom of the image, process only what's left. + */ + if (cinfo->comps_in_scan > 1) { + coef->MCU_rows_per_iMCU_row = 1; + } else { + if (cinfo->input_iMCU_row < (cinfo->total_iMCU_rows-1)) + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; + else + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; + } + + coef->MCU_ctr = 0; + coef->MCU_vert_offset = 0; +} + + +/* + * Initialize for an input processing pass. + */ + +METHODDEF(void) +start_input_pass (j_decompress_ptr cinfo) +{ + cinfo->input_iMCU_row = 0; + start_iMCU_row(cinfo); +} + + +/* + * Initialize for an output processing pass. + */ + +METHODDEF(void) +start_output_pass (j_decompress_ptr cinfo) +{ +#ifdef BLOCK_SMOOTHING_SUPPORTED + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + + /* If multipass, check to see whether to use block smoothing on this pass */ + if (coef->pub.coef_arrays != NULL) { + if (cinfo->do_block_smoothing && smoothing_ok(cinfo)) + coef->pub.decompress_data = decompress_smooth_data; + else + coef->pub.decompress_data = decompress_data; + } +#endif + cinfo->output_iMCU_row = 0; +} + + +/* + * Decompress and return some data in the single-pass case. + * Always attempts to emit one fully interleaved MCU row ("iMCU" row). + * Input and output must run in lockstep since we have only a one-MCU buffer. + * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. + * + * NB: output_buf contains a plane for each component in image, + * which we index according to the component's SOF position. + */ + +METHODDEF(int) +decompress_onepass (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + int blkn, ci, xindex, yindex, yoffset, useful_width; + JSAMPARRAY output_ptr; + JDIMENSION start_col, output_col; + jpeg_component_info *compptr; + inverse_DCT_method_ptr inverse_DCT; + + /* Loop to process as much as one whole iMCU row */ + for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; + yoffset++) { + for (MCU_col_num = coef->MCU_ctr; MCU_col_num <= last_MCU_col; + MCU_col_num++) { + /* Try to fetch an MCU. Entropy decoder expects buffer to be zeroed. */ + jzero_far((void FAR *) coef->MCU_buffer[0], + (size_t) (cinfo->blocks_in_MCU * SIZEOF(JBLOCK))); + if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) { + /* Suspension forced; update state counters and exit */ + coef->MCU_vert_offset = yoffset; + coef->MCU_ctr = MCU_col_num; + return JPEG_SUSPENDED; + } + /* Determine where data should go in output_buf and do the IDCT thing. + * We skip dummy blocks at the right and bottom edges (but blkn gets + * incremented past them!). Note the inner loop relies on having + * allocated the MCU_buffer[] blocks sequentially. + */ + blkn = 0; /* index of current DCT block within MCU */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* Don't bother to IDCT an uninteresting component. */ + if (! compptr->component_needed) { + blkn += compptr->MCU_blocks; + continue; + } + inverse_DCT = cinfo->idct->inverse_DCT[compptr->component_index]; + useful_width = (MCU_col_num < last_MCU_col) ? compptr->MCU_width + : compptr->last_col_width; + output_ptr = output_buf[compptr->component_index] + + yoffset * compptr->DCT_scaled_size; + start_col = MCU_col_num * compptr->MCU_sample_width; + for (yindex = 0; yindex < compptr->MCU_height; yindex++) { + if (cinfo->input_iMCU_row < last_iMCU_row || + yoffset+yindex < compptr->last_row_height) { + output_col = start_col; + for (xindex = 0; xindex < useful_width; xindex++) { + (*inverse_DCT) (cinfo, compptr, + (JCOEFPTR) coef->MCU_buffer[blkn+xindex], + output_ptr, output_col); + output_col += compptr->DCT_scaled_size; + } + } + blkn += compptr->MCU_width; + output_ptr += compptr->DCT_scaled_size; + } + } + } + /* Completed an MCU row, but perhaps not an iMCU row */ + coef->MCU_ctr = 0; + } + /* Completed the iMCU row, advance counters for next one */ + cinfo->output_iMCU_row++; + if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) { + start_iMCU_row(cinfo); + return JPEG_ROW_COMPLETED; + } + /* Completed the scan */ + (*cinfo->inputctl->finish_input_pass) (cinfo); + return JPEG_SCAN_COMPLETED; +} + + +/* + * Dummy consume-input routine for single-pass operation. + */ + +METHODDEF(int) +dummy_consume_data (j_decompress_ptr cinfo) +{ + return JPEG_SUSPENDED; /* Always indicate nothing was done */ +} + + +#ifdef D_MULTISCAN_FILES_SUPPORTED + +/* + * Consume input data and store it in the full-image coefficient buffer. + * We read as much as one fully interleaved MCU row ("iMCU" row) per call, + * ie, v_samp_factor block rows for each component in the scan. + * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. + */ + +METHODDEF(int) +consume_data (j_decompress_ptr cinfo) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + int blkn, ci, xindex, yindex, yoffset; + JDIMENSION start_col; + JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; + JBLOCKROW buffer_ptr; + jpeg_component_info *compptr; + + /* Align the virtual buffers for the components used in this scan. */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + buffer[ci] = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], + cinfo->input_iMCU_row * compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, TRUE); + /* Note: entropy decoder expects buffer to be zeroed, + * but this is handled automatically by the memory manager + * because we requested a pre-zeroed array. + */ + } + + /* Loop to process one whole iMCU row */ + for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; + yoffset++) { + for (MCU_col_num = coef->MCU_ctr; MCU_col_num < cinfo->MCUs_per_row; + MCU_col_num++) { + /* Construct list of pointers to DCT blocks belonging to this MCU */ + blkn = 0; /* index of current DCT block within MCU */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + start_col = MCU_col_num * compptr->MCU_width; + for (yindex = 0; yindex < compptr->MCU_height; yindex++) { + buffer_ptr = buffer[ci][yindex+yoffset] + start_col; + for (xindex = 0; xindex < compptr->MCU_width; xindex++) { + coef->MCU_buffer[blkn++] = buffer_ptr++; + } + } + } + /* Try to fetch the MCU. */ + if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) { + /* Suspension forced; update state counters and exit */ + coef->MCU_vert_offset = yoffset; + coef->MCU_ctr = MCU_col_num; + return JPEG_SUSPENDED; + } + } + /* Completed an MCU row, but perhaps not an iMCU row */ + coef->MCU_ctr = 0; + } + /* Completed the iMCU row, advance counters for next one */ + if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) { + start_iMCU_row(cinfo); + return JPEG_ROW_COMPLETED; + } + /* Completed the scan */ + (*cinfo->inputctl->finish_input_pass) (cinfo); + return JPEG_SCAN_COMPLETED; +} + + +/* + * Decompress and return some data in the multi-pass case. + * Always attempts to emit one fully interleaved MCU row ("iMCU" row). + * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. + * + * NB: output_buf contains a plane for each component in image. + */ + +METHODDEF(int) +decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + JDIMENSION block_num; + int ci, block_row, block_rows; + JBLOCKARRAY buffer; + JBLOCKROW buffer_ptr; + JSAMPARRAY output_ptr; + JDIMENSION output_col; + jpeg_component_info *compptr; + inverse_DCT_method_ptr inverse_DCT; + + /* Force some input to be done if we are getting ahead of the input. */ + while (cinfo->input_scan_number < cinfo->output_scan_number || + (cinfo->input_scan_number == cinfo->output_scan_number && + cinfo->input_iMCU_row <= cinfo->output_iMCU_row)) { + if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED) + return JPEG_SUSPENDED; + } + + /* OK, output from the virtual arrays. */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Don't bother to IDCT an uninteresting component. */ + if (! compptr->component_needed) + continue; + /* Align the virtual buffer for this component. */ + buffer = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[ci], + cinfo->output_iMCU_row * compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, FALSE); + /* Count non-dummy DCT block rows in this iMCU row. */ + if (cinfo->output_iMCU_row < last_iMCU_row) + block_rows = compptr->v_samp_factor; + else { + /* NB: can't use last_row_height here; it is input-side-dependent! */ + block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor); + if (block_rows == 0) block_rows = compptr->v_samp_factor; + } + inverse_DCT = cinfo->idct->inverse_DCT[ci]; + output_ptr = output_buf[ci]; + /* Loop over all DCT blocks to be processed. */ + for (block_row = 0; block_row < block_rows; block_row++) { + buffer_ptr = buffer[block_row]; + output_col = 0; + for (block_num = 0; block_num < compptr->width_in_blocks; block_num++) { + (*inverse_DCT) (cinfo, compptr, (JCOEFPTR) buffer_ptr, + output_ptr, output_col); + buffer_ptr++; + output_col += compptr->DCT_scaled_size; + } + output_ptr += compptr->DCT_scaled_size; + } + } + + if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows) + return JPEG_ROW_COMPLETED; + return JPEG_SCAN_COMPLETED; +} + +#endif /* D_MULTISCAN_FILES_SUPPORTED */ + + +#ifdef BLOCK_SMOOTHING_SUPPORTED + +/* + * This code applies interblock smoothing as described by section K.8 + * of the JPEG standard: the first 5 AC coefficients are estimated from + * the DC values of a DCT block and its 8 neighboring blocks. + * We apply smoothing only for progressive JPEG decoding, and only if + * the coefficients it can estimate are not yet known to full precision. + */ + +/* Natural-order array positions of the first 5 zigzag-order coefficients */ +#define Q01_POS 1 +#define Q10_POS 8 +#define Q20_POS 16 +#define Q11_POS 9 +#define Q02_POS 2 + +/* + * Determine whether block smoothing is applicable and safe. + * We also latch the current states of the coef_bits[] entries for the + * AC coefficients; otherwise, if the input side of the decompressor + * advances into a new scan, we might think the coefficients are known + * more accurately than they really are. + */ + +LOCAL(boolean) +smoothing_ok (j_decompress_ptr cinfo) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + boolean smoothing_useful = FALSE; + int ci, coefi; + jpeg_component_info *compptr; + JQUANT_TBL * qtable; + int * coef_bits; + int * coef_bits_latch; + + if (! cinfo->progressive_mode || cinfo->coef_bits == NULL) + return FALSE; + + /* Allocate latch area if not already done */ + if (coef->coef_bits_latch == NULL) + coef->coef_bits_latch = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + cinfo->num_components * + (SAVED_COEFS * SIZEOF(int))); + coef_bits_latch = coef->coef_bits_latch; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* All components' quantization values must already be latched. */ + if ((qtable = compptr->quant_table) == NULL) + return FALSE; + /* Verify DC & first 5 AC quantizers are nonzero to avoid zero-divide. */ + if (qtable->quantval[0] == 0 || + qtable->quantval[Q01_POS] == 0 || + qtable->quantval[Q10_POS] == 0 || + qtable->quantval[Q20_POS] == 0 || + qtable->quantval[Q11_POS] == 0 || + qtable->quantval[Q02_POS] == 0) + return FALSE; + /* DC values must be at least partly known for all components. */ + coef_bits = cinfo->coef_bits[ci]; + if (coef_bits[0] < 0) + return FALSE; + /* Block smoothing is helpful if some AC coefficients remain inaccurate. */ + for (coefi = 1; coefi <= 5; coefi++) { + coef_bits_latch[coefi] = coef_bits[coefi]; + if (coef_bits[coefi] != 0) + smoothing_useful = TRUE; + } + coef_bits_latch += SAVED_COEFS; + } + + return smoothing_useful; +} + + +/* + * Variant of decompress_data for use when doing block smoothing. + */ + +METHODDEF(int) +decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + JDIMENSION block_num, last_block_column; + int ci, block_row, block_rows, access_rows; + JBLOCKARRAY buffer; + JBLOCKROW buffer_ptr, prev_block_row, next_block_row; + JSAMPARRAY output_ptr; + JDIMENSION output_col; + jpeg_component_info *compptr; + inverse_DCT_method_ptr inverse_DCT; + boolean first_row, last_row; + JBLOCK workspace; + int *coef_bits; + JQUANT_TBL *quanttbl; + INT32 Q00,Q01,Q02,Q10,Q11,Q20, num; + int DC1,DC2,DC3,DC4,DC5,DC6,DC7,DC8,DC9; + int Al, pred; + + /* Force some input to be done if we are getting ahead of the input. */ + while (cinfo->input_scan_number <= cinfo->output_scan_number && + ! cinfo->inputctl->eoi_reached) { + if (cinfo->input_scan_number == cinfo->output_scan_number) { + /* If input is working on current scan, we ordinarily want it to + * have completed the current row. But if input scan is DC, + * we want it to keep one row ahead so that next block row's DC + * values are up to date. + */ + JDIMENSION delta = (cinfo->Ss == 0) ? 1 : 0; + if (cinfo->input_iMCU_row > cinfo->output_iMCU_row+delta) + break; + } + if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED) + return JPEG_SUSPENDED; + } + + /* OK, output from the virtual arrays. */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Don't bother to IDCT an uninteresting component. */ + if (! compptr->component_needed) + continue; + /* Count non-dummy DCT block rows in this iMCU row. */ + if (cinfo->output_iMCU_row < last_iMCU_row) { + block_rows = compptr->v_samp_factor; + access_rows = block_rows * 2; /* this and next iMCU row */ + last_row = FALSE; + } else { + /* NB: can't use last_row_height here; it is input-side-dependent! */ + block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor); + if (block_rows == 0) block_rows = compptr->v_samp_factor; + access_rows = block_rows; /* this iMCU row only */ + last_row = TRUE; + } + /* Align the virtual buffer for this component. */ + if (cinfo->output_iMCU_row > 0) { + access_rows += compptr->v_samp_factor; /* prior iMCU row too */ + buffer = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[ci], + (cinfo->output_iMCU_row - 1) * compptr->v_samp_factor, + (JDIMENSION) access_rows, FALSE); + buffer += compptr->v_samp_factor; /* point to current iMCU row */ + first_row = FALSE; + } else { + buffer = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[ci], + (JDIMENSION) 0, (JDIMENSION) access_rows, FALSE); + first_row = TRUE; + } + /* Fetch component-dependent info */ + coef_bits = coef->coef_bits_latch + (ci * SAVED_COEFS); + quanttbl = compptr->quant_table; + Q00 = quanttbl->quantval[0]; + Q01 = quanttbl->quantval[Q01_POS]; + Q10 = quanttbl->quantval[Q10_POS]; + Q20 = quanttbl->quantval[Q20_POS]; + Q11 = quanttbl->quantval[Q11_POS]; + Q02 = quanttbl->quantval[Q02_POS]; + inverse_DCT = cinfo->idct->inverse_DCT[ci]; + output_ptr = output_buf[ci]; + /* Loop over all DCT blocks to be processed. */ + for (block_row = 0; block_row < block_rows; block_row++) { + buffer_ptr = buffer[block_row]; + if (first_row && block_row == 0) + prev_block_row = buffer_ptr; + else + prev_block_row = buffer[block_row-1]; + if (last_row && block_row == block_rows-1) + next_block_row = buffer_ptr; + else + next_block_row = buffer[block_row+1]; + /* We fetch the surrounding DC values using a sliding-register approach. + * Initialize all nine here so as to do the right thing on narrow pics. + */ + DC1 = DC2 = DC3 = (int) prev_block_row[0][0]; + DC4 = DC5 = DC6 = (int) buffer_ptr[0][0]; + DC7 = DC8 = DC9 = (int) next_block_row[0][0]; + output_col = 0; + last_block_column = compptr->width_in_blocks - 1; + for (block_num = 0; block_num <= last_block_column; block_num++) { + /* Fetch current DCT block into workspace so we can modify it. */ + jcopy_block_row(buffer_ptr, (JBLOCKROW) workspace, (JDIMENSION) 1); + /* Update DC values */ + if (block_num < last_block_column) { + DC3 = (int) prev_block_row[1][0]; + DC6 = (int) buffer_ptr[1][0]; + DC9 = (int) next_block_row[1][0]; + } + /* Compute coefficient estimates per K.8. + * An estimate is applied only if coefficient is still zero, + * and is not known to be fully accurate. + */ + /* AC01 */ + if ((Al=coef_bits[1]) != 0 && workspace[1] == 0) { + num = 36 * Q00 * (DC4 - DC6); + if (num >= 0) { + pred = (int) (((Q01<<7) + num) / (Q01<<8)); + if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { + pred = (int) (((Q10<<7) + num) / (Q10<<8)); + if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { + pred = (int) (((Q20<<7) + num) / (Q20<<8)); + if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { + pred = (int) (((Q11<<7) + num) / (Q11<<8)); + if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { + pred = (int) (((Q02<<7) + num) / (Q02<<8)); + if (Al > 0 && pred >= (1< 0 && pred >= (1<DCT_scaled_size; + } + output_ptr += compptr->DCT_scaled_size; + } + } + + if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows) + return JPEG_ROW_COMPLETED; + return JPEG_SCAN_COMPLETED; +} + +#endif /* BLOCK_SMOOTHING_SUPPORTED */ + + +/* + * Initialize coefficient buffer controller. + */ + +GLOBAL(void) +jinit_d_coef_controller (j_decompress_ptr cinfo, boolean need_full_buffer) +{ + my_coef_ptr coef; + + coef = (my_coef_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_coef_controller)); + cinfo->coef = (struct jpeg_d_coef_controller *) coef; + coef->pub.start_input_pass = start_input_pass; + coef->pub.start_output_pass = start_output_pass; +#ifdef BLOCK_SMOOTHING_SUPPORTED + coef->coef_bits_latch = NULL; +#endif + + /* Create the coefficient buffer. */ + if (need_full_buffer) { +#ifdef D_MULTISCAN_FILES_SUPPORTED + /* Allocate a full-image virtual array for each component, */ + /* padded to a multiple of samp_factor DCT blocks in each direction. */ + /* Note we ask for a pre-zeroed array. */ + int ci, access_rows; + jpeg_component_info *compptr; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + access_rows = compptr->v_samp_factor; +#ifdef BLOCK_SMOOTHING_SUPPORTED + /* If block smoothing could be used, need a bigger window */ + if (cinfo->progressive_mode) + access_rows *= 3; +#endif + coef->whole_image[ci] = (*cinfo->mem->request_virt_barray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, TRUE, + (JDIMENSION) jround_up((long) compptr->width_in_blocks, + (long) compptr->h_samp_factor), + (JDIMENSION) jround_up((long) compptr->height_in_blocks, + (long) compptr->v_samp_factor), + (JDIMENSION) access_rows); + } + coef->pub.consume_data = consume_data; + coef->pub.decompress_data = decompress_data; + coef->pub.coef_arrays = coef->whole_image; /* link to virtual arrays */ +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + /* We only need a single-MCU buffer. */ + JBLOCKROW buffer; + int i; + + buffer = (JBLOCKROW) + (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, + D_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); + for (i = 0; i < D_MAX_BLOCKS_IN_MCU; i++) { + coef->MCU_buffer[i] = buffer + i; + } + coef->pub.consume_data = dummy_consume_data; + coef->pub.decompress_data = decompress_onepass; + coef->pub.coef_arrays = NULL; /* flag for no virtual arrays */ + } +} diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jdcolor.c b/lc-continuity/mk4/modimage/jpeg-6b/jdcolor.c new file mode 100644 index 0000000000000000000000000000000000000000..6c04dfe8aa1b36e4ab4c9909c77e9cd26b74e9d7 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jdcolor.c @@ -0,0 +1,396 @@ +/* + * jdcolor.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains output colorspace conversion routines. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Private subobject */ + +typedef struct { + struct jpeg_color_deconverter pub; /* public fields */ + + /* Private state for YCC->RGB conversion */ + int * Cr_r_tab; /* => table for Cr to R conversion */ + int * Cb_b_tab; /* => table for Cb to B conversion */ + INT32 * Cr_g_tab; /* => table for Cr to G conversion */ + INT32 * Cb_g_tab; /* => table for Cb to G conversion */ +} my_color_deconverter; + +typedef my_color_deconverter * my_cconvert_ptr; + + +/**************** YCbCr -> RGB conversion: most common case **************/ + +/* + * YCbCr is defined per CCIR 601-1, except that Cb and Cr are + * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. + * The conversion equations to be implemented are therefore + * R = Y + 1.40200 * Cr + * G = Y - 0.34414 * Cb - 0.71414 * Cr + * B = Y + 1.77200 * Cb + * where Cb and Cr represent the incoming values less CENTERJSAMPLE. + * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) + * + * To avoid floating-point arithmetic, we represent the fractional constants + * as integers scaled up by 2^16 (about 4 digits precision); we have to divide + * the products by 2^16, with appropriate rounding, to get the correct answer. + * Notice that Y, being an integral input, does not contribute any fraction + * so it need not participate in the rounding. + * + * For even more speed, we avoid doing any multiplications in the inner loop + * by precalculating the constants times Cb and Cr for all possible values. + * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); + * for 12-bit samples it is still acceptable. It's not very reasonable for + * 16-bit samples, but if you want lossless storage you shouldn't be changing + * colorspace anyway. + * The Cr=>R and Cb=>B values can be rounded to integers in advance; the + * values for the G calculation are left scaled up, since we must add them + * together before rounding. + */ + +#define SCALEBITS 16 /* speediest right-shift on some machines */ +#define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) +#define FIX(x) ((INT32) ((x) * (1L<RGB colorspace conversion. + */ + +LOCAL(void) +build_ycc_rgb_table (j_decompress_ptr cinfo) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + int i; + INT32 x; + SHIFT_TEMPS + + cconvert->Cr_r_tab = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(int)); + cconvert->Cb_b_tab = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(int)); + cconvert->Cr_g_tab = (INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(INT32)); + cconvert->Cb_g_tab = (INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(INT32)); + + for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { + /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ + /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ + /* Cr=>R value is nearest int to 1.40200 * x */ + cconvert->Cr_r_tab[i] = (int) + RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS); + /* Cb=>B value is nearest int to 1.77200 * x */ + cconvert->Cb_b_tab[i] = (int) + RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS); + /* Cr=>G value is scaled-up -0.71414 * x */ + cconvert->Cr_g_tab[i] = (- FIX(0.71414)) * x; + /* Cb=>G value is scaled-up -0.34414 * x */ + /* We also add in ONE_HALF so that need not do it in inner loop */ + cconvert->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF; + } +} + + +/* + * Convert some rows of samples to the output colorspace. + * + * Note that we change from noninterleaved, one-plane-per-component format + * to interleaved-pixel format. The output buffer is therefore three times + * as wide as the input buffer. + * A starting row offset is provided only for the input buffer. The caller + * can easily adjust the passed output_buf value to accommodate any row + * offset required on that side. + */ + +METHODDEF(void) +ycc_rgb_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + register int y, cb, cr; + register JSAMPROW outptr; + register JSAMPROW inptr0, inptr1, inptr2; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->output_width; + /* copy these pointers into registers if possible */ + register JSAMPLE * range_limit = cinfo->sample_range_limit; + register int * Crrtab = cconvert->Cr_r_tab; + register int * Cbbtab = cconvert->Cb_b_tab; + register INT32 * Crgtab = cconvert->Cr_g_tab; + register INT32 * Cbgtab = cconvert->Cb_g_tab; + SHIFT_TEMPS + + while (--num_rows >= 0) { + inptr0 = input_buf[0][input_row]; + inptr1 = input_buf[1][input_row]; + inptr2 = input_buf[2][input_row]; + input_row++; + outptr = *output_buf++; + for (col = 0; col < num_cols; col++) { + y = GETJSAMPLE(inptr0[col]); + cb = GETJSAMPLE(inptr1[col]); + cr = GETJSAMPLE(inptr2[col]); + /* Range-limiting is essential due to noise introduced by DCT losses. */ + outptr[RGB_RED] = range_limit[y + Crrtab[cr]]; + outptr[RGB_GREEN] = range_limit[y + + ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], + SCALEBITS))]; + outptr[RGB_BLUE] = range_limit[y + Cbbtab[cb]]; + outptr += RGB_PIXELSIZE; + } + } +} + + +/**************** Cases other than YCbCr -> RGB **************/ + + +/* + * Color conversion for no colorspace change: just copy the data, + * converting from separate-planes to interleaved representation. + */ + +METHODDEF(void) +null_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + register JSAMPROW inptr, outptr; + register JDIMENSION count; + register int num_components = cinfo->num_components; + JDIMENSION num_cols = cinfo->output_width; + int ci; + + while (--num_rows >= 0) { + for (ci = 0; ci < num_components; ci++) { + inptr = input_buf[ci][input_row]; + outptr = output_buf[0] + ci; + for (count = num_cols; count > 0; count--) { + *outptr = *inptr++; /* needn't bother with GETJSAMPLE() here */ + outptr += num_components; + } + } + input_row++; + output_buf++; + } +} + + +/* + * Color conversion for grayscale: just copy the data. + * This also works for YCbCr -> grayscale conversion, in which + * we just copy the Y (luminance) component and ignore chrominance. + */ + +METHODDEF(void) +grayscale_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + jcopy_sample_rows(input_buf[0], (int) input_row, output_buf, 0, + num_rows, cinfo->output_width); +} + + +/* + * Convert grayscale to RGB: just duplicate the graylevel three times. + * This is provided to support applications that don't want to cope + * with grayscale as a separate case. + */ + +METHODDEF(void) +gray_rgb_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + register JSAMPROW inptr, outptr; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->output_width; + + while (--num_rows >= 0) { + inptr = input_buf[0][input_row++]; + outptr = *output_buf++; + for (col = 0; col < num_cols; col++) { + /* We can dispense with GETJSAMPLE() here */ + outptr[RGB_RED] = outptr[RGB_GREEN] = outptr[RGB_BLUE] = inptr[col]; + outptr += RGB_PIXELSIZE; + } + } +} + + +/* + * Adobe-style YCCK->CMYK conversion. + * We convert YCbCr to R=1-C, G=1-M, and B=1-Y using the same + * conversion as above, while passing K (black) unchanged. + * We assume build_ycc_rgb_table has been called. + */ + +METHODDEF(void) +ycck_cmyk_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + register int y, cb, cr; + register JSAMPROW outptr; + register JSAMPROW inptr0, inptr1, inptr2, inptr3; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->output_width; + /* copy these pointers into registers if possible */ + register JSAMPLE * range_limit = cinfo->sample_range_limit; + register int * Crrtab = cconvert->Cr_r_tab; + register int * Cbbtab = cconvert->Cb_b_tab; + register INT32 * Crgtab = cconvert->Cr_g_tab; + register INT32 * Cbgtab = cconvert->Cb_g_tab; + SHIFT_TEMPS + + while (--num_rows >= 0) { + inptr0 = input_buf[0][input_row]; + inptr1 = input_buf[1][input_row]; + inptr2 = input_buf[2][input_row]; + inptr3 = input_buf[3][input_row]; + input_row++; + outptr = *output_buf++; + for (col = 0; col < num_cols; col++) { + y = GETJSAMPLE(inptr0[col]); + cb = GETJSAMPLE(inptr1[col]); + cr = GETJSAMPLE(inptr2[col]); + /* Range-limiting is essential due to noise introduced by DCT losses. */ + outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])]; /* red */ + outptr[1] = range_limit[MAXJSAMPLE - (y + /* green */ + ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], + SCALEBITS)))]; + outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])]; /* blue */ + /* K passes through unchanged */ + outptr[3] = inptr3[col]; /* don't need GETJSAMPLE here */ + outptr += 4; + } + } +} + + +/* + * Empty method for start_pass. + */ + +METHODDEF(void) +start_pass_dcolor (j_decompress_ptr cinfo) +{ + /* no work needed */ +} + + +/* + * Module initialization routine for output colorspace conversion. + */ + +GLOBAL(void) +jinit_color_deconverter (j_decompress_ptr cinfo) +{ + my_cconvert_ptr cconvert; + int ci; + + cconvert = (my_cconvert_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_color_deconverter)); + cinfo->cconvert = (struct jpeg_color_deconverter *) cconvert; + cconvert->pub.start_pass = start_pass_dcolor; + + /* Make sure num_components agrees with jpeg_color_space */ + switch (cinfo->jpeg_color_space) { + case JCS_GRAYSCALE: + if (cinfo->num_components != 1) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + break; + + case JCS_RGB: + case JCS_YCbCr: + if (cinfo->num_components != 3) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + break; + + case JCS_CMYK: + case JCS_YCCK: + if (cinfo->num_components != 4) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + break; + + default: /* JCS_UNKNOWN can be anything */ + if (cinfo->num_components < 1) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + break; + } + + /* Set out_color_components and conversion method based on requested space. + * Also clear the component_needed flags for any unused components, + * so that earlier pipeline stages can avoid useless computation. + */ + + switch (cinfo->out_color_space) { + case JCS_GRAYSCALE: + cinfo->out_color_components = 1; + if (cinfo->jpeg_color_space == JCS_GRAYSCALE || + cinfo->jpeg_color_space == JCS_YCbCr) { + cconvert->pub.color_convert = grayscale_convert; + /* For color->grayscale conversion, only the Y (0) component is needed */ + for (ci = 1; ci < cinfo->num_components; ci++) + cinfo->comp_info[ci].component_needed = FALSE; + } else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_RGB: + cinfo->out_color_components = RGB_PIXELSIZE; + if (cinfo->jpeg_color_space == JCS_YCbCr) { + cconvert->pub.color_convert = ycc_rgb_convert; + build_ycc_rgb_table(cinfo); + } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) { + cconvert->pub.color_convert = gray_rgb_convert; + } else if (cinfo->jpeg_color_space == JCS_RGB && RGB_PIXELSIZE == 3) { + cconvert->pub.color_convert = null_convert; + } else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_CMYK: + cinfo->out_color_components = 4; + if (cinfo->jpeg_color_space == JCS_YCCK) { + cconvert->pub.color_convert = ycck_cmyk_convert; + build_ycc_rgb_table(cinfo); + } else if (cinfo->jpeg_color_space == JCS_CMYK) { + cconvert->pub.color_convert = null_convert; + } else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + default: + /* Permit null conversion to same output space */ + if (cinfo->out_color_space == cinfo->jpeg_color_space) { + cinfo->out_color_components = cinfo->num_components; + cconvert->pub.color_convert = null_convert; + } else /* unsupported non-null conversion */ + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + } + + if (cinfo->quantize_colors) + cinfo->output_components = 1; /* single colormapped output component */ + else + cinfo->output_components = cinfo->out_color_components; +} diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jdct.h b/lc-continuity/mk4/modimage/jpeg-6b/jdct.h new file mode 100644 index 0000000000000000000000000000000000000000..04192a266ae148072feecb5feff6bca796c2b71a --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jdct.h @@ -0,0 +1,176 @@ +/* + * jdct.h + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This include file contains common declarations for the forward and + * inverse DCT modules. These declarations are private to the DCT managers + * (jcdctmgr.c, jddctmgr.c) and the individual DCT algorithms. + * The individual DCT algorithms are kept in separate files to ease + * machine-dependent tuning (e.g., assembly coding). + */ + + +/* + * A forward DCT routine is given a pointer to a work area of type DCTELEM[]; + * the DCT is to be performed in-place in that buffer. Type DCTELEM is int + * for 8-bit samples, INT32 for 12-bit samples. (NOTE: Floating-point DCT + * implementations use an array of type FAST_FLOAT, instead.) + * The DCT inputs are expected to be signed (range +-CENTERJSAMPLE). + * The DCT outputs are returned scaled up by a factor of 8; they therefore + * have a range of +-8K for 8-bit data, +-128K for 12-bit data. This + * convention improves accuracy in integer implementations and saves some + * work in floating-point ones. + * Quantization of the output coefficients is done by jcdctmgr.c. + */ + +#if BITS_IN_JSAMPLE == 8 +typedef int DCTELEM; /* 16 or 32 bits is fine */ +#else +typedef INT32 DCTELEM; /* must have 32 bits */ +#endif + +typedef JMETHOD(void, forward_DCT_method_ptr, (DCTELEM * data)); +typedef JMETHOD(void, float_DCT_method_ptr, (FAST_FLOAT * data)); + + +/* + * An inverse DCT routine is given a pointer to the input JBLOCK and a pointer + * to an output sample array. The routine must dequantize the input data as + * well as perform the IDCT; for dequantization, it uses the multiplier table + * pointed to by compptr->dct_table. The output data is to be placed into the + * sample array starting at a specified column. (Any row offset needed will + * be applied to the array pointer before it is passed to the IDCT code.) + * Note that the number of samples emitted by the IDCT routine is + * DCT_scaled_size * DCT_scaled_size. + */ + +/* typedef inverse_DCT_method_ptr is declared in jpegint.h */ + +/* + * Each IDCT routine has its own ideas about the best dct_table element type. + */ + +typedef MULTIPLIER ISLOW_MULT_TYPE; /* short or int, whichever is faster */ +#if BITS_IN_JSAMPLE == 8 +typedef MULTIPLIER IFAST_MULT_TYPE; /* 16 bits is OK, use short if faster */ +#define IFAST_SCALE_BITS 2 /* fractional bits in scale factors */ +#else +typedef INT32 IFAST_MULT_TYPE; /* need 32 bits for scaled quantizers */ +#define IFAST_SCALE_BITS 13 /* fractional bits in scale factors */ +#endif +typedef FAST_FLOAT FLOAT_MULT_TYPE; /* preferred floating type */ + + +/* + * Each IDCT routine is responsible for range-limiting its results and + * converting them to unsigned form (0..MAXJSAMPLE). The raw outputs could + * be quite far out of range if the input data is corrupt, so a bulletproof + * range-limiting step is required. We use a mask-and-table-lookup method + * to do the combined operations quickly. See the comments with + * prepare_range_limit_table (in jdmaster.c) for more info. + */ + +#define IDCT_range_limit(cinfo) ((cinfo)->sample_range_limit + CENTERJSAMPLE) + +#define RANGE_MASK (MAXJSAMPLE * 4 + 3) /* 2 bits wider than legal samples */ + + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_fdct_islow jFDislow +#define jpeg_fdct_ifast jFDifast +#define jpeg_fdct_float jFDfloat +#define jpeg_idct_islow jRDislow +#define jpeg_idct_ifast jRDifast +#define jpeg_idct_float jRDfloat +#define jpeg_idct_4x4 jRD4x4 +#define jpeg_idct_2x2 jRD2x2 +#define jpeg_idct_1x1 jRD1x1 +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + +/* Extern declarations for the forward and inverse DCT routines. */ + +EXTERN(void) jpeg_fdct_islow JPP((DCTELEM * data)); +EXTERN(void) jpeg_fdct_ifast JPP((DCTELEM * data)); +EXTERN(void) jpeg_fdct_float JPP((FAST_FLOAT * data)); + +EXTERN(void) jpeg_idct_islow + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_ifast + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_float + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_4x4 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_2x2 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_1x1 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); + + +/* + * Macros for handling fixed-point arithmetic; these are used by many + * but not all of the DCT/IDCT modules. + * + * All values are expected to be of type INT32. + * Fractional constants are scaled left by CONST_BITS bits. + * CONST_BITS is defined within each module using these macros, + * and may differ from one module to the next. + */ + +#define ONE ((INT32) 1) +#define CONST_SCALE (ONE << CONST_BITS) + +/* Convert a positive real constant to an integer scaled by CONST_SCALE. + * Caution: some C compilers fail to reduce "FIX(constant)" at compile time, + * thus causing a lot of useless floating-point operations at run time. + */ + +#define FIX(x) ((INT32) ((x) * CONST_SCALE + 0.5)) + +/* Descale and correctly round an INT32 value that's scaled by N bits. + * We assume RIGHT_SHIFT rounds towards minus infinity, so adding + * the fudge factor is correct for either sign of X. + */ + +#define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n) + +/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. + * This macro is used only when the two inputs will actually be no more than + * 16 bits wide, so that a 16x16->32 bit multiply can be used instead of a + * full 32x32 multiply. This provides a useful speedup on many machines. + * Unfortunately there is no way to specify a 16x16->32 multiply portably + * in C, but some C compilers will do the right thing if you provide the + * correct combination of casts. + */ + +#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */ +#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT16) (const))) +#endif +#ifdef SHORTxLCONST_32 /* known to work with Microsoft C 6.0 */ +#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT32) (const))) +#endif + +#ifndef MULTIPLY16C16 /* default definition */ +#define MULTIPLY16C16(var,const) ((var) * (const)) +#endif + +/* Same except both inputs are variables. */ + +#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */ +#define MULTIPLY16V16(var1,var2) (((INT16) (var1)) * ((INT16) (var2))) +#endif + +#ifndef MULTIPLY16V16 /* default definition */ +#define MULTIPLY16V16(var1,var2) ((var1) * (var2)) +#endif diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jddctmgr.c b/lc-continuity/mk4/modimage/jpeg-6b/jddctmgr.c new file mode 100644 index 0000000000000000000000000000000000000000..bbf8d0e92fdd84ddaa0017a2df039d224a740898 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jddctmgr.c @@ -0,0 +1,269 @@ +/* + * jddctmgr.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the inverse-DCT management logic. + * This code selects a particular IDCT implementation to be used, + * and it performs related housekeeping chores. No code in this file + * is executed per IDCT step, only during output pass setup. + * + * Note that the IDCT routines are responsible for performing coefficient + * dequantization as well as the IDCT proper. This module sets up the + * dequantization multiplier table needed by the IDCT routine. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdct.h" /* Private declarations for DCT subsystem */ + + +/* + * The decompressor input side (jdinput.c) saves away the appropriate + * quantization table for each component at the start of the first scan + * involving that component. (This is necessary in order to correctly + * decode files that reuse Q-table slots.) + * When we are ready to make an output pass, the saved Q-table is converted + * to a multiplier table that will actually be used by the IDCT routine. + * The multiplier table contents are IDCT-method-dependent. To support + * application changes in IDCT method between scans, we can remake the + * multiplier tables if necessary. + * In buffered-image mode, the first output pass may occur before any data + * has been seen for some components, and thus before their Q-tables have + * been saved away. To handle this case, multiplier tables are preset + * to zeroes; the result of the IDCT will be a neutral gray level. + */ + + +/* Private subobject for this module */ + +typedef struct { + struct jpeg_inverse_dct pub; /* public fields */ + + /* This array contains the IDCT method code that each multiplier table + * is currently set up for, or -1 if it's not yet set up. + * The actual multiplier tables are pointed to by dct_table in the + * per-component comp_info structures. + */ + int cur_method[MAX_COMPONENTS]; +} my_idct_controller; + +typedef my_idct_controller * my_idct_ptr; + + +/* Allocated multiplier tables: big enough for any supported variant */ + +typedef union { + ISLOW_MULT_TYPE islow_array[DCTSIZE2]; +#ifdef DCT_IFAST_SUPPORTED + IFAST_MULT_TYPE ifast_array[DCTSIZE2]; +#endif +#ifdef DCT_FLOAT_SUPPORTED + FLOAT_MULT_TYPE float_array[DCTSIZE2]; +#endif +} multiplier_table; + + +/* The current scaled-IDCT routines require ISLOW-style multiplier tables, + * so be sure to compile that code if either ISLOW or SCALING is requested. + */ +#ifdef DCT_ISLOW_SUPPORTED +#define PROVIDE_ISLOW_TABLES +#else +#ifdef IDCT_SCALING_SUPPORTED +#define PROVIDE_ISLOW_TABLES +#endif +#endif + + +/* + * Prepare for an output pass. + * Here we select the proper IDCT routine for each component and build + * a matching multiplier table. + */ + +METHODDEF(void) +start_pass (j_decompress_ptr cinfo) +{ + my_idct_ptr idct = (my_idct_ptr) cinfo->idct; + int ci, i; + jpeg_component_info *compptr; + int method = 0; + inverse_DCT_method_ptr method_ptr = NULL; + JQUANT_TBL * qtbl; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Select the proper IDCT routine for this component's scaling */ + switch (compptr->DCT_scaled_size) { +#ifdef IDCT_SCALING_SUPPORTED + case 1: + method_ptr = jpeg_idct_1x1; + method = JDCT_ISLOW; /* jidctred uses islow-style table */ + break; + case 2: + method_ptr = jpeg_idct_2x2; + method = JDCT_ISLOW; /* jidctred uses islow-style table */ + break; + case 4: + method_ptr = jpeg_idct_4x4; + method = JDCT_ISLOW; /* jidctred uses islow-style table */ + break; +#endif + case DCTSIZE: + switch (cinfo->dct_method) { +#ifdef DCT_ISLOW_SUPPORTED + case JDCT_ISLOW: + method_ptr = jpeg_idct_islow; + method = JDCT_ISLOW; + break; +#endif +#ifdef DCT_IFAST_SUPPORTED + case JDCT_IFAST: + method_ptr = jpeg_idct_ifast; + method = JDCT_IFAST; + break; +#endif +#ifdef DCT_FLOAT_SUPPORTED + case JDCT_FLOAT: + method_ptr = jpeg_idct_float; + method = JDCT_FLOAT; + break; +#endif + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; + } + break; + default: + ERREXIT1(cinfo, JERR_BAD_DCTSIZE, compptr->DCT_scaled_size); + break; + } + idct->pub.inverse_DCT[ci] = method_ptr; + /* Create multiplier table from quant table. + * However, we can skip this if the component is uninteresting + * or if we already built the table. Also, if no quant table + * has yet been saved for the component, we leave the + * multiplier table all-zero; we'll be reading zeroes from the + * coefficient controller's buffer anyway. + */ + if (! compptr->component_needed || idct->cur_method[ci] == method) + continue; + qtbl = compptr->quant_table; + if (qtbl == NULL) /* happens if no data yet for component */ + continue; + idct->cur_method[ci] = method; + switch (method) { +#ifdef PROVIDE_ISLOW_TABLES + case JDCT_ISLOW: + { + /* For LL&M IDCT method, multipliers are equal to raw quantization + * coefficients, but are stored as ints to ensure access efficiency. + */ + ISLOW_MULT_TYPE * ismtbl = (ISLOW_MULT_TYPE *) compptr->dct_table; + for (i = 0; i < DCTSIZE2; i++) { + ismtbl[i] = (ISLOW_MULT_TYPE) qtbl->quantval[i]; + } + } + break; +#endif +#ifdef DCT_IFAST_SUPPORTED + case JDCT_IFAST: + { + /* For AA&N IDCT method, multipliers are equal to quantization + * coefficients scaled by scalefactor[row]*scalefactor[col], where + * scalefactor[0] = 1 + * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 + * For integer operation, the multiplier table is to be scaled by + * IFAST_SCALE_BITS. + */ + IFAST_MULT_TYPE * ifmtbl = (IFAST_MULT_TYPE *) compptr->dct_table; +#define CONST_BITS 14 + static const INT16 aanscales[DCTSIZE2] = { + /* precomputed values scaled up by 14 bits */ + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, + 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, + 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, + 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, + 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 + }; + SHIFT_TEMPS + + for (i = 0; i < DCTSIZE2; i++) { + ifmtbl[i] = (IFAST_MULT_TYPE) + DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i], + (INT32) aanscales[i]), + CONST_BITS-IFAST_SCALE_BITS); + } + } + break; +#endif +#ifdef DCT_FLOAT_SUPPORTED + case JDCT_FLOAT: + { + /* For float AA&N IDCT method, multipliers are equal to quantization + * coefficients scaled by scalefactor[row]*scalefactor[col], where + * scalefactor[0] = 1 + * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 + */ + FLOAT_MULT_TYPE * fmtbl = (FLOAT_MULT_TYPE *) compptr->dct_table; + int row, col; + static const double aanscalefactor[DCTSIZE] = { + 1.0, 1.387039845, 1.306562965, 1.175875602, + 1.0, 0.785694958, 0.541196100, 0.275899379 + }; + + i = 0; + for (row = 0; row < DCTSIZE; row++) { + for (col = 0; col < DCTSIZE; col++) { + fmtbl[i] = (FLOAT_MULT_TYPE) + ((double) qtbl->quantval[i] * + aanscalefactor[row] * aanscalefactor[col]); + i++; + } + } + } + break; +#endif + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; + } + } +} + + +/* + * Initialize IDCT manager. + */ + +GLOBAL(void) +jinit_inverse_dct (j_decompress_ptr cinfo) +{ + my_idct_ptr idct; + int ci; + jpeg_component_info *compptr; + + idct = (my_idct_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_idct_controller)); + cinfo->idct = (struct jpeg_inverse_dct *) idct; + idct->pub.start_pass = start_pass; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Allocate and pre-zero a multiplier table for each component */ + compptr->dct_table = + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(multiplier_table)); + MEMZERO(compptr->dct_table, SIZEOF(multiplier_table)); + /* Mark multiplier table not yet set up for any method */ + idct->cur_method[ci] = -1; + } +} diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jdhuff.c b/lc-continuity/mk4/modimage/jpeg-6b/jdhuff.c new file mode 100644 index 0000000000000000000000000000000000000000..b5ba39f736a7ae4f059d4b0594f4cc8ff854e1f4 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jdhuff.c @@ -0,0 +1,651 @@ +/* + * jdhuff.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains Huffman entropy decoding routines. + * + * Much of the complexity here has to do with supporting input suspension. + * If the data source module demands suspension, we want to be able to back + * up to the start of the current MCU. To do this, we copy state variables + * into local working storage, and update them back to the permanent + * storage only upon successful completion of an MCU. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdhuff.h" /* Declarations shared with jdphuff.c */ + + +/* + * Expanded entropy decoder object for Huffman decoding. + * + * The savable_state subrecord contains fields that change within an MCU, + * but must not be updated permanently until we complete the MCU. + */ + +typedef struct { + int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ +} savable_state; + +/* This macro is to work around compilers with missing or broken + * structure assignment. You'll need to fix this code if you have + * such a compiler and you change MAX_COMPS_IN_SCAN. + */ + +#ifndef NO_STRUCT_ASSIGN +#define ASSIGN_STATE(dest,src) ((dest) = (src)) +#else +#if MAX_COMPS_IN_SCAN == 4 +#define ASSIGN_STATE(dest,src) \ + ((dest).last_dc_val[0] = (src).last_dc_val[0], \ + (dest).last_dc_val[1] = (src).last_dc_val[1], \ + (dest).last_dc_val[2] = (src).last_dc_val[2], \ + (dest).last_dc_val[3] = (src).last_dc_val[3]) +#endif +#endif + + +typedef struct { + struct jpeg_entropy_decoder pub; /* public fields */ + + /* These fields are loaded into local variables at start of each MCU. + * In case of suspension, we exit WITHOUT updating them. + */ + bitread_perm_state bitstate; /* Bit buffer at start of MCU */ + savable_state saved; /* Other state at start of MCU */ + + /* These fields are NOT loaded into local working state. */ + unsigned int restarts_to_go; /* MCUs left in this restart interval */ + + /* Pointers to derived tables (these workspaces have image lifespan) */ + d_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS]; + d_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS]; + + /* Precalculated info set up by start_pass for use in decode_mcu: */ + + /* Pointers to derived tables to be used for each block within an MCU */ + d_derived_tbl * dc_cur_tbls[D_MAX_BLOCKS_IN_MCU]; + d_derived_tbl * ac_cur_tbls[D_MAX_BLOCKS_IN_MCU]; + /* Whether we care about the DC and AC coefficient values for each block */ + boolean dc_needed[D_MAX_BLOCKS_IN_MCU]; + boolean ac_needed[D_MAX_BLOCKS_IN_MCU]; +} huff_entropy_decoder; + +typedef huff_entropy_decoder * huff_entropy_ptr; + + +/* + * Initialize for a Huffman-compressed scan. + */ + +METHODDEF(void) +start_pass_huff_decoder (j_decompress_ptr cinfo) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + int ci, blkn, dctbl, actbl; + jpeg_component_info * compptr; + + /* Check that the scan parameters Ss, Se, Ah/Al are OK for sequential JPEG. + * This ought to be an error condition, but we make it a warning because + * there are some baseline files out there with all zeroes in these bytes. + */ + if (cinfo->Ss != 0 || cinfo->Se != DCTSIZE2-1 || + cinfo->Ah != 0 || cinfo->Al != 0) + WARNMS(cinfo, JWRN_NOT_SEQUENTIAL); + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + dctbl = compptr->dc_tbl_no; + actbl = compptr->ac_tbl_no; + /* Compute derived values for Huffman tables */ + /* We may do this more than once for a table, but it's not expensive */ + jpeg_make_d_derived_tbl(cinfo, TRUE, dctbl, + & entropy->dc_derived_tbls[dctbl]); + jpeg_make_d_derived_tbl(cinfo, FALSE, actbl, + & entropy->ac_derived_tbls[actbl]); + /* Initialize DC predictions to 0 */ + entropy->saved.last_dc_val[ci] = 0; + } + + /* Precalculate decoding info for each block in an MCU of this scan */ + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + /* Precalculate which table to use for each block */ + entropy->dc_cur_tbls[blkn] = entropy->dc_derived_tbls[compptr->dc_tbl_no]; + entropy->ac_cur_tbls[blkn] = entropy->ac_derived_tbls[compptr->ac_tbl_no]; + /* Decide whether we really care about the coefficient values */ + if (compptr->component_needed) { + entropy->dc_needed[blkn] = TRUE; + /* we don't need the ACs if producing a 1/8th-size image */ + entropy->ac_needed[blkn] = (compptr->DCT_scaled_size > 1); + } else { + entropy->dc_needed[blkn] = entropy->ac_needed[blkn] = FALSE; + } + } + + /* Initialize bitread state variables */ + entropy->bitstate.bits_left = 0; + entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */ + entropy->pub.insufficient_data = FALSE; + + /* Initialize restart counter */ + entropy->restarts_to_go = cinfo->restart_interval; +} + + +/* + * Compute the derived values for a Huffman table. + * This routine also performs some validation checks on the table. + * + * Note this is also used by jdphuff.c. + */ + +GLOBAL(void) +jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno, + d_derived_tbl ** pdtbl) +{ + JHUFF_TBL *htbl; + d_derived_tbl *dtbl; + int p, i, l, si, numsymbols; + int lookbits, ctr; + char huffsize[257]; + unsigned int huffcode[257]; + unsigned int code; + + /* Note that huffsize[] and huffcode[] are filled in code-length order, + * paralleling the order of the symbols themselves in htbl->huffval[]. + */ + + /* Find the input Huffman table */ + if (tblno < 0 || tblno >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); + htbl = + isDC ? cinfo->dc_huff_tbl_ptrs[tblno] : cinfo->ac_huff_tbl_ptrs[tblno]; + if (htbl == NULL) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); + + /* Allocate a workspace if we haven't already done so. */ + if (*pdtbl == NULL) + *pdtbl = (d_derived_tbl *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(d_derived_tbl)); + dtbl = *pdtbl; + dtbl->pub = htbl; /* fill in back link */ + + /* Figure C.1: make table of Huffman code length for each symbol */ + + p = 0; + for (l = 1; l <= 16; l++) { + i = (int) htbl->bits[l]; + if (i < 0 || p + i > 256) /* protect against table overrun */ + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + while (i--) + huffsize[p++] = (char) l; + } + huffsize[p] = 0; + numsymbols = p; + + /* Figure C.2: generate the codes themselves */ + /* We also validate that the counts represent a legal Huffman code tree. */ + + code = 0; + si = huffsize[0]; + p = 0; + while (huffsize[p]) { + while (((int) huffsize[p]) == si) { + huffcode[p++] = code; + code++; + } + /* code is now 1 more than the last code used for codelength si; but + * it must still fit in si bits, since no code is allowed to be all ones. + */ + if (((INT32) code) >= (((INT32) 1) << si)) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + code <<= 1; + si++; + } + + /* Figure F.15: generate decoding tables for bit-sequential decoding */ + + p = 0; + for (l = 1; l <= 16; l++) { + if (htbl->bits[l]) { + /* valoffset[l] = huffval[] index of 1st symbol of code length l, + * minus the minimum code of length l + */ + dtbl->valoffset[l] = (INT32) p - (INT32) huffcode[p]; + p += htbl->bits[l]; + dtbl->maxcode[l] = huffcode[p-1]; /* maximum code of length l */ + } else { + dtbl->maxcode[l] = -1; /* -1 if no codes of this length */ + } + } + dtbl->maxcode[17] = 0xFFFFFL; /* ensures jpeg_huff_decode terminates */ + + /* Compute lookahead tables to speed up decoding. + * First we set all the table entries to 0, indicating "too long"; + * then we iterate through the Huffman codes that are short enough and + * fill in all the entries that correspond to bit sequences starting + * with that code. + */ + + MEMZERO(dtbl->look_nbits, SIZEOF(dtbl->look_nbits)); + + p = 0; + for (l = 1; l <= HUFF_LOOKAHEAD; l++) { + for (i = 1; i <= (int) htbl->bits[l]; i++, p++) { + /* l = current code's length, p = its index in huffcode[] & huffval[]. */ + /* Generate left-justified code followed by all possible bit sequences */ + lookbits = huffcode[p] << (HUFF_LOOKAHEAD-l); + for (ctr = 1 << (HUFF_LOOKAHEAD-l); ctr > 0; ctr--) { + dtbl->look_nbits[lookbits] = l; + dtbl->look_sym[lookbits] = htbl->huffval[p]; + lookbits++; + } + } + } + + /* Validate symbols as being reasonable. + * For AC tables, we make no check, but accept all byte values 0..255. + * For DC tables, we require the symbols to be in range 0..15. + * (Tighter bounds could be applied depending on the data depth and mode, + * but this is sufficient to ensure safe decoding.) + */ + if (isDC) { + for (i = 0; i < numsymbols; i++) { + int sym = htbl->huffval[i]; + if (sym < 0 || sym > 15) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + } + } +} + + +/* + * Out-of-line code for bit fetching (shared with jdphuff.c). + * See jdhuff.h for info about usage. + * Note: current values of get_buffer and bits_left are passed as parameters, + * but are returned in the corresponding fields of the state struct. + * + * On most machines MIN_GET_BITS should be 25 to allow the full 32-bit width + * of get_buffer to be used. (On machines with wider words, an even larger + * buffer could be used.) However, on some machines 32-bit shifts are + * quite slow and take time proportional to the number of places shifted. + * (This is true with most PC compilers, for instance.) In this case it may + * be a win to set MIN_GET_BITS to the minimum value of 15. This reduces the + * average shift distance at the cost of more calls to jpeg_fill_bit_buffer. + */ + +#ifdef SLOW_SHIFT_32 +#define MIN_GET_BITS 15 /* minimum allowable value */ +#else +#define MIN_GET_BITS (BIT_BUF_SIZE-7) +#endif + + +GLOBAL(boolean) +jpeg_fill_bit_buffer (bitread_working_state * state, + register bit_buf_type get_buffer, register int bits_left, + int nbits) +/* Load up the bit buffer to a depth of at least nbits */ +{ + /* Copy heavily used state fields into locals (hopefully registers) */ + register const JOCTET * next_input_byte = state->next_input_byte; + register size_t bytes_in_buffer = state->bytes_in_buffer; + j_decompress_ptr cinfo = state->cinfo; + + /* Attempt to load at least MIN_GET_BITS bits into get_buffer. */ + /* (It is assumed that no request will be for more than that many bits.) */ + /* We fail to do so only if we hit a marker or are forced to suspend. */ + + if (cinfo->unread_marker == 0) { /* cannot advance past a marker */ + while (bits_left < MIN_GET_BITS) { + register int c; + + /* Attempt to read a byte */ + if (bytes_in_buffer == 0) { + if (! (*cinfo->src->fill_input_buffer) (cinfo)) + return FALSE; + next_input_byte = cinfo->src->next_input_byte; + bytes_in_buffer = cinfo->src->bytes_in_buffer; + } + bytes_in_buffer--; + c = GETJOCTET(*next_input_byte++); + + /* If it's 0xFF, check and discard stuffed zero byte */ + if (c == 0xFF) { + /* Loop here to discard any padding FF's on terminating marker, + * so that we can save a valid unread_marker value. NOTE: we will + * accept multiple FF's followed by a 0 as meaning a single FF data + * byte. This data pattern is not valid according to the standard. + */ + do { + if (bytes_in_buffer == 0) { + if (! (*cinfo->src->fill_input_buffer) (cinfo)) + return FALSE; + next_input_byte = cinfo->src->next_input_byte; + bytes_in_buffer = cinfo->src->bytes_in_buffer; + } + bytes_in_buffer--; + c = GETJOCTET(*next_input_byte++); + } while (c == 0xFF); + + if (c == 0) { + /* Found FF/00, which represents an FF data byte */ + c = 0xFF; + } else { + /* Oops, it's actually a marker indicating end of compressed data. + * Save the marker code for later use. + * Fine point: it might appear that we should save the marker into + * bitread working state, not straight into permanent state. But + * once we have hit a marker, we cannot need to suspend within the + * current MCU, because we will read no more bytes from the data + * source. So it is OK to update permanent state right away. + */ + cinfo->unread_marker = c; + /* See if we need to insert some fake zero bits. */ + goto no_more_bytes; + } + } + + /* OK, load c into get_buffer */ + get_buffer = (get_buffer << 8) | c; + bits_left += 8; + } /* end while */ + } else { + no_more_bytes: + /* We get here if we've read the marker that terminates the compressed + * data segment. There should be enough bits in the buffer register + * to satisfy the request; if so, no problem. + */ + if (nbits > bits_left) { + /* Uh-oh. Report corrupted data to user and stuff zeroes into + * the data stream, so that we can produce some kind of image. + * We use a nonvolatile flag to ensure that only one warning message + * appears per data segment. + */ + if (! cinfo->entropy->insufficient_data) { + WARNMS(cinfo, JWRN_HIT_MARKER); + cinfo->entropy->insufficient_data = TRUE; + } + /* Fill the buffer with zero bits */ + get_buffer <<= MIN_GET_BITS - bits_left; + bits_left = MIN_GET_BITS; + } + } + + /* Unload the local registers */ + state->next_input_byte = next_input_byte; + state->bytes_in_buffer = bytes_in_buffer; + state->get_buffer = get_buffer; + state->bits_left = bits_left; + + return TRUE; +} + + +/* + * Out-of-line code for Huffman code decoding. + * See jdhuff.h for info about usage. + */ + +GLOBAL(int) +jpeg_huff_decode (bitread_working_state * state, + register bit_buf_type get_buffer, register int bits_left, + d_derived_tbl * htbl, int min_bits) +{ + register int l = min_bits; + register INT32 code; + + /* HUFF_DECODE has determined that the code is at least min_bits */ + /* bits long, so fetch that many bits in one swoop. */ + + CHECK_BIT_BUFFER(*state, l, return -1); + code = GET_BITS(l); + + /* Collect the rest of the Huffman code one bit at a time. */ + /* This is per Figure F.16 in the JPEG spec. */ + + while (code > htbl->maxcode[l]) { + code <<= 1; + CHECK_BIT_BUFFER(*state, 1, return -1); + code |= GET_BITS(1); + l++; + } + + /* Unload the local registers */ + state->get_buffer = get_buffer; + state->bits_left = bits_left; + + /* With garbage input we may reach the sentinel value l = 17. */ + + if (l > 16) { + WARNMS(state->cinfo, JWRN_HUFF_BAD_CODE); + return 0; /* fake a zero as the safest result */ + } + + return htbl->pub->huffval[ (int) (code + htbl->valoffset[l]) ]; +} + + +/* + * Figure F.12: extend sign bit. + * On some machines, a shift and add will be faster than a table lookup. + */ + +#ifdef AVOID_TABLES + +#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x)) + +#else + +#define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x)) + +static const int extend_test[16] = /* entry n is 2**(n-1) */ + { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, + 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 }; + +static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */ + { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1, + ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1, + ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1, + ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 }; + +#endif /* AVOID_TABLES */ + + +/* + * Check for a restart marker & resynchronize decoder. + * Returns FALSE if must suspend. + */ + +LOCAL(boolean) +process_restart (j_decompress_ptr cinfo) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + int ci; + + /* Throw away any unused bits remaining in bit buffer; */ + /* include any full bytes in next_marker's count of discarded bytes */ + cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8; + entropy->bitstate.bits_left = 0; + + /* Advance past the RSTn marker */ + if (! (*cinfo->marker->read_restart_marker) (cinfo)) + return FALSE; + + /* Re-initialize DC predictions to 0 */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) + entropy->saved.last_dc_val[ci] = 0; + + /* Reset restart counter */ + entropy->restarts_to_go = cinfo->restart_interval; + + /* Reset out-of-data flag, unless read_restart_marker left us smack up + * against a marker. In that case we will end up treating the next data + * segment as empty, and we can avoid producing bogus output pixels by + * leaving the flag set. + */ + if (cinfo->unread_marker == 0) + entropy->pub.insufficient_data = FALSE; + + return TRUE; +} + + +/* + * Decode and return one MCU's worth of Huffman-compressed coefficients. + * The coefficients are reordered from zigzag order into natural array order, + * but are not dequantized. + * + * The i'th block of the MCU is stored into the block pointed to by + * MCU_data[i]. WE ASSUME THIS AREA HAS BEEN ZEROED BY THE CALLER. + * (Wholesale zeroing is usually a little faster than retail...) + * + * Returns FALSE if data source requested suspension. In that case no + * changes have been made to permanent state. (Exception: some output + * coefficients may already have been assigned. This is harmless for + * this module, since we'll just re-assign them on the next call.) + */ + +METHODDEF(boolean) +decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + int blkn; + BITREAD_STATE_VARS; + savable_state state; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* If we've run out of data, just leave the MCU set to zeroes. + * This way, we return uniform gray for the remainder of the segment. + */ + if (! entropy->pub.insufficient_data) { + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(state, entropy->saved); + + /* Outer loop handles each block in the MCU */ + + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + JBLOCKROW block = MCU_data[blkn]; + d_derived_tbl * dctbl = entropy->dc_cur_tbls[blkn]; + d_derived_tbl * actbl = entropy->ac_cur_tbls[blkn]; + register int s, k, r; + + /* Decode a single block's worth of coefficients */ + + /* Section F.2.2.1: decode the DC coefficient difference */ + HUFF_DECODE(s, br_state, dctbl, return FALSE, label1); + if (s) { + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + } + + if (entropy->dc_needed[blkn]) { + /* Convert DC difference to actual value, update last_dc_val */ + int ci = cinfo->MCU_membership[blkn]; + s += state.last_dc_val[ci]; + state.last_dc_val[ci] = s; + /* Output the DC coefficient (assumes jpeg_natural_order[0] = 0) */ + (*block)[0] = (JCOEF) s; + } + + if (entropy->ac_needed[blkn]) { + + /* Section F.2.2.2: decode the AC coefficients */ + /* Since zeroes are skipped, output area must be cleared beforehand */ + for (k = 1; k < DCTSIZE2; k++) { + HUFF_DECODE(s, br_state, actbl, return FALSE, label2); + + r = s >> 4; + s &= 15; + + if (s) { + k += r; + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + /* Output coefficient in natural (dezigzagged) order. + * Note: the extra entries in jpeg_natural_order[] will save us + * if k >= DCTSIZE2, which could happen if the data is corrupted. + */ + (*block)[jpeg_natural_order[k]] = (JCOEF) s; + } else { + if (r != 15) + break; + k += 15; + } + } + + } else { + + /* Section F.2.2.2: decode the AC coefficients */ + /* In this path we just discard the values */ + for (k = 1; k < DCTSIZE2; k++) { + HUFF_DECODE(s, br_state, actbl, return FALSE, label3); + + r = s >> 4; + s &= 15; + + if (s) { + k += r; + CHECK_BIT_BUFFER(br_state, s, return FALSE); + DROP_BITS(s); + } else { + if (r != 15) + break; + k += 15; + } + } + + } + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(entropy->saved, state); + } + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; +} + + +/* + * Module initialization routine for Huffman entropy decoding. + */ + +GLOBAL(void) +jinit_huff_decoder (j_decompress_ptr cinfo) +{ + huff_entropy_ptr entropy; + int i; + + entropy = (huff_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(huff_entropy_decoder)); + cinfo->entropy = (struct jpeg_entropy_decoder *) entropy; + entropy->pub.start_pass = start_pass_huff_decoder; + entropy->pub.decode_mcu = decode_mcu; + + /* Mark tables unallocated */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL; + } +} diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jdhuff.h b/lc-continuity/mk4/modimage/jpeg-6b/jdhuff.h new file mode 100644 index 0000000000000000000000000000000000000000..ae19b6cafd7e81f94499d92876a6cf88bcafda86 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jdhuff.h @@ -0,0 +1,201 @@ +/* + * jdhuff.h + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains declarations for Huffman entropy decoding routines + * that are shared between the sequential decoder (jdhuff.c) and the + * progressive decoder (jdphuff.c). No other modules need to see these. + */ + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_make_d_derived_tbl jMkDDerived +#define jpeg_fill_bit_buffer jFilBitBuf +#define jpeg_huff_decode jHufDecode +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* Derived data constructed for each Huffman table */ + +#define HUFF_LOOKAHEAD 8 /* # of bits of lookahead */ + +typedef struct { + /* Basic tables: (element [0] of each array is unused) */ + INT32 maxcode[18]; /* largest code of length k (-1 if none) */ + /* (maxcode[17] is a sentinel to ensure jpeg_huff_decode terminates) */ + INT32 valoffset[17]; /* huffval[] offset for codes of length k */ + /* valoffset[k] = huffval[] index of 1st symbol of code length k, less + * the smallest code of length k; so given a code of length k, the + * corresponding symbol is huffval[code + valoffset[k]] + */ + + /* Link to public Huffman table (needed only in jpeg_huff_decode) */ + JHUFF_TBL *pub; + + /* Lookahead tables: indexed by the next HUFF_LOOKAHEAD bits of + * the input data stream. If the next Huffman code is no more + * than HUFF_LOOKAHEAD bits long, we can obtain its length and + * the corresponding symbol directly from these tables. + */ + int look_nbits[1< 32 bits on your machine, and shifting/masking longs is + * reasonably fast, making bit_buf_type be long and setting BIT_BUF_SIZE + * appropriately should be a win. Unfortunately we can't define the size + * with something like #define BIT_BUF_SIZE (sizeof(bit_buf_type)*8) + * because not all machines measure sizeof in 8-bit bytes. + */ + +typedef struct { /* Bitreading state saved across MCUs */ + bit_buf_type get_buffer; /* current bit-extraction buffer */ + int bits_left; /* # of unused bits in it */ +} bitread_perm_state; + +typedef struct { /* Bitreading working state within an MCU */ + /* Current data source location */ + /* We need a copy, rather than munging the original, in case of suspension */ + const JOCTET * next_input_byte; /* => next byte to read from source */ + size_t bytes_in_buffer; /* # of bytes remaining in source buffer */ + /* Bit input buffer --- note these values are kept in register variables, + * not in this struct, inside the inner loops. + */ + bit_buf_type get_buffer; /* current bit-extraction buffer */ + int bits_left; /* # of unused bits in it */ + /* Pointer needed by jpeg_fill_bit_buffer. */ + j_decompress_ptr cinfo; /* back link to decompress master record */ +} bitread_working_state; + +/* Macros to declare and load/save bitread local variables. */ +#define BITREAD_STATE_VARS \ + register bit_buf_type get_buffer; \ + register int bits_left; \ + bitread_working_state br_state + +#define BITREAD_LOAD_STATE(cinfop,permstate) \ + br_state.cinfo = cinfop; \ + br_state.next_input_byte = cinfop->src->next_input_byte; \ + br_state.bytes_in_buffer = cinfop->src->bytes_in_buffer; \ + get_buffer = permstate.get_buffer; \ + bits_left = permstate.bits_left; + +#define BITREAD_SAVE_STATE(cinfop,permstate) \ + cinfop->src->next_input_byte = br_state.next_input_byte; \ + cinfop->src->bytes_in_buffer = br_state.bytes_in_buffer; \ + permstate.get_buffer = get_buffer; \ + permstate.bits_left = bits_left + +/* + * These macros provide the in-line portion of bit fetching. + * Use CHECK_BIT_BUFFER to ensure there are N bits in get_buffer + * before using GET_BITS, PEEK_BITS, or DROP_BITS. + * The variables get_buffer and bits_left are assumed to be locals, + * but the state struct might not be (jpeg_huff_decode needs this). + * CHECK_BIT_BUFFER(state,n,action); + * Ensure there are N bits in get_buffer; if suspend, take action. + * val = GET_BITS(n); + * Fetch next N bits. + * val = PEEK_BITS(n); + * Fetch next N bits without removing them from the buffer. + * DROP_BITS(n); + * Discard next N bits. + * The value N should be a simple variable, not an expression, because it + * is evaluated multiple times. + */ + +#define CHECK_BIT_BUFFER(state,nbits,action) \ + { if (bits_left < (nbits)) { \ + if (! jpeg_fill_bit_buffer(&(state),get_buffer,bits_left,nbits)) \ + { action; } \ + get_buffer = (state).get_buffer; bits_left = (state).bits_left; } } + +#define GET_BITS(nbits) \ + (((int) (get_buffer >> (bits_left -= (nbits)))) & ((1<<(nbits))-1)) + +#define PEEK_BITS(nbits) \ + (((int) (get_buffer >> (bits_left - (nbits)))) & ((1<<(nbits))-1)) + +#define DROP_BITS(nbits) \ + (bits_left -= (nbits)) + +/* Load up the bit buffer to a depth of at least nbits */ +EXTERN(boolean) jpeg_fill_bit_buffer + JPP((bitread_working_state * state, register bit_buf_type get_buffer, + register int bits_left, int nbits)); + + +/* + * Code for extracting next Huffman-coded symbol from input bit stream. + * Again, this is time-critical and we make the main paths be macros. + * + * We use a lookahead table to process codes of up to HUFF_LOOKAHEAD bits + * without looping. Usually, more than 95% of the Huffman codes will be 8 + * or fewer bits long. The few overlength codes are handled with a loop, + * which need not be inline code. + * + * Notes about the HUFF_DECODE macro: + * 1. Near the end of the data segment, we may fail to get enough bits + * for a lookahead. In that case, we do it the hard way. + * 2. If the lookahead table contains no entry, the next code must be + * more than HUFF_LOOKAHEAD bits long. + * 3. jpeg_huff_decode returns -1 if forced to suspend. + */ + +#define HUFF_DECODE(result,state,htbl,failaction,slowlabel) \ +{ register int nb, look; \ + if (bits_left < HUFF_LOOKAHEAD) { \ + if (! jpeg_fill_bit_buffer(&state,get_buffer,bits_left, 0)) {failaction;} \ + get_buffer = state.get_buffer; bits_left = state.bits_left; \ + if (bits_left < HUFF_LOOKAHEAD) { \ + nb = 1; goto slowlabel; \ + } \ + } \ + look = PEEK_BITS(HUFF_LOOKAHEAD); \ + if ((nb = htbl->look_nbits[look]) != 0) { \ + DROP_BITS(nb); \ + result = htbl->look_sym[look]; \ + } else { \ + nb = HUFF_LOOKAHEAD+1; \ +slowlabel: \ + if ((result=jpeg_huff_decode(&state,get_buffer,bits_left,htbl,nb)) < 0) \ + { failaction; } \ + get_buffer = state.get_buffer; bits_left = state.bits_left; \ + } \ +} + +/* Out-of-line case for Huffman code fetching */ +EXTERN(int) jpeg_huff_decode + JPP((bitread_working_state * state, register bit_buf_type get_buffer, + register int bits_left, d_derived_tbl * htbl, int min_bits)); diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jdinput.c b/lc-continuity/mk4/modimage/jpeg-6b/jdinput.c new file mode 100644 index 0000000000000000000000000000000000000000..0c2ac8f120bca16bff13b989d8879ac9db85a011 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jdinput.c @@ -0,0 +1,381 @@ +/* + * jdinput.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains input control logic for the JPEG decompressor. + * These routines are concerned with controlling the decompressor's input + * processing (marker reading and coefficient decoding). The actual input + * reading is done in jdmarker.c, jdhuff.c, and jdphuff.c. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Private state */ + +typedef struct { + struct jpeg_input_controller pub; /* public fields */ + + boolean inheaders; /* TRUE until first SOS is reached */ +} my_input_controller; + +typedef my_input_controller * my_inputctl_ptr; + + +/* Forward declarations */ +METHODDEF(int) consume_markers JPP((j_decompress_ptr cinfo)); + + +/* + * Routines to calculate various quantities related to the size of the image. + */ + +LOCAL(void) +initial_setup (j_decompress_ptr cinfo) +/* Called once, when first SOS marker is reached */ +{ + int ci; + jpeg_component_info *compptr; + + /* Make sure image isn't bigger than I can handle */ + if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION || + (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION) + ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION); + + /* For now, precision must match compiled-in value... */ + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + + /* Check that number of components won't exceed internal array sizes */ + if (cinfo->num_components > MAX_COMPONENTS) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, + MAX_COMPONENTS); + + /* Compute maximum sampling factors; check factor validity */ + cinfo->max_h_samp_factor = 1; + cinfo->max_v_samp_factor = 1; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR || + compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR) + ERREXIT(cinfo, JERR_BAD_SAMPLING); + cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor, + compptr->h_samp_factor); + cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor, + compptr->v_samp_factor); + } + + /* We initialize DCT_scaled_size and min_DCT_scaled_size to DCTSIZE. + * In the full decompressor, this will be overridden by jdmaster.c; + * but in the transcoder, jdmaster.c is not used, so we must do it here. + */ + cinfo->min_DCT_scaled_size = DCTSIZE; + + /* Compute dimensions of components */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + compptr->DCT_scaled_size = DCTSIZE; + /* Size in DCT blocks */ + compptr->width_in_blocks = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, + (long) (cinfo->max_h_samp_factor * DCTSIZE)); + compptr->height_in_blocks = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, + (long) (cinfo->max_v_samp_factor * DCTSIZE)); + /* downsampled_width and downsampled_height will also be overridden by + * jdmaster.c if we are doing full decompression. The transcoder library + * doesn't use these values, but the calling application might. + */ + /* Size in samples */ + compptr->downsampled_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, + (long) cinfo->max_h_samp_factor); + compptr->downsampled_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, + (long) cinfo->max_v_samp_factor); + /* Mark component needed, until color conversion says otherwise */ + compptr->component_needed = TRUE; + /* Mark no quantization table yet saved for component */ + compptr->quant_table = NULL; + } + + /* Compute number of fully interleaved MCU rows. */ + cinfo->total_iMCU_rows = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, + (long) (cinfo->max_v_samp_factor*DCTSIZE)); + + /* Decide whether file contains multiple scans */ + if (cinfo->comps_in_scan < cinfo->num_components || cinfo->progressive_mode) + cinfo->inputctl->has_multiple_scans = TRUE; + else + cinfo->inputctl->has_multiple_scans = FALSE; +} + + +LOCAL(void) +per_scan_setup (j_decompress_ptr cinfo) +/* Do computations that are needed before processing a JPEG scan */ +/* cinfo->comps_in_scan and cinfo->cur_comp_info[] were set from SOS marker */ +{ + int ci, mcublks, tmp; + jpeg_component_info *compptr; + + if (cinfo->comps_in_scan == 1) { + + /* Noninterleaved (single-component) scan */ + compptr = cinfo->cur_comp_info[0]; + + /* Overall image size in MCUs */ + cinfo->MCUs_per_row = compptr->width_in_blocks; + cinfo->MCU_rows_in_scan = compptr->height_in_blocks; + + /* For noninterleaved scan, always one block per MCU */ + compptr->MCU_width = 1; + compptr->MCU_height = 1; + compptr->MCU_blocks = 1; + compptr->MCU_sample_width = compptr->DCT_scaled_size; + compptr->last_col_width = 1; + /* For noninterleaved scans, it is convenient to define last_row_height + * as the number of block rows present in the last iMCU row. + */ + tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor); + if (tmp == 0) tmp = compptr->v_samp_factor; + compptr->last_row_height = tmp; + + /* Prepare array describing MCU composition */ + cinfo->blocks_in_MCU = 1; + cinfo->MCU_membership[0] = 0; + + } else { + + /* Interleaved (multi-component) scan */ + if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan, + MAX_COMPS_IN_SCAN); + + /* Overall image size in MCUs */ + cinfo->MCUs_per_row = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, + (long) (cinfo->max_h_samp_factor*DCTSIZE)); + cinfo->MCU_rows_in_scan = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, + (long) (cinfo->max_v_samp_factor*DCTSIZE)); + + cinfo->blocks_in_MCU = 0; + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* Sampling factors give # of blocks of component in each MCU */ + compptr->MCU_width = compptr->h_samp_factor; + compptr->MCU_height = compptr->v_samp_factor; + compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height; + compptr->MCU_sample_width = compptr->MCU_width * compptr->DCT_scaled_size; + /* Figure number of non-dummy blocks in last MCU column & row */ + tmp = (int) (compptr->width_in_blocks % compptr->MCU_width); + if (tmp == 0) tmp = compptr->MCU_width; + compptr->last_col_width = tmp; + tmp = (int) (compptr->height_in_blocks % compptr->MCU_height); + if (tmp == 0) tmp = compptr->MCU_height; + compptr->last_row_height = tmp; + /* Prepare array describing MCU composition */ + mcublks = compptr->MCU_blocks; + if (cinfo->blocks_in_MCU + mcublks > D_MAX_BLOCKS_IN_MCU) + ERREXIT(cinfo, JERR_BAD_MCU_SIZE); + while (mcublks-- > 0) { + cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci; + } + } + + } +} + + +/* + * Save away a copy of the Q-table referenced by each component present + * in the current scan, unless already saved during a prior scan. + * + * In a multiple-scan JPEG file, the encoder could assign different components + * the same Q-table slot number, but change table definitions between scans + * so that each component uses a different Q-table. (The IJG encoder is not + * currently capable of doing this, but other encoders might.) Since we want + * to be able to dequantize all the components at the end of the file, this + * means that we have to save away the table actually used for each component. + * We do this by copying the table at the start of the first scan containing + * the component. + * The JPEG spec prohibits the encoder from changing the contents of a Q-table + * slot between scans of a component using that slot. If the encoder does so + * anyway, this decoder will simply use the Q-table values that were current + * at the start of the first scan for the component. + * + * The decompressor output side looks only at the saved quant tables, + * not at the current Q-table slots. + */ + +LOCAL(void) +latch_quant_tables (j_decompress_ptr cinfo) +{ + int ci, qtblno; + jpeg_component_info *compptr; + JQUANT_TBL * qtbl; + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* No work if we already saved Q-table for this component */ + if (compptr->quant_table != NULL) + continue; + /* Make sure specified quantization table is present */ + qtblno = compptr->quant_tbl_no; + if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || + cinfo->quant_tbl_ptrs[qtblno] == NULL) + ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno); + /* OK, save away the quantization table */ + qtbl = (JQUANT_TBL *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(JQUANT_TBL)); + MEMCOPY(qtbl, cinfo->quant_tbl_ptrs[qtblno], SIZEOF(JQUANT_TBL)); + compptr->quant_table = qtbl; + } +} + + +/* + * Initialize the input modules to read a scan of compressed data. + * The first call to this is done by jdmaster.c after initializing + * the entire decompressor (during jpeg_start_decompress). + * Subsequent calls come from consume_markers, below. + */ + +METHODDEF(void) +start_input_pass (j_decompress_ptr cinfo) +{ + per_scan_setup(cinfo); + latch_quant_tables(cinfo); + (*cinfo->entropy->start_pass) (cinfo); + (*cinfo->coef->start_input_pass) (cinfo); + cinfo->inputctl->consume_input = cinfo->coef->consume_data; +} + + +/* + * Finish up after inputting a compressed-data scan. + * This is called by the coefficient controller after it's read all + * the expected data of the scan. + */ + +METHODDEF(void) +finish_input_pass (j_decompress_ptr cinfo) +{ + cinfo->inputctl->consume_input = consume_markers; +} + + +/* + * Read JPEG markers before, between, or after compressed-data scans. + * Change state as necessary when a new scan is reached. + * Return value is JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. + * + * The consume_input method pointer points either here or to the + * coefficient controller's consume_data routine, depending on whether + * we are reading a compressed data segment or inter-segment markers. + */ + +METHODDEF(int) +consume_markers (j_decompress_ptr cinfo) +{ + my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl; + int val; + + if (inputctl->pub.eoi_reached) /* After hitting EOI, read no further */ + return JPEG_REACHED_EOI; + + val = (*cinfo->marker->read_markers) (cinfo); + + switch (val) { + case JPEG_REACHED_SOS: /* Found SOS */ + if (inputctl->inheaders) { /* 1st SOS */ + initial_setup(cinfo); + inputctl->inheaders = FALSE; + /* Note: start_input_pass must be called by jdmaster.c + * before any more input can be consumed. jdapimin.c is + * responsible for enforcing this sequencing. + */ + } else { /* 2nd or later SOS marker */ + if (! inputctl->pub.has_multiple_scans) + ERREXIT(cinfo, JERR_EOI_EXPECTED); /* Oops, I wasn't expecting this! */ + start_input_pass(cinfo); + } + break; + case JPEG_REACHED_EOI: /* Found EOI */ + inputctl->pub.eoi_reached = TRUE; + if (inputctl->inheaders) { /* Tables-only datastream, apparently */ + if (cinfo->marker->saw_SOF) + ERREXIT(cinfo, JERR_SOF_NO_SOS); + } else { + /* Prevent infinite loop in coef ctlr's decompress_data routine + * if user set output_scan_number larger than number of scans. + */ + if (cinfo->output_scan_number > cinfo->input_scan_number) + cinfo->output_scan_number = cinfo->input_scan_number; + } + break; + case JPEG_SUSPENDED: + break; + } + + return val; +} + + +/* + * Reset state to begin a fresh datastream. + */ + +METHODDEF(void) +reset_input_controller (j_decompress_ptr cinfo) +{ + my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl; + + inputctl->pub.consume_input = consume_markers; + inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */ + inputctl->pub.eoi_reached = FALSE; + inputctl->inheaders = TRUE; + /* Reset other modules */ + (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); + (*cinfo->marker->reset_marker_reader) (cinfo); + /* Reset progression state -- would be cleaner if entropy decoder did this */ + cinfo->coef_bits = NULL; +} + + +/* + * Initialize the input controller module. + * This is called only once, when the decompression object is created. + */ + +GLOBAL(void) +jinit_input_controller (j_decompress_ptr cinfo) +{ + my_inputctl_ptr inputctl; + + /* Create subobject in permanent pool */ + inputctl = (my_inputctl_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(my_input_controller)); + cinfo->inputctl = (struct jpeg_input_controller *) inputctl; + /* Initialize method pointers */ + inputctl->pub.consume_input = consume_markers; + inputctl->pub.reset_input_controller = reset_input_controller; + inputctl->pub.start_input_pass = start_input_pass; + inputctl->pub.finish_input_pass = finish_input_pass; + /* Initialize state: can't use reset_input_controller since we don't + * want to try to reset other modules yet. + */ + inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */ + inputctl->pub.eoi_reached = FALSE; + inputctl->inheaders = TRUE; +} diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jdmainct.c b/lc-continuity/mk4/modimage/jpeg-6b/jdmainct.c new file mode 100644 index 0000000000000000000000000000000000000000..13c956f5deb7da999d6d22c0bc25b81751b96815 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jdmainct.c @@ -0,0 +1,512 @@ +/* + * jdmainct.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the main buffer controller for decompression. + * The main buffer lies between the JPEG decompressor proper and the + * post-processor; it holds downsampled data in the JPEG colorspace. + * + * Note that this code is bypassed in raw-data mode, since the application + * supplies the equivalent of the main buffer in that case. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* + * In the current system design, the main buffer need never be a full-image + * buffer; any full-height buffers will be found inside the coefficient or + * postprocessing controllers. Nonetheless, the main controller is not + * trivial. Its responsibility is to provide context rows for upsampling/ + * rescaling, and doing this in an efficient fashion is a bit tricky. + * + * Postprocessor input data is counted in "row groups". A row group + * is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size) + * sample rows of each component. (We require DCT_scaled_size values to be + * chosen such that these numbers are integers. In practice DCT_scaled_size + * values will likely be powers of two, so we actually have the stronger + * condition that DCT_scaled_size / min_DCT_scaled_size is an integer.) + * Upsampling will typically produce max_v_samp_factor pixel rows from each + * row group (times any additional scale factor that the upsampler is + * applying). + * + * The coefficient controller will deliver data to us one iMCU row at a time; + * each iMCU row contains v_samp_factor * DCT_scaled_size sample rows, or + * exactly min_DCT_scaled_size row groups. (This amount of data corresponds + * to one row of MCUs when the image is fully interleaved.) Note that the + * number of sample rows varies across components, but the number of row + * groups does not. Some garbage sample rows may be included in the last iMCU + * row at the bottom of the image. + * + * Depending on the vertical scaling algorithm used, the upsampler may need + * access to the sample row(s) above and below its current input row group. + * The upsampler is required to set need_context_rows TRUE at global selection + * time if so. When need_context_rows is FALSE, this controller can simply + * obtain one iMCU row at a time from the coefficient controller and dole it + * out as row groups to the postprocessor. + * + * When need_context_rows is TRUE, this controller guarantees that the buffer + * passed to postprocessing contains at least one row group's worth of samples + * above and below the row group(s) being processed. Note that the context + * rows "above" the first passed row group appear at negative row offsets in + * the passed buffer. At the top and bottom of the image, the required + * context rows are manufactured by duplicating the first or last real sample + * row; this avoids having special cases in the upsampling inner loops. + * + * The amount of context is fixed at one row group just because that's a + * convenient number for this controller to work with. The existing + * upsamplers really only need one sample row of context. An upsampler + * supporting arbitrary output rescaling might wish for more than one row + * group of context when shrinking the image; tough, we don't handle that. + * (This is justified by the assumption that downsizing will be handled mostly + * by adjusting the DCT_scaled_size values, so that the actual scale factor at + * the upsample step needn't be much less than one.) + * + * To provide the desired context, we have to retain the last two row groups + * of one iMCU row while reading in the next iMCU row. (The last row group + * can't be processed until we have another row group for its below-context, + * and so we have to save the next-to-last group too for its above-context.) + * We could do this most simply by copying data around in our buffer, but + * that'd be very slow. We can avoid copying any data by creating a rather + * strange pointer structure. Here's how it works. We allocate a workspace + * consisting of M+2 row groups (where M = min_DCT_scaled_size is the number + * of row groups per iMCU row). We create two sets of redundant pointers to + * the workspace. Labeling the physical row groups 0 to M+1, the synthesized + * pointer lists look like this: + * M+1 M-1 + * master pointer --> 0 master pointer --> 0 + * 1 1 + * ... ... + * M-3 M-3 + * M-2 M + * M-1 M+1 + * M M-2 + * M+1 M-1 + * 0 0 + * We read alternate iMCU rows using each master pointer; thus the last two + * row groups of the previous iMCU row remain un-overwritten in the workspace. + * The pointer lists are set up so that the required context rows appear to + * be adjacent to the proper places when we pass the pointer lists to the + * upsampler. + * + * The above pictures describe the normal state of the pointer lists. + * At top and bottom of the image, we diddle the pointer lists to duplicate + * the first or last sample row as necessary (this is cheaper than copying + * sample rows around). + * + * This scheme breaks down if M < 2, ie, min_DCT_scaled_size is 1. In that + * situation each iMCU row provides only one row group so the buffering logic + * must be different (eg, we must read two iMCU rows before we can emit the + * first row group). For now, we simply do not support providing context + * rows when min_DCT_scaled_size is 1. That combination seems unlikely to + * be worth providing --- if someone wants a 1/8th-size preview, they probably + * want it quick and dirty, so a context-free upsampler is sufficient. + */ + + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_d_main_controller pub; /* public fields */ + + /* Pointer to allocated workspace (M or M+2 row groups). */ + JSAMPARRAY buffer[MAX_COMPONENTS]; + + boolean buffer_full; /* Have we gotten an iMCU row from decoder? */ + JDIMENSION rowgroup_ctr; /* counts row groups output to postprocessor */ + + /* Remaining fields are only used in the context case. */ + + /* These are the master pointers to the funny-order pointer lists. */ + JSAMPIMAGE xbuffer[2]; /* pointers to weird pointer lists */ + + int whichptr; /* indicates which pointer set is now in use */ + int context_state; /* process_data state machine status */ + JDIMENSION rowgroups_avail; /* row groups available to postprocessor */ + JDIMENSION iMCU_row_ctr; /* counts iMCU rows to detect image top/bot */ +} my_main_controller; + +typedef my_main_controller * my_main_ptr; + +/* context_state values: */ +#define CTX_PREPARE_FOR_IMCU 0 /* need to prepare for MCU row */ +#define CTX_PROCESS_IMCU 1 /* feeding iMCU to postprocessor */ +#define CTX_POSTPONED_ROW 2 /* feeding postponed row group */ + + +/* Forward declarations */ +METHODDEF(void) process_data_simple_main + JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); +METHODDEF(void) process_data_context_main + JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); +#ifdef QUANT_2PASS_SUPPORTED +METHODDEF(void) process_data_crank_post + JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); +#endif + + +LOCAL(void) +alloc_funny_pointers (j_decompress_ptr cinfo) +/* Allocate space for the funny pointer lists. + * This is done only once, not once per pass. + */ +{ + my_main_ptr main = (my_main_ptr) cinfo->main; + int ci, rgroup; + int M = cinfo->min_DCT_scaled_size; + jpeg_component_info *compptr; + JSAMPARRAY xbuf; + + /* Get top-level space for component array pointers. + * We alloc both arrays with one call to save a few cycles. + */ + main->xbuffer[0] = (JSAMPIMAGE) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + cinfo->num_components * 2 * SIZEOF(JSAMPARRAY)); + main->xbuffer[1] = main->xbuffer[0] + cinfo->num_components; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / + cinfo->min_DCT_scaled_size; /* height of a row group of component */ + /* Get space for pointer lists --- M+4 row groups in each list. + * We alloc both pointer lists with one call to save a few cycles. + */ + xbuf = (JSAMPARRAY) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + 2 * (rgroup * (M + 4)) * SIZEOF(JSAMPROW)); + xbuf += rgroup; /* want one row group at negative offsets */ + main->xbuffer[0][ci] = xbuf; + xbuf += rgroup * (M + 4); + main->xbuffer[1][ci] = xbuf; + } +} + + +LOCAL(void) +make_funny_pointers (j_decompress_ptr cinfo) +/* Create the funny pointer lists discussed in the comments above. + * The actual workspace is already allocated (in main->buffer), + * and the space for the pointer lists is allocated too. + * This routine just fills in the curiously ordered lists. + * This will be repeated at the beginning of each pass. + */ +{ + my_main_ptr main = (my_main_ptr) cinfo->main; + int ci, i, rgroup; + int M = cinfo->min_DCT_scaled_size; + jpeg_component_info *compptr; + JSAMPARRAY buf, xbuf0, xbuf1; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / + cinfo->min_DCT_scaled_size; /* height of a row group of component */ + xbuf0 = main->xbuffer[0][ci]; + xbuf1 = main->xbuffer[1][ci]; + /* First copy the workspace pointers as-is */ + buf = main->buffer[ci]; + for (i = 0; i < rgroup * (M + 2); i++) { + xbuf0[i] = xbuf1[i] = buf[i]; + } + /* In the second list, put the last four row groups in swapped order */ + for (i = 0; i < rgroup * 2; i++) { + xbuf1[rgroup*(M-2) + i] = buf[rgroup*M + i]; + xbuf1[rgroup*M + i] = buf[rgroup*(M-2) + i]; + } + /* The wraparound pointers at top and bottom will be filled later + * (see set_wraparound_pointers, below). Initially we want the "above" + * pointers to duplicate the first actual data line. This only needs + * to happen in xbuffer[0]. + */ + for (i = 0; i < rgroup; i++) { + xbuf0[i - rgroup] = xbuf0[0]; + } + } +} + + +LOCAL(void) +set_wraparound_pointers (j_decompress_ptr cinfo) +/* Set up the "wraparound" pointers at top and bottom of the pointer lists. + * This changes the pointer list state from top-of-image to the normal state. + */ +{ + my_main_ptr main = (my_main_ptr) cinfo->main; + int ci, i, rgroup; + int M = cinfo->min_DCT_scaled_size; + jpeg_component_info *compptr; + JSAMPARRAY xbuf0, xbuf1; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / + cinfo->min_DCT_scaled_size; /* height of a row group of component */ + xbuf0 = main->xbuffer[0][ci]; + xbuf1 = main->xbuffer[1][ci]; + for (i = 0; i < rgroup; i++) { + xbuf0[i - rgroup] = xbuf0[rgroup*(M+1) + i]; + xbuf1[i - rgroup] = xbuf1[rgroup*(M+1) + i]; + xbuf0[rgroup*(M+2) + i] = xbuf0[i]; + xbuf1[rgroup*(M+2) + i] = xbuf1[i]; + } + } +} + + +LOCAL(void) +set_bottom_pointers (j_decompress_ptr cinfo) +/* Change the pointer lists to duplicate the last sample row at the bottom + * of the image. whichptr indicates which xbuffer holds the final iMCU row. + * Also sets rowgroups_avail to indicate number of nondummy row groups in row. + */ +{ + my_main_ptr main = (my_main_ptr) cinfo->main; + int ci, i, rgroup, iMCUheight, rows_left; + jpeg_component_info *compptr; + JSAMPARRAY xbuf; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Count sample rows in one iMCU row and in one row group */ + iMCUheight = compptr->v_samp_factor * compptr->DCT_scaled_size; + rgroup = iMCUheight / cinfo->min_DCT_scaled_size; + /* Count nondummy sample rows remaining for this component */ + rows_left = (int) (compptr->downsampled_height % (JDIMENSION) iMCUheight); + if (rows_left == 0) rows_left = iMCUheight; + /* Count nondummy row groups. Should get same answer for each component, + * so we need only do it once. + */ + if (ci == 0) { + main->rowgroups_avail = (JDIMENSION) ((rows_left-1) / rgroup + 1); + } + /* Duplicate the last real sample row rgroup*2 times; this pads out the + * last partial rowgroup and ensures at least one full rowgroup of context. + */ + xbuf = main->xbuffer[main->whichptr][ci]; + for (i = 0; i < rgroup * 2; i++) { + xbuf[rows_left + i] = xbuf[rows_left-1]; + } + } +} + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_main (j_decompress_ptr cinfo, J_BUF_MODE pass_mode) +{ + my_main_ptr main = (my_main_ptr) cinfo->main; + + switch (pass_mode) { + case JBUF_PASS_THRU: + if (cinfo->upsample->need_context_rows) { + main->pub.process_data = process_data_context_main; + make_funny_pointers(cinfo); /* Create the xbuffer[] lists */ + main->whichptr = 0; /* Read first iMCU row into xbuffer[0] */ + main->context_state = CTX_PREPARE_FOR_IMCU; + main->iMCU_row_ctr = 0; + } else { + /* Simple case with no context needed */ + main->pub.process_data = process_data_simple_main; + } + main->buffer_full = FALSE; /* Mark buffer empty */ + main->rowgroup_ctr = 0; + break; +#ifdef QUANT_2PASS_SUPPORTED + case JBUF_CRANK_DEST: + /* For last pass of 2-pass quantization, just crank the postprocessor */ + main->pub.process_data = process_data_crank_post; + break; +#endif + default: + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + break; + } +} + + +/* + * Process some data. + * This handles the simple case where no context is required. + */ + +METHODDEF(void) +process_data_simple_main (j_decompress_ptr cinfo, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_main_ptr main = (my_main_ptr) cinfo->main; + JDIMENSION rowgroups_avail; + + /* Read input data if we haven't filled the main buffer yet */ + if (! main->buffer_full) { + if (! (*cinfo->coef->decompress_data) (cinfo, main->buffer)) + return; /* suspension forced, can do nothing more */ + main->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ + } + + /* There are always min_DCT_scaled_size row groups in an iMCU row. */ + rowgroups_avail = (JDIMENSION) cinfo->min_DCT_scaled_size; + /* Note: at the bottom of the image, we may pass extra garbage row groups + * to the postprocessor. The postprocessor has to check for bottom + * of image anyway (at row resolution), so no point in us doing it too. + */ + + /* Feed the postprocessor */ + (*cinfo->post->post_process_data) (cinfo, main->buffer, + &main->rowgroup_ctr, rowgroups_avail, + output_buf, out_row_ctr, out_rows_avail); + + /* Has postprocessor consumed all the data yet? If so, mark buffer empty */ + if (main->rowgroup_ctr >= rowgroups_avail) { + main->buffer_full = FALSE; + main->rowgroup_ctr = 0; + } +} + + +/* + * Process some data. + * This handles the case where context rows must be provided. + */ + +METHODDEF(void) +process_data_context_main (j_decompress_ptr cinfo, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_main_ptr main = (my_main_ptr) cinfo->main; + + /* Read input data if we haven't filled the main buffer yet */ + if (! main->buffer_full) { + if (! (*cinfo->coef->decompress_data) (cinfo, + main->xbuffer[main->whichptr])) + return; /* suspension forced, can do nothing more */ + main->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ + main->iMCU_row_ctr++; /* count rows received */ + } + + /* Postprocessor typically will not swallow all the input data it is handed + * in one call (due to filling the output buffer first). Must be prepared + * to exit and restart. This switch lets us keep track of how far we got. + * Note that each case falls through to the next on successful completion. + */ + switch (main->context_state) { + case CTX_POSTPONED_ROW: + /* Call postprocessor using previously set pointers for postponed row */ + (*cinfo->post->post_process_data) (cinfo, main->xbuffer[main->whichptr], + &main->rowgroup_ctr, main->rowgroups_avail, + output_buf, out_row_ctr, out_rows_avail); + if (main->rowgroup_ctr < main->rowgroups_avail) + return; /* Need to suspend */ + main->context_state = CTX_PREPARE_FOR_IMCU; + if (*out_row_ctr >= out_rows_avail) + return; /* Postprocessor exactly filled output buf */ + /*FALLTHROUGH*/ + case CTX_PREPARE_FOR_IMCU: + /* Prepare to process first M-1 row groups of this iMCU row */ + main->rowgroup_ctr = 0; + main->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_scaled_size - 1); + /* Check for bottom of image: if so, tweak pointers to "duplicate" + * the last sample row, and adjust rowgroups_avail to ignore padding rows. + */ + if (main->iMCU_row_ctr == cinfo->total_iMCU_rows) + set_bottom_pointers(cinfo); + main->context_state = CTX_PROCESS_IMCU; + /*FALLTHROUGH*/ + case CTX_PROCESS_IMCU: + /* Call postprocessor using previously set pointers */ + (*cinfo->post->post_process_data) (cinfo, main->xbuffer[main->whichptr], + &main->rowgroup_ctr, main->rowgroups_avail, + output_buf, out_row_ctr, out_rows_avail); + if (main->rowgroup_ctr < main->rowgroups_avail) + return; /* Need to suspend */ + /* After the first iMCU, change wraparound pointers to normal state */ + if (main->iMCU_row_ctr == 1) + set_wraparound_pointers(cinfo); + /* Prepare to load new iMCU row using other xbuffer list */ + main->whichptr ^= 1; /* 0=>1 or 1=>0 */ + main->buffer_full = FALSE; + /* Still need to process last row group of this iMCU row, */ + /* which is saved at index M+1 of the other xbuffer */ + main->rowgroup_ctr = (JDIMENSION) (cinfo->min_DCT_scaled_size + 1); + main->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_scaled_size + 2); + main->context_state = CTX_POSTPONED_ROW; + } +} + + +/* + * Process some data. + * Final pass of two-pass quantization: just call the postprocessor. + * Source data will be the postprocessor controller's internal buffer. + */ + +#ifdef QUANT_2PASS_SUPPORTED + +METHODDEF(void) +process_data_crank_post (j_decompress_ptr cinfo, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + (*cinfo->post->post_process_data) (cinfo, (JSAMPIMAGE) NULL, + (JDIMENSION *) NULL, (JDIMENSION) 0, + output_buf, out_row_ctr, out_rows_avail); +} + +#endif /* QUANT_2PASS_SUPPORTED */ + + +/* + * Initialize main buffer controller. + */ + +GLOBAL(void) +jinit_d_main_controller (j_decompress_ptr cinfo, boolean need_full_buffer) +{ + my_main_ptr main; + int ci, rgroup, ngroups; + jpeg_component_info *compptr; + + main = (my_main_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_main_controller)); + cinfo->main = (struct jpeg_d_main_controller *) main; + main->pub.start_pass = start_pass_main; + + if (need_full_buffer) /* shouldn't happen */ + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + + /* Allocate the workspace. + * ngroups is the number of row groups we need. + */ + if (cinfo->upsample->need_context_rows) { + if (cinfo->min_DCT_scaled_size < 2) /* unsupported, see comments above */ + ERREXIT(cinfo, JERR_NOTIMPL); + alloc_funny_pointers(cinfo); /* Alloc space for xbuffer[] lists */ + ngroups = cinfo->min_DCT_scaled_size + 2; + } else { + ngroups = cinfo->min_DCT_scaled_size; + } + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / + cinfo->min_DCT_scaled_size; /* height of a row group of component */ + main->buffer[ci] = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + compptr->width_in_blocks * compptr->DCT_scaled_size, + (JDIMENSION) (rgroup * ngroups)); + } +} diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jdmarker.c b/lc-continuity/mk4/modimage/jpeg-6b/jdmarker.c new file mode 100644 index 0000000000000000000000000000000000000000..f4cca8cc835c271ce14920ca790461ffc7ba4640 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jdmarker.c @@ -0,0 +1,1360 @@ +/* + * jdmarker.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains routines to decode JPEG datastream markers. + * Most of the complexity arises from our desire to support input + * suspension: if not all of the data for a marker is available, + * we must exit back to the application. On resumption, we reprocess + * the marker. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +typedef enum { /* JPEG marker codes */ + M_SOF0 = 0xc0, + M_SOF1 = 0xc1, + M_SOF2 = 0xc2, + M_SOF3 = 0xc3, + + M_SOF5 = 0xc5, + M_SOF6 = 0xc6, + M_SOF7 = 0xc7, + + M_JPG = 0xc8, + M_SOF9 = 0xc9, + M_SOF10 = 0xca, + M_SOF11 = 0xcb, + + M_SOF13 = 0xcd, + M_SOF14 = 0xce, + M_SOF15 = 0xcf, + + M_DHT = 0xc4, + + M_DAC = 0xcc, + + M_RST0 = 0xd0, + M_RST1 = 0xd1, + M_RST2 = 0xd2, + M_RST3 = 0xd3, + M_RST4 = 0xd4, + M_RST5 = 0xd5, + M_RST6 = 0xd6, + M_RST7 = 0xd7, + + M_SOI = 0xd8, + M_EOI = 0xd9, + M_SOS = 0xda, + M_DQT = 0xdb, + M_DNL = 0xdc, + M_DRI = 0xdd, + M_DHP = 0xde, + M_EXP = 0xdf, + + M_APP0 = 0xe0, + M_APP1 = 0xe1, + M_APP2 = 0xe2, + M_APP3 = 0xe3, + M_APP4 = 0xe4, + M_APP5 = 0xe5, + M_APP6 = 0xe6, + M_APP7 = 0xe7, + M_APP8 = 0xe8, + M_APP9 = 0xe9, + M_APP10 = 0xea, + M_APP11 = 0xeb, + M_APP12 = 0xec, + M_APP13 = 0xed, + M_APP14 = 0xee, + M_APP15 = 0xef, + + M_JPG0 = 0xf0, + M_JPG13 = 0xfd, + M_COM = 0xfe, + + M_TEM = 0x01, + + M_ERROR = 0x100 +} JPEG_MARKER; + + +/* Private state */ + +typedef struct { + struct jpeg_marker_reader pub; /* public fields */ + + /* Application-overridable marker processing methods */ + jpeg_marker_parser_method process_COM; + jpeg_marker_parser_method process_APPn[16]; + + /* Limit on marker data length to save for each marker type */ + unsigned int length_limit_COM; + unsigned int length_limit_APPn[16]; + + /* Status of COM/APPn marker saving */ + jpeg_saved_marker_ptr cur_marker; /* NULL if not processing a marker */ + unsigned int bytes_read; /* data bytes read so far in marker */ + /* Note: cur_marker is not linked into marker_list until it's all read. */ +} my_marker_reader; + +typedef my_marker_reader * my_marker_ptr; + + +/* + * Macros for fetching data from the data source module. + * + * At all times, cinfo->src->next_input_byte and ->bytes_in_buffer reflect + * the current restart point; we update them only when we have reached a + * suitable place to restart if a suspension occurs. + */ + +/* Declare and initialize local copies of input pointer/count */ +#define INPUT_VARS(cinfo) \ + struct jpeg_source_mgr * datasrc = (cinfo)->src; \ + const JOCTET * next_input_byte = datasrc->next_input_byte; \ + size_t bytes_in_buffer = datasrc->bytes_in_buffer + +/* Unload the local copies --- do this only at a restart boundary */ +#define INPUT_SYNC(cinfo) \ + ( datasrc->next_input_byte = next_input_byte, \ + datasrc->bytes_in_buffer = bytes_in_buffer ) + +/* Reload the local copies --- used only in MAKE_BYTE_AVAIL */ +#define INPUT_RELOAD(cinfo) \ + ( next_input_byte = datasrc->next_input_byte, \ + bytes_in_buffer = datasrc->bytes_in_buffer ) + +/* Internal macro for INPUT_BYTE and INPUT_2BYTES: make a byte available. + * Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + * but we must reload the local copies after a successful fill. + */ +#define MAKE_BYTE_AVAIL(cinfo,action) \ + if (bytes_in_buffer == 0) { \ + if (! (*datasrc->fill_input_buffer) (cinfo)) \ + { action; } \ + INPUT_RELOAD(cinfo); \ + } + +/* Read a byte into variable V. + * If must suspend, take the specified action (typically "return FALSE"). + */ +#define INPUT_BYTE(cinfo,V,action) \ + MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \ + bytes_in_buffer--; \ + V = GETJOCTET(*next_input_byte++); ) + +/* As above, but read two bytes interpreted as an unsigned 16-bit integer. + * V should be declared unsigned int or perhaps INT32. + */ +#define INPUT_2BYTES(cinfo,V,action) \ + MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \ + bytes_in_buffer--; \ + V = ((unsigned int) GETJOCTET(*next_input_byte++)) << 8; \ + MAKE_BYTE_AVAIL(cinfo,action); \ + bytes_in_buffer--; \ + V += GETJOCTET(*next_input_byte++); ) + + +/* + * Routines to process JPEG markers. + * + * Entry condition: JPEG marker itself has been read and its code saved + * in cinfo->unread_marker; input restart point is just after the marker. + * + * Exit: if return TRUE, have read and processed any parameters, and have + * updated the restart point to point after the parameters. + * If return FALSE, was forced to suspend before reaching end of + * marker parameters; restart point has not been moved. Same routine + * will be called again after application supplies more input data. + * + * This approach to suspension assumes that all of a marker's parameters + * can fit into a single input bufferload. This should hold for "normal" + * markers. Some COM/APPn markers might have large parameter segments + * that might not fit. If we are simply dropping such a marker, we use + * skip_input_data to get past it, and thereby put the problem on the + * source manager's shoulders. If we are saving the marker's contents + * into memory, we use a slightly different convention: when forced to + * suspend, the marker processor updates the restart point to the end of + * what it's consumed (ie, the end of the buffer) before returning FALSE. + * On resumption, cinfo->unread_marker still contains the marker code, + * but the data source will point to the next chunk of marker data. + * The marker processor must retain internal state to deal with this. + * + * Note that we don't bother to avoid duplicate trace messages if a + * suspension occurs within marker parameters. Other side effects + * require more care. + */ + + +LOCAL(boolean) +get_soi (j_decompress_ptr cinfo) +/* Process an SOI marker */ +{ + int i; + + TRACEMS(cinfo, 1, JTRC_SOI); + + if (cinfo->marker->saw_SOI) + ERREXIT(cinfo, JERR_SOI_DUPLICATE); + + /* Reset all parameters that are defined to be reset by SOI */ + + for (i = 0; i < NUM_ARITH_TBLS; i++) { + cinfo->arith_dc_L[i] = 0; + cinfo->arith_dc_U[i] = 1; + cinfo->arith_ac_K[i] = 5; + } + cinfo->restart_interval = 0; + + /* Set initial assumptions for colorspace etc */ + + cinfo->jpeg_color_space = JCS_UNKNOWN; + cinfo->CCIR601_sampling = FALSE; /* Assume non-CCIR sampling??? */ + + cinfo->saw_JFIF_marker = FALSE; + cinfo->JFIF_major_version = 1; /* set default JFIF APP0 values */ + cinfo->JFIF_minor_version = 1; + cinfo->density_unit = 0; + cinfo->X_density = 1; + cinfo->Y_density = 1; + cinfo->saw_Adobe_marker = FALSE; + cinfo->Adobe_transform = 0; + + cinfo->marker->saw_SOI = TRUE; + + return TRUE; +} + + +LOCAL(boolean) +get_sof (j_decompress_ptr cinfo, boolean is_prog, boolean is_arith) +/* Process a SOFn marker */ +{ + INT32 length; + int c, ci; + jpeg_component_info * compptr; + INPUT_VARS(cinfo); + + cinfo->progressive_mode = is_prog; + cinfo->arith_code = is_arith; + + INPUT_2BYTES(cinfo, length, return FALSE); + + INPUT_BYTE(cinfo, cinfo->data_precision, return FALSE); + INPUT_2BYTES(cinfo, cinfo->image_height, return FALSE); + INPUT_2BYTES(cinfo, cinfo->image_width, return FALSE); + INPUT_BYTE(cinfo, cinfo->num_components, return FALSE); + + length -= 8; + + TRACEMS4(cinfo, 1, JTRC_SOF, cinfo->unread_marker, + (int) cinfo->image_width, (int) cinfo->image_height, + cinfo->num_components); + + if (cinfo->marker->saw_SOF) + ERREXIT(cinfo, JERR_SOF_DUPLICATE); + + /* We don't support files in which the image height is initially specified */ + /* as 0 and is later redefined by DNL. As long as we have to check that, */ + /* might as well have a general sanity check. */ + if (cinfo->image_height <= 0 || cinfo->image_width <= 0 + || cinfo->num_components <= 0) + ERREXIT(cinfo, JERR_EMPTY_IMAGE); + + if (length != (cinfo->num_components * 3)) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + if (cinfo->comp_info == NULL) /* do only once, even if suspend */ + cinfo->comp_info = (jpeg_component_info *) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + cinfo->num_components * SIZEOF(jpeg_component_info)); + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + compptr->component_index = ci; + INPUT_BYTE(cinfo, compptr->component_id, return FALSE); + INPUT_BYTE(cinfo, c, return FALSE); + compptr->h_samp_factor = (c >> 4) & 15; + compptr->v_samp_factor = (c ) & 15; + INPUT_BYTE(cinfo, compptr->quant_tbl_no, return FALSE); + + TRACEMS4(cinfo, 1, JTRC_SOF_COMPONENT, + compptr->component_id, compptr->h_samp_factor, + compptr->v_samp_factor, compptr->quant_tbl_no); + } + + cinfo->marker->saw_SOF = TRUE; + + INPUT_SYNC(cinfo); + return TRUE; +} + + +LOCAL(boolean) +get_sos (j_decompress_ptr cinfo) +/* Process a SOS marker */ +{ + INT32 length; + int i, ci, n, c, cc; + jpeg_component_info * compptr; + INPUT_VARS(cinfo); + + if (! cinfo->marker->saw_SOF) + ERREXIT(cinfo, JERR_SOS_NO_SOF); + + INPUT_2BYTES(cinfo, length, return FALSE); + + INPUT_BYTE(cinfo, n, return FALSE); /* Number of components */ + + TRACEMS1(cinfo, 1, JTRC_SOS, n); + + if (length != (n * 2 + 6) || n < 1 || n > MAX_COMPS_IN_SCAN) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + cinfo->comps_in_scan = n; + + /* Collect the component-spec parameters */ + + for (i = 0; i < n; i++) { + INPUT_BYTE(cinfo, cc, return FALSE); + INPUT_BYTE(cinfo, c, return FALSE); + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + if (cc == compptr->component_id) + goto id_found; + } + + ERREXIT1(cinfo, JERR_BAD_COMPONENT_ID, cc); + + id_found: + + cinfo->cur_comp_info[i] = compptr; + compptr->dc_tbl_no = (c >> 4) & 15; + compptr->ac_tbl_no = (c ) & 15; + + TRACEMS3(cinfo, 1, JTRC_SOS_COMPONENT, cc, + compptr->dc_tbl_no, compptr->ac_tbl_no); + } + + /* Collect the additional scan parameters Ss, Se, Ah/Al. */ + INPUT_BYTE(cinfo, c, return FALSE); + cinfo->Ss = c; + INPUT_BYTE(cinfo, c, return FALSE); + cinfo->Se = c; + INPUT_BYTE(cinfo, c, return FALSE); + cinfo->Ah = (c >> 4) & 15; + cinfo->Al = (c ) & 15; + + TRACEMS4(cinfo, 1, JTRC_SOS_PARAMS, cinfo->Ss, cinfo->Se, + cinfo->Ah, cinfo->Al); + + /* Prepare to scan data & restart markers */ + cinfo->marker->next_restart_num = 0; + + /* Count another SOS marker */ + cinfo->input_scan_number++; + + INPUT_SYNC(cinfo); + return TRUE; +} + + +#ifdef D_ARITH_CODING_SUPPORTED + +LOCAL(boolean) +get_dac (j_decompress_ptr cinfo) +/* Process a DAC marker */ +{ + INT32 length; + int index, val; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + + while (length > 0) { + INPUT_BYTE(cinfo, index, return FALSE); + INPUT_BYTE(cinfo, val, return FALSE); + + length -= 2; + + TRACEMS2(cinfo, 1, JTRC_DAC, index, val); + + if (index < 0 || index >= (2*NUM_ARITH_TBLS)) + ERREXIT1(cinfo, JERR_DAC_INDEX, index); + + if (index >= NUM_ARITH_TBLS) { /* define AC table */ + cinfo->arith_ac_K[index-NUM_ARITH_TBLS] = (UINT8) val; + } else { /* define DC table */ + cinfo->arith_dc_L[index] = (UINT8) (val & 0x0F); + cinfo->arith_dc_U[index] = (UINT8) (val >> 4); + if (cinfo->arith_dc_L[index] > cinfo->arith_dc_U[index]) + ERREXIT1(cinfo, JERR_DAC_VALUE, val); + } + } + + if (length != 0) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + INPUT_SYNC(cinfo); + return TRUE; +} + +#else /* ! D_ARITH_CODING_SUPPORTED */ + +#define get_dac(cinfo) skip_variable(cinfo) + +#endif /* D_ARITH_CODING_SUPPORTED */ + + +LOCAL(boolean) +get_dht (j_decompress_ptr cinfo) +/* Process a DHT marker */ +{ + INT32 length; + UINT8 bits[17]; + UINT8 huffval[256]; + int i, index, count; + JHUFF_TBL **htblptr; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + + while (length > 16) { + INPUT_BYTE(cinfo, index, return FALSE); + + TRACEMS1(cinfo, 1, JTRC_DHT, index); + + bits[0] = 0; + count = 0; + for (i = 1; i <= 16; i++) { + INPUT_BYTE(cinfo, bits[i], return FALSE); + count += bits[i]; + } + + length -= 1 + 16; + + TRACEMS8(cinfo, 2, JTRC_HUFFBITS, + bits[1], bits[2], bits[3], bits[4], + bits[5], bits[6], bits[7], bits[8]); + TRACEMS8(cinfo, 2, JTRC_HUFFBITS, + bits[9], bits[10], bits[11], bits[12], + bits[13], bits[14], bits[15], bits[16]); + + /* Here we just do minimal validation of the counts to avoid walking + * off the end of our table space. jdhuff.c will check more carefully. + */ + if (count > 256 || ((INT32) count) > length) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + + for (i = 0; i < count; i++) + INPUT_BYTE(cinfo, huffval[i], return FALSE); + + length -= count; + + if (index & 0x10) { /* AC table definition */ + index -= 0x10; + htblptr = &cinfo->ac_huff_tbl_ptrs[index]; + } else { /* DC table definition */ + htblptr = &cinfo->dc_huff_tbl_ptrs[index]; + } + + if (index < 0 || index >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_DHT_INDEX, index); + + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + + MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits)); + MEMCOPY((*htblptr)->huffval, huffval, SIZEOF((*htblptr)->huffval)); + } + + if (length != 0) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + INPUT_SYNC(cinfo); + return TRUE; +} + + +LOCAL(boolean) +get_dqt (j_decompress_ptr cinfo) +/* Process a DQT marker */ +{ + INT32 length; + int n, i, prec; + unsigned int tmp; + JQUANT_TBL *quant_ptr; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + + while (length > 0) { + INPUT_BYTE(cinfo, n, return FALSE); + prec = n >> 4; + n &= 0x0F; + + TRACEMS2(cinfo, 1, JTRC_DQT, n, prec); + + if (n >= NUM_QUANT_TBLS) + ERREXIT1(cinfo, JERR_DQT_INDEX, n); + + if (cinfo->quant_tbl_ptrs[n] == NULL) + cinfo->quant_tbl_ptrs[n] = jpeg_alloc_quant_table((j_common_ptr) cinfo); + quant_ptr = cinfo->quant_tbl_ptrs[n]; + + for (i = 0; i < DCTSIZE2; i++) { + if (prec) + INPUT_2BYTES(cinfo, tmp, return FALSE); + else + INPUT_BYTE(cinfo, tmp, return FALSE); + /* We convert the zigzag-order table to natural array order. */ + quant_ptr->quantval[jpeg_natural_order[i]] = (UINT16) tmp; + } + + if (cinfo->err->trace_level >= 2) { + for (i = 0; i < DCTSIZE2; i += 8) { + TRACEMS8(cinfo, 2, JTRC_QUANTVALS, + quant_ptr->quantval[i], quant_ptr->quantval[i+1], + quant_ptr->quantval[i+2], quant_ptr->quantval[i+3], + quant_ptr->quantval[i+4], quant_ptr->quantval[i+5], + quant_ptr->quantval[i+6], quant_ptr->quantval[i+7]); + } + } + + length -= DCTSIZE2+1; + if (prec) length -= DCTSIZE2; + } + + if (length != 0) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + INPUT_SYNC(cinfo); + return TRUE; +} + + +LOCAL(boolean) +get_dri (j_decompress_ptr cinfo) +/* Process a DRI marker */ +{ + INT32 length; + unsigned int tmp; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + + if (length != 4) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + INPUT_2BYTES(cinfo, tmp, return FALSE); + + TRACEMS1(cinfo, 1, JTRC_DRI, tmp); + + cinfo->restart_interval = tmp; + + INPUT_SYNC(cinfo); + return TRUE; +} + + +/* + * Routines for processing APPn and COM markers. + * These are either saved in memory or discarded, per application request. + * APP0 and APP14 are specially checked to see if they are + * JFIF and Adobe markers, respectively. + */ + +#define APP0_DATA_LEN 14 /* Length of interesting data in APP0 */ +#define APP14_DATA_LEN 12 /* Length of interesting data in APP14 */ +#define APPN_DATA_LEN 14 /* Must be the largest of the above!! */ + + +LOCAL(void) +examine_app0 (j_decompress_ptr cinfo, JOCTET FAR * data, + unsigned int datalen, INT32 remaining) +/* Examine first few bytes from an APP0. + * Take appropriate action if it is a JFIF marker. + * datalen is # of bytes at data[], remaining is length of rest of marker data. + */ +{ + INT32 totallen = (INT32) datalen + remaining; + + if (datalen >= APP0_DATA_LEN && + GETJOCTET(data[0]) == 0x4A && + GETJOCTET(data[1]) == 0x46 && + GETJOCTET(data[2]) == 0x49 && + GETJOCTET(data[3]) == 0x46 && + GETJOCTET(data[4]) == 0) { + /* Found JFIF APP0 marker: save info */ + cinfo->saw_JFIF_marker = TRUE; + cinfo->JFIF_major_version = GETJOCTET(data[5]); + cinfo->JFIF_minor_version = GETJOCTET(data[6]); + cinfo->density_unit = GETJOCTET(data[7]); + cinfo->X_density = (GETJOCTET(data[8]) << 8) + GETJOCTET(data[9]); + cinfo->Y_density = (GETJOCTET(data[10]) << 8) + GETJOCTET(data[11]); + /* Check version. + * Major version must be 1, anything else signals an incompatible change. + * (We used to treat this as an error, but now it's a nonfatal warning, + * because some bozo at Hijaak couldn't read the spec.) + * Minor version should be 0..2, but process anyway if newer. + */ + if (cinfo->JFIF_major_version != 1) + WARNMS2(cinfo, JWRN_JFIF_MAJOR, + cinfo->JFIF_major_version, cinfo->JFIF_minor_version); + /* Generate trace messages */ + TRACEMS5(cinfo, 1, JTRC_JFIF, + cinfo->JFIF_major_version, cinfo->JFIF_minor_version, + cinfo->X_density, cinfo->Y_density, cinfo->density_unit); + /* Validate thumbnail dimensions and issue appropriate messages */ + if (GETJOCTET(data[12]) | GETJOCTET(data[13])) + TRACEMS2(cinfo, 1, JTRC_JFIF_THUMBNAIL, + GETJOCTET(data[12]), GETJOCTET(data[13])); + totallen -= APP0_DATA_LEN; + if (totallen != + ((INT32)GETJOCTET(data[12]) * (INT32)GETJOCTET(data[13]) * (INT32) 3)) + TRACEMS1(cinfo, 1, JTRC_JFIF_BADTHUMBNAILSIZE, (int) totallen); + } else if (datalen >= 6 && + GETJOCTET(data[0]) == 0x4A && + GETJOCTET(data[1]) == 0x46 && + GETJOCTET(data[2]) == 0x58 && + GETJOCTET(data[3]) == 0x58 && + GETJOCTET(data[4]) == 0) { + /* Found JFIF "JFXX" extension APP0 marker */ + /* The library doesn't actually do anything with these, + * but we try to produce a helpful trace message. + */ + switch (GETJOCTET(data[5])) { + case 0x10: + TRACEMS1(cinfo, 1, JTRC_THUMB_JPEG, (int) totallen); + break; + case 0x11: + TRACEMS1(cinfo, 1, JTRC_THUMB_PALETTE, (int) totallen); + break; + case 0x13: + TRACEMS1(cinfo, 1, JTRC_THUMB_RGB, (int) totallen); + break; + default: + TRACEMS2(cinfo, 1, JTRC_JFIF_EXTENSION, + GETJOCTET(data[5]), (int) totallen); + break; + } + } else { + /* Start of APP0 does not match "JFIF" or "JFXX", or too short */ + TRACEMS1(cinfo, 1, JTRC_APP0, (int) totallen); + } +} + + +LOCAL(void) +examine_app14 (j_decompress_ptr cinfo, JOCTET FAR * data, + unsigned int datalen, INT32 remaining) +/* Examine first few bytes from an APP14. + * Take appropriate action if it is an Adobe marker. + * datalen is # of bytes at data[], remaining is length of rest of marker data. + */ +{ + unsigned int version, flags0, flags1, transform; + + if (datalen >= APP14_DATA_LEN && + GETJOCTET(data[0]) == 0x41 && + GETJOCTET(data[1]) == 0x64 && + GETJOCTET(data[2]) == 0x6F && + GETJOCTET(data[3]) == 0x62 && + GETJOCTET(data[4]) == 0x65) { + /* Found Adobe APP14 marker */ + version = (GETJOCTET(data[5]) << 8) + GETJOCTET(data[6]); + flags0 = (GETJOCTET(data[7]) << 8) + GETJOCTET(data[8]); + flags1 = (GETJOCTET(data[9]) << 8) + GETJOCTET(data[10]); + transform = GETJOCTET(data[11]); + TRACEMS4(cinfo, 1, JTRC_ADOBE, version, flags0, flags1, transform); + cinfo->saw_Adobe_marker = TRUE; + cinfo->Adobe_transform = (UINT8) transform; + } else { + /* Start of APP14 does not match "Adobe", or too short */ + TRACEMS1(cinfo, 1, JTRC_APP14, (int) (datalen + remaining)); + } +} + + +METHODDEF(boolean) +get_interesting_appn (j_decompress_ptr cinfo) +/* Process an APP0 or APP14 marker without saving it */ +{ + INT32 length; + JOCTET b[APPN_DATA_LEN]; + unsigned int i, numtoread; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + + /* get the interesting part of the marker data */ + if (length >= APPN_DATA_LEN) + numtoread = APPN_DATA_LEN; + else if (length > 0) + numtoread = (unsigned int) length; + else + numtoread = 0; + for (i = 0; i < numtoread; i++) + INPUT_BYTE(cinfo, b[i], return FALSE); + length -= numtoread; + + /* process it */ + switch (cinfo->unread_marker) { + case M_APP0: + examine_app0(cinfo, (JOCTET FAR *) b, numtoread, length); + break; + case M_APP14: + examine_app14(cinfo, (JOCTET FAR *) b, numtoread, length); + break; + default: + /* can't get here unless jpeg_save_markers chooses wrong processor */ + ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker); + break; + } + + /* skip any remaining data -- could be lots */ + INPUT_SYNC(cinfo); + if (length > 0) + (*cinfo->src->skip_input_data) (cinfo, (long) length); + + return TRUE; +} + + +#ifdef SAVE_MARKERS_SUPPORTED + +METHODDEF(boolean) +save_marker (j_decompress_ptr cinfo) +/* Save an APPn or COM marker into the marker list */ +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + jpeg_saved_marker_ptr cur_marker = marker->cur_marker; + unsigned int bytes_read, data_length; + JOCTET FAR * data; + INT32 length = 0; + INPUT_VARS(cinfo); + + if (cur_marker == NULL) { + /* begin reading a marker */ + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + if (length >= 0) { /* watch out for bogus length word */ + /* figure out how much we want to save */ + unsigned int limit; + if (cinfo->unread_marker == (int) M_COM) + limit = marker->length_limit_COM; + else + limit = marker->length_limit_APPn[cinfo->unread_marker - (int) M_APP0]; + if ((unsigned int) length < limit) + limit = (unsigned int) length; + /* allocate and initialize the marker item */ + cur_marker = (jpeg_saved_marker_ptr) + (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(struct jpeg_marker_struct) + limit); + cur_marker->next = NULL; + cur_marker->marker = (UINT8) cinfo->unread_marker; + cur_marker->original_length = (unsigned int) length; + cur_marker->data_length = limit; + /* data area is just beyond the jpeg_marker_struct */ + data = cur_marker->data = (JOCTET FAR *) (cur_marker + 1); + marker->cur_marker = cur_marker; + marker->bytes_read = 0; + bytes_read = 0; + data_length = limit; + } else { + /* deal with bogus length word */ + bytes_read = data_length = 0; + data = NULL; + } + } else { + /* resume reading a marker */ + bytes_read = marker->bytes_read; + data_length = cur_marker->data_length; + data = cur_marker->data + bytes_read; + } + + while (bytes_read < data_length) { + INPUT_SYNC(cinfo); /* move the restart point to here */ + marker->bytes_read = bytes_read; + /* If there's not at least one byte in buffer, suspend */ + MAKE_BYTE_AVAIL(cinfo, return FALSE); + /* Copy bytes with reasonable rapidity */ + while (bytes_read < data_length && bytes_in_buffer > 0) { + *data++ = *next_input_byte++; + bytes_in_buffer--; + bytes_read++; + } + } + + /* Done reading what we want to read */ + if (cur_marker != NULL) { /* will be NULL if bogus length word */ + /* Add new marker to end of list */ + if (cinfo->marker_list == NULL) { + cinfo->marker_list = cur_marker; + } else { + jpeg_saved_marker_ptr prev = cinfo->marker_list; + while (prev->next != NULL) + prev = prev->next; + prev->next = cur_marker; + } + /* Reset pointer & calc remaining data length */ + data = cur_marker->data; + length = cur_marker->original_length - data_length; + } + /* Reset to initial state for next marker */ + marker->cur_marker = NULL; + + /* Process the marker if interesting; else just make a generic trace msg */ + switch (cinfo->unread_marker) { + case M_APP0: + examine_app0(cinfo, data, data_length, length); + break; + case M_APP14: + examine_app14(cinfo, data, data_length, length); + break; + default: + TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker, + (int) (data_length + length)); + break; + } + + /* skip any remaining data -- could be lots */ + INPUT_SYNC(cinfo); /* do before skip_input_data */ + if (length > 0) + (*cinfo->src->skip_input_data) (cinfo, (long) length); + + return TRUE; +} + +#endif /* SAVE_MARKERS_SUPPORTED */ + + +METHODDEF(boolean) +skip_variable (j_decompress_ptr cinfo) +/* Skip over an unknown or uninteresting variable-length marker */ +{ + INT32 length; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + + TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker, (int) length); + + INPUT_SYNC(cinfo); /* do before skip_input_data */ + if (length > 0) + (*cinfo->src->skip_input_data) (cinfo, (long) length); + + return TRUE; +} + + +/* + * Find the next JPEG marker, save it in cinfo->unread_marker. + * Returns FALSE if had to suspend before reaching a marker; + * in that case cinfo->unread_marker is unchanged. + * + * Note that the result might not be a valid marker code, + * but it will never be 0 or FF. + */ + +LOCAL(boolean) +next_marker (j_decompress_ptr cinfo) +{ + int c; + INPUT_VARS(cinfo); + + for (;;) { + INPUT_BYTE(cinfo, c, return FALSE); + /* Skip any non-FF bytes. + * This may look a bit inefficient, but it will not occur in a valid file. + * We sync after each discarded byte so that a suspending data source + * can discard the byte from its buffer. + */ + while (c != 0xFF) { + cinfo->marker->discarded_bytes++; + INPUT_SYNC(cinfo); + INPUT_BYTE(cinfo, c, return FALSE); + } + /* This loop swallows any duplicate FF bytes. Extra FFs are legal as + * pad bytes, so don't count them in discarded_bytes. We assume there + * will not be so many consecutive FF bytes as to overflow a suspending + * data source's input buffer. + */ + do { + INPUT_BYTE(cinfo, c, return FALSE); + } while (c == 0xFF); + if (c != 0) + break; /* found a valid marker, exit loop */ + /* Reach here if we found a stuffed-zero data sequence (FF/00). + * Discard it and loop back to try again. + */ + cinfo->marker->discarded_bytes += 2; + INPUT_SYNC(cinfo); + } + + if (cinfo->marker->discarded_bytes != 0) { + WARNMS2(cinfo, JWRN_EXTRANEOUS_DATA, cinfo->marker->discarded_bytes, c); + cinfo->marker->discarded_bytes = 0; + } + + cinfo->unread_marker = c; + + INPUT_SYNC(cinfo); + return TRUE; +} + + +LOCAL(boolean) +first_marker (j_decompress_ptr cinfo) +/* Like next_marker, but used to obtain the initial SOI marker. */ +/* For this marker, we do not allow preceding garbage or fill; otherwise, + * we might well scan an entire input file before realizing it ain't JPEG. + * If an application wants to process non-JFIF files, it must seek to the + * SOI before calling the JPEG library. + */ +{ + int c, c2; + INPUT_VARS(cinfo); + + INPUT_BYTE(cinfo, c, return FALSE); + INPUT_BYTE(cinfo, c2, return FALSE); + if (c != 0xFF || c2 != (int) M_SOI) + ERREXIT2(cinfo, JERR_NO_SOI, c, c2); + + cinfo->unread_marker = c2; + + INPUT_SYNC(cinfo); + return TRUE; +} + + +/* + * Read markers until SOS or EOI. + * + * Returns same codes as are defined for jpeg_consume_input: + * JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. + */ + +METHODDEF(int) +read_markers (j_decompress_ptr cinfo) +{ + /* Outer loop repeats once for each marker. */ + for (;;) { + /* Collect the marker proper, unless we already did. */ + /* NB: first_marker() enforces the requirement that SOI appear first. */ + if (cinfo->unread_marker == 0) { + if (! cinfo->marker->saw_SOI) { + if (! first_marker(cinfo)) + return JPEG_SUSPENDED; + } else { + if (! next_marker(cinfo)) + return JPEG_SUSPENDED; + } + } + /* At this point cinfo->unread_marker contains the marker code and the + * input point is just past the marker proper, but before any parameters. + * A suspension will cause us to return with this state still true. + */ + switch (cinfo->unread_marker) { + case M_SOI: + if (! get_soi(cinfo)) + return JPEG_SUSPENDED; + break; + + case M_SOF0: /* Baseline */ + case M_SOF1: /* Extended sequential, Huffman */ + if (! get_sof(cinfo, FALSE, FALSE)) + return JPEG_SUSPENDED; + break; + + case M_SOF2: /* Progressive, Huffman */ + if (! get_sof(cinfo, TRUE, FALSE)) + return JPEG_SUSPENDED; + break; + + case M_SOF9: /* Extended sequential, arithmetic */ + if (! get_sof(cinfo, FALSE, TRUE)) + return JPEG_SUSPENDED; + break; + + case M_SOF10: /* Progressive, arithmetic */ + if (! get_sof(cinfo, TRUE, TRUE)) + return JPEG_SUSPENDED; + break; + + /* Currently unsupported SOFn types */ + case M_SOF3: /* Lossless, Huffman */ + case M_SOF5: /* Differential sequential, Huffman */ + case M_SOF6: /* Differential progressive, Huffman */ + case M_SOF7: /* Differential lossless, Huffman */ + case M_JPG: /* Reserved for JPEG extensions */ + case M_SOF11: /* Lossless, arithmetic */ + case M_SOF13: /* Differential sequential, arithmetic */ + case M_SOF14: /* Differential progressive, arithmetic */ + case M_SOF15: /* Differential lossless, arithmetic */ + ERREXIT1(cinfo, JERR_SOF_UNSUPPORTED, cinfo->unread_marker); + break; + + case M_SOS: + if (! get_sos(cinfo)) + return JPEG_SUSPENDED; + cinfo->unread_marker = 0; /* processed the marker */ + return JPEG_REACHED_SOS; + + case M_EOI: + TRACEMS(cinfo, 1, JTRC_EOI); + cinfo->unread_marker = 0; /* processed the marker */ + return JPEG_REACHED_EOI; + + case M_DAC: + if (! get_dac(cinfo)) + return JPEG_SUSPENDED; + break; + + case M_DHT: + if (! get_dht(cinfo)) + return JPEG_SUSPENDED; + break; + + case M_DQT: + if (! get_dqt(cinfo)) + return JPEG_SUSPENDED; + break; + + case M_DRI: + if (! get_dri(cinfo)) + return JPEG_SUSPENDED; + break; + + case M_APP0: + case M_APP1: + case M_APP2: + case M_APP3: + case M_APP4: + case M_APP5: + case M_APP6: + case M_APP7: + case M_APP8: + case M_APP9: + case M_APP10: + case M_APP11: + case M_APP12: + case M_APP13: + case M_APP14: + case M_APP15: + if (! (*((my_marker_ptr) cinfo->marker)->process_APPn[ + cinfo->unread_marker - (int) M_APP0]) (cinfo)) + return JPEG_SUSPENDED; + break; + + case M_COM: + if (! (*((my_marker_ptr) cinfo->marker)->process_COM) (cinfo)) + return JPEG_SUSPENDED; + break; + + case M_RST0: /* these are all parameterless */ + case M_RST1: + case M_RST2: + case M_RST3: + case M_RST4: + case M_RST5: + case M_RST6: + case M_RST7: + case M_TEM: + TRACEMS1(cinfo, 1, JTRC_PARMLESS_MARKER, cinfo->unread_marker); + break; + + case M_DNL: /* Ignore DNL ... perhaps the wrong thing */ + if (! skip_variable(cinfo)) + return JPEG_SUSPENDED; + break; + + default: /* must be DHP, EXP, JPGn, or RESn */ + /* For now, we treat the reserved markers as fatal errors since they are + * likely to be used to signal incompatible JPEG Part 3 extensions. + * Once the JPEG 3 version-number marker is well defined, this code + * ought to change! + */ + ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker); + break; + } + /* Successfully processed marker, so reset state variable */ + cinfo->unread_marker = 0; + } /* end loop */ +} + + +/* + * Read a restart marker, which is expected to appear next in the datastream; + * if the marker is not there, take appropriate recovery action. + * Returns FALSE if suspension is required. + * + * This is called by the entropy decoder after it has read an appropriate + * number of MCUs. cinfo->unread_marker may be nonzero if the entropy decoder + * has already read a marker from the data source. Under normal conditions + * cinfo->unread_marker will be reset to 0 before returning; if not reset, + * it holds a marker which the decoder will be unable to read past. + */ + +METHODDEF(boolean) +read_restart_marker (j_decompress_ptr cinfo) +{ + /* Obtain a marker unless we already did. */ + /* Note that next_marker will complain if it skips any data. */ + if (cinfo->unread_marker == 0) { + if (! next_marker(cinfo)) + return FALSE; + } + + if (cinfo->unread_marker == + ((int) M_RST0 + cinfo->marker->next_restart_num)) { + /* Normal case --- swallow the marker and let entropy decoder continue */ + TRACEMS1(cinfo, 3, JTRC_RST, cinfo->marker->next_restart_num); + cinfo->unread_marker = 0; + } else { + /* Uh-oh, the restart markers have been messed up. */ + /* Let the data source manager determine how to resync. */ + if (! (*cinfo->src->resync_to_restart) (cinfo, + cinfo->marker->next_restart_num)) + return FALSE; + } + + /* Update next-restart state */ + cinfo->marker->next_restart_num = (cinfo->marker->next_restart_num + 1) & 7; + + return TRUE; +} + + +/* + * This is the default resync_to_restart method for data source managers + * to use if they don't have any better approach. Some data source managers + * may be able to back up, or may have additional knowledge about the data + * which permits a more intelligent recovery strategy; such managers would + * presumably supply their own resync method. + * + * read_restart_marker calls resync_to_restart if it finds a marker other than + * the restart marker it was expecting. (This code is *not* used unless + * a nonzero restart interval has been declared.) cinfo->unread_marker is + * the marker code actually found (might be anything, except 0 or FF). + * The desired restart marker number (0..7) is passed as a parameter. + * This routine is supposed to apply whatever error recovery strategy seems + * appropriate in order to position the input stream to the next data segment. + * Note that cinfo->unread_marker is treated as a marker appearing before + * the current data-source input point; usually it should be reset to zero + * before returning. + * Returns FALSE if suspension is required. + * + * This implementation is substantially constrained by wanting to treat the + * input as a data stream; this means we can't back up. Therefore, we have + * only the following actions to work with: + * 1. Simply discard the marker and let the entropy decoder resume at next + * byte of file. + * 2. Read forward until we find another marker, discarding intervening + * data. (In theory we could look ahead within the current bufferload, + * without having to discard data if we don't find the desired marker. + * This idea is not implemented here, in part because it makes behavior + * dependent on buffer size and chance buffer-boundary positions.) + * 3. Leave the marker unread (by failing to zero cinfo->unread_marker). + * This will cause the entropy decoder to process an empty data segment, + * inserting dummy zeroes, and then we will reprocess the marker. + * + * #2 is appropriate if we think the desired marker lies ahead, while #3 is + * appropriate if the found marker is a future restart marker (indicating + * that we have missed the desired restart marker, probably because it got + * corrupted). + * We apply #2 or #3 if the found marker is a restart marker no more than + * two counts behind or ahead of the expected one. We also apply #2 if the + * found marker is not a legal JPEG marker code (it's certainly bogus data). + * If the found marker is a restart marker more than 2 counts away, we do #1 + * (too much risk that the marker is erroneous; with luck we will be able to + * resync at some future point). + * For any valid non-restart JPEG marker, we apply #3. This keeps us from + * overrunning the end of a scan. An implementation limited to single-scan + * files might find it better to apply #2 for markers other than EOI, since + * any other marker would have to be bogus data in that case. + */ + +GLOBAL(boolean) +jpeg_resync_to_restart (j_decompress_ptr cinfo, int desired) +{ + int marker = cinfo->unread_marker; + int action = 1; + + /* Always put up a warning. */ + WARNMS2(cinfo, JWRN_MUST_RESYNC, marker, desired); + + /* Outer loop handles repeated decision after scanning forward. */ + for (;;) { + if (marker < (int) M_SOF0) + action = 2; /* invalid marker */ + else if (marker < (int) M_RST0 || marker > (int) M_RST7) + action = 3; /* valid non-restart marker */ + else { + if (marker == ((int) M_RST0 + ((desired+1) & 7)) || + marker == ((int) M_RST0 + ((desired+2) & 7))) + action = 3; /* one of the next two expected restarts */ + else if (marker == ((int) M_RST0 + ((desired-1) & 7)) || + marker == ((int) M_RST0 + ((desired-2) & 7))) + action = 2; /* a prior restart, so advance */ + else + action = 1; /* desired restart or too far away */ + } + TRACEMS2(cinfo, 4, JTRC_RECOVERY_ACTION, marker, action); + switch (action) { + case 1: + /* Discard marker and let entropy decoder resume processing. */ + cinfo->unread_marker = 0; + return TRUE; + case 2: + /* Scan to the next marker, and repeat the decision loop. */ + if (! next_marker(cinfo)) + return FALSE; + marker = cinfo->unread_marker; + break; + case 3: + /* Return without advancing past this marker. */ + /* Entropy decoder will be forced to process an empty segment. */ + return TRUE; + } + } /* end loop */ +} + + +/* + * Reset marker processing state to begin a fresh datastream. + */ + +METHODDEF(void) +reset_marker_reader (j_decompress_ptr cinfo) +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + + cinfo->comp_info = NULL; /* until allocated by get_sof */ + cinfo->input_scan_number = 0; /* no SOS seen yet */ + cinfo->unread_marker = 0; /* no pending marker */ + marker->pub.saw_SOI = FALSE; /* set internal state too */ + marker->pub.saw_SOF = FALSE; + marker->pub.discarded_bytes = 0; + marker->cur_marker = NULL; +} + + +/* + * Initialize the marker reader module. + * This is called only once, when the decompression object is created. + */ + +GLOBAL(void) +jinit_marker_reader (j_decompress_ptr cinfo) +{ + my_marker_ptr marker; + int i; + + /* Create subobject in permanent pool */ + marker = (my_marker_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(my_marker_reader)); + cinfo->marker = (struct jpeg_marker_reader *) marker; + /* Initialize public method pointers */ + marker->pub.reset_marker_reader = reset_marker_reader; + marker->pub.read_markers = read_markers; + marker->pub.read_restart_marker = read_restart_marker; + /* Initialize COM/APPn processing. + * By default, we examine and then discard APP0 and APP14, + * but simply discard COM and all other APPn. + */ + marker->process_COM = skip_variable; + marker->length_limit_COM = 0; + for (i = 0; i < 16; i++) { + marker->process_APPn[i] = skip_variable; + marker->length_limit_APPn[i] = 0; + } + marker->process_APPn[0] = get_interesting_appn; + marker->process_APPn[14] = get_interesting_appn; + /* Reset marker processing state */ + reset_marker_reader(cinfo); +} + + +/* + * Control saving of COM and APPn markers into marker_list. + */ + +#ifdef SAVE_MARKERS_SUPPORTED + +GLOBAL(void) +jpeg_save_markers (j_decompress_ptr cinfo, int marker_code, + unsigned int length_limit) +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + long maxlength; + jpeg_marker_parser_method processor; + + /* Length limit mustn't be larger than what we can allocate + * (should only be a concern in a 16-bit environment). + */ + maxlength = cinfo->mem->max_alloc_chunk - SIZEOF(struct jpeg_marker_struct); + if (((long) length_limit) > maxlength) + length_limit = (unsigned int) maxlength; + + /* Choose processor routine to use. + * APP0/APP14 have special requirements. + */ + if (length_limit) { + processor = save_marker; + /* If saving APP0/APP14, save at least enough for our internal use. */ + if (marker_code == (int) M_APP0 && length_limit < APP0_DATA_LEN) + length_limit = APP0_DATA_LEN; + else if (marker_code == (int) M_APP14 && length_limit < APP14_DATA_LEN) + length_limit = APP14_DATA_LEN; + } else { + processor = skip_variable; + /* If discarding APP0/APP14, use our regular on-the-fly processor. */ + if (marker_code == (int) M_APP0 || marker_code == (int) M_APP14) + processor = get_interesting_appn; + } + + if (marker_code == (int) M_COM) { + marker->process_COM = processor; + marker->length_limit_COM = length_limit; + } else if (marker_code >= (int) M_APP0 && marker_code <= (int) M_APP15) { + marker->process_APPn[marker_code - (int) M_APP0] = processor; + marker->length_limit_APPn[marker_code - (int) M_APP0] = length_limit; + } else + ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code); +} + +#endif /* SAVE_MARKERS_SUPPORTED */ + + +/* + * Install a special processing method for COM or APPn markers. + */ + +GLOBAL(void) +jpeg_set_marker_processor (j_decompress_ptr cinfo, int marker_code, + jpeg_marker_parser_method routine) +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + + if (marker_code == (int) M_COM) + marker->process_COM = routine; + else if (marker_code >= (int) M_APP0 && marker_code <= (int) M_APP15) + marker->process_APPn[marker_code - (int) M_APP0] = routine; + else + ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code); +} diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jdmaster.c b/lc-continuity/mk4/modimage/jpeg-6b/jdmaster.c new file mode 100644 index 0000000000000000000000000000000000000000..2802c5b7b29757e27b561ccccedba169deb9b42c --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jdmaster.c @@ -0,0 +1,557 @@ +/* + * jdmaster.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains master control logic for the JPEG decompressor. + * These routines are concerned with selecting the modules to be executed + * and with determining the number of passes and the work to be done in each + * pass. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Private state */ + +typedef struct { + struct jpeg_decomp_master pub; /* public fields */ + + int pass_number; /* # of passes completed */ + + boolean using_merged_upsample; /* TRUE if using merged upsample/cconvert */ + + /* Saved references to initialized quantizer modules, + * in case we need to switch modes. + */ + struct jpeg_color_quantizer * quantizer_1pass; + struct jpeg_color_quantizer * quantizer_2pass; +} my_decomp_master; + +typedef my_decomp_master * my_master_ptr; + + +/* + * Determine whether merged upsample/color conversion should be used. + * CRUCIAL: this must match the actual capabilities of jdmerge.c! + */ + +LOCAL(boolean) +use_merged_upsample (j_decompress_ptr cinfo) +{ +#ifdef UPSAMPLE_MERGING_SUPPORTED + /* Merging is the equivalent of plain box-filter upsampling */ + if (cinfo->do_fancy_upsampling || cinfo->CCIR601_sampling) + return FALSE; + /* jdmerge.c only supports YCC=>RGB color conversion */ + if (cinfo->jpeg_color_space != JCS_YCbCr || cinfo->num_components != 3 || + cinfo->out_color_space != JCS_RGB || + cinfo->out_color_components != RGB_PIXELSIZE) + return FALSE; + /* and it only handles 2h1v or 2h2v sampling ratios */ + if (cinfo->comp_info[0].h_samp_factor != 2 || + cinfo->comp_info[1].h_samp_factor != 1 || + cinfo->comp_info[2].h_samp_factor != 1 || + cinfo->comp_info[0].v_samp_factor > 2 || + cinfo->comp_info[1].v_samp_factor != 1 || + cinfo->comp_info[2].v_samp_factor != 1) + return FALSE; + /* furthermore, it doesn't work if we've scaled the IDCTs differently */ + if (cinfo->comp_info[0].DCT_scaled_size != cinfo->min_DCT_scaled_size || + cinfo->comp_info[1].DCT_scaled_size != cinfo->min_DCT_scaled_size || + cinfo->comp_info[2].DCT_scaled_size != cinfo->min_DCT_scaled_size) + return FALSE; + /* ??? also need to test for upsample-time rescaling, when & if supported */ + return TRUE; /* by golly, it'll work... */ +#else + return FALSE; +#endif +} + + +/* + * Compute output image dimensions and related values. + * NOTE: this is exported for possible use by application. + * Hence it mustn't do anything that can't be done twice. + * Also note that it may be called before the master module is initialized! + */ + +GLOBAL(void) +jpeg_calc_output_dimensions (j_decompress_ptr cinfo) +/* Do computations that are needed before master selection phase */ +{ +#ifdef IDCT_SCALING_SUPPORTED + int ci; + jpeg_component_info *compptr; +#endif + + /* Prevent application from calling me at wrong times */ + if (cinfo->global_state != DSTATE_READY) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + +#ifdef IDCT_SCALING_SUPPORTED + + /* Compute actual output image dimensions and DCT scaling choices. */ + if (cinfo->scale_num * 8 <= cinfo->scale_denom) { + /* Provide 1/8 scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, 8L); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, 8L); + cinfo->min_DCT_scaled_size = 1; + } else if (cinfo->scale_num * 4 <= cinfo->scale_denom) { + /* Provide 1/4 scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, 4L); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, 4L); + cinfo->min_DCT_scaled_size = 2; + } else if (cinfo->scale_num * 2 <= cinfo->scale_denom) { + /* Provide 1/2 scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, 2L); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, 2L); + cinfo->min_DCT_scaled_size = 4; + } else { + /* Provide 1/1 scaling */ + cinfo->output_width = cinfo->image_width; + cinfo->output_height = cinfo->image_height; + cinfo->min_DCT_scaled_size = DCTSIZE; + } + /* In selecting the actual DCT scaling for each component, we try to + * scale up the chroma components via IDCT scaling rather than upsampling. + * This saves time if the upsampler gets to use 1:1 scaling. + * Note this code assumes that the supported DCT scalings are powers of 2. + */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + int ssize = cinfo->min_DCT_scaled_size; + while (ssize < DCTSIZE && + (compptr->h_samp_factor * ssize * 2 <= + cinfo->max_h_samp_factor * cinfo->min_DCT_scaled_size) && + (compptr->v_samp_factor * ssize * 2 <= + cinfo->max_v_samp_factor * cinfo->min_DCT_scaled_size)) { + ssize = ssize * 2; + } + compptr->DCT_scaled_size = ssize; + } + + /* Recompute downsampled dimensions of components; + * application needs to know these if using raw downsampled data. + */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Size in samples, after IDCT scaling */ + compptr->downsampled_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * + (long) (compptr->h_samp_factor * compptr->DCT_scaled_size), + (long) (cinfo->max_h_samp_factor * DCTSIZE)); + compptr->downsampled_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * + (long) (compptr->v_samp_factor * compptr->DCT_scaled_size), + (long) (cinfo->max_v_samp_factor * DCTSIZE)); + } + +#else /* !IDCT_SCALING_SUPPORTED */ + + /* Hardwire it to "no scaling" */ + cinfo->output_width = cinfo->image_width; + cinfo->output_height = cinfo->image_height; + /* jdinput.c has already initialized DCT_scaled_size to DCTSIZE, + * and has computed unscaled downsampled_width and downsampled_height. + */ + +#endif /* IDCT_SCALING_SUPPORTED */ + + /* Report number of components in selected colorspace. */ + /* Probably this should be in the color conversion module... */ + switch (cinfo->out_color_space) { + case JCS_GRAYSCALE: + cinfo->out_color_components = 1; + break; + case JCS_RGB: +#if RGB_PIXELSIZE != 3 + cinfo->out_color_components = RGB_PIXELSIZE; + break; +#endif /* else share code with YCbCr */ + case JCS_YCbCr: + cinfo->out_color_components = 3; + break; + case JCS_CMYK: + case JCS_YCCK: + cinfo->out_color_components = 4; + break; + default: /* else must be same colorspace as in file */ + cinfo->out_color_components = cinfo->num_components; + break; + } + cinfo->output_components = (cinfo->quantize_colors ? 1 : + cinfo->out_color_components); + + /* See if upsampler will want to emit more than one row at a time */ + if (use_merged_upsample(cinfo)) + cinfo->rec_outbuf_height = cinfo->max_v_samp_factor; + else + cinfo->rec_outbuf_height = 1; +} + + +/* + * Several decompression processes need to range-limit values to the range + * 0..MAXJSAMPLE; the input value may fall somewhat outside this range + * due to noise introduced by quantization, roundoff error, etc. These + * processes are inner loops and need to be as fast as possible. On most + * machines, particularly CPUs with pipelines or instruction prefetch, + * a (subscript-check-less) C table lookup + * x = sample_range_limit[x]; + * is faster than explicit tests + * if (x < 0) x = 0; + * else if (x > MAXJSAMPLE) x = MAXJSAMPLE; + * These processes all use a common table prepared by the routine below. + * + * For most steps we can mathematically guarantee that the initial value + * of x is within MAXJSAMPLE+1 of the legal range, so a table running from + * -(MAXJSAMPLE+1) to 2*MAXJSAMPLE+1 is sufficient. But for the initial + * limiting step (just after the IDCT), a wildly out-of-range value is + * possible if the input data is corrupt. To avoid any chance of indexing + * off the end of memory and getting a bad-pointer trap, we perform the + * post-IDCT limiting thus: + * x = range_limit[x & MASK]; + * where MASK is 2 bits wider than legal sample data, ie 10 bits for 8-bit + * samples. Under normal circumstances this is more than enough range and + * a correct output will be generated; with bogus input data the mask will + * cause wraparound, and we will safely generate a bogus-but-in-range output. + * For the post-IDCT step, we want to convert the data from signed to unsigned + * representation by adding CENTERJSAMPLE at the same time that we limit it. + * So the post-IDCT limiting table ends up looking like this: + * CENTERJSAMPLE,CENTERJSAMPLE+1,...,MAXJSAMPLE, + * MAXJSAMPLE (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times), + * 0 (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times), + * 0,1,...,CENTERJSAMPLE-1 + * Negative inputs select values from the upper half of the table after + * masking. + * + * We can save some space by overlapping the start of the post-IDCT table + * with the simpler range limiting table. The post-IDCT table begins at + * sample_range_limit + CENTERJSAMPLE. + * + * Note that the table is allocated in near data space on PCs; it's small + * enough and used often enough to justify this. + */ + +LOCAL(void) +prepare_range_limit_table (j_decompress_ptr cinfo) +/* Allocate and fill in the sample_range_limit table */ +{ + JSAMPLE * table; + int i; + + table = (JSAMPLE *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (5 * (MAXJSAMPLE+1) + CENTERJSAMPLE) * SIZEOF(JSAMPLE)); + table += (MAXJSAMPLE+1); /* allow negative subscripts of simple table */ + cinfo->sample_range_limit = table; + /* First segment of "simple" table: limit[x] = 0 for x < 0 */ + MEMZERO(table - (MAXJSAMPLE+1), (MAXJSAMPLE+1) * SIZEOF(JSAMPLE)); + /* Main part of "simple" table: limit[x] = x */ + for (i = 0; i <= MAXJSAMPLE; i++) + table[i] = (JSAMPLE) i; + table += CENTERJSAMPLE; /* Point to where post-IDCT table starts */ + /* End of simple table, rest of first half of post-IDCT table */ + for (i = CENTERJSAMPLE; i < 2*(MAXJSAMPLE+1); i++) + table[i] = MAXJSAMPLE; + /* Second half of post-IDCT table */ + MEMZERO(table + (2 * (MAXJSAMPLE+1)), + (2 * (MAXJSAMPLE+1) - CENTERJSAMPLE) * SIZEOF(JSAMPLE)); + MEMCOPY(table + (4 * (MAXJSAMPLE+1) - CENTERJSAMPLE), + cinfo->sample_range_limit, CENTERJSAMPLE * SIZEOF(JSAMPLE)); +} + + +/* + * Master selection of decompression modules. + * This is done once at jpeg_start_decompress time. We determine + * which modules will be used and give them appropriate initialization calls. + * We also initialize the decompressor input side to begin consuming data. + * + * Since jpeg_read_header has finished, we know what is in the SOF + * and (first) SOS markers. We also have all the application parameter + * settings. + */ + +LOCAL(void) +master_selection (j_decompress_ptr cinfo) +{ + my_master_ptr master = (my_master_ptr) cinfo->master; + boolean use_c_buffer; + long samplesperrow; + JDIMENSION jd_samplesperrow; + + /* Initialize dimensions and other stuff */ + jpeg_calc_output_dimensions(cinfo); + prepare_range_limit_table(cinfo); + + /* Width of an output scanline must be representable as JDIMENSION. */ + samplesperrow = (long) cinfo->output_width * (long) cinfo->out_color_components; + jd_samplesperrow = (JDIMENSION) samplesperrow; + if ((long) jd_samplesperrow != samplesperrow) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + + /* Initialize my private state */ + master->pass_number = 0; + master->using_merged_upsample = use_merged_upsample(cinfo); + + /* Color quantizer selection */ + master->quantizer_1pass = NULL; + master->quantizer_2pass = NULL; + /* No mode changes if not using buffered-image mode. */ + if (! cinfo->quantize_colors || ! cinfo->buffered_image) { + cinfo->enable_1pass_quant = FALSE; + cinfo->enable_external_quant = FALSE; + cinfo->enable_2pass_quant = FALSE; + } + if (cinfo->quantize_colors) { + if (cinfo->raw_data_out) + ERREXIT(cinfo, JERR_NOTIMPL); + /* 2-pass quantizer only works in 3-component color space. */ + if (cinfo->out_color_components != 3) { + cinfo->enable_1pass_quant = TRUE; + cinfo->enable_external_quant = FALSE; + cinfo->enable_2pass_quant = FALSE; + cinfo->colormap = NULL; + } else if (cinfo->colormap != NULL) { + cinfo->enable_external_quant = TRUE; + } else if (cinfo->two_pass_quantize) { + cinfo->enable_2pass_quant = TRUE; + } else { + cinfo->enable_1pass_quant = TRUE; + } + + if (cinfo->enable_1pass_quant) { +#ifdef QUANT_1PASS_SUPPORTED + jinit_1pass_quantizer(cinfo); + master->quantizer_1pass = cinfo->cquantize; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } + + /* We use the 2-pass code to map to external colormaps. */ + if (cinfo->enable_2pass_quant || cinfo->enable_external_quant) { +#ifdef QUANT_2PASS_SUPPORTED + jinit_2pass_quantizer(cinfo); + master->quantizer_2pass = cinfo->cquantize; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } + /* If both quantizers are initialized, the 2-pass one is left active; + * this is necessary for starting with quantization to an external map. + */ + } + + /* Post-processing: in particular, color conversion first */ + if (! cinfo->raw_data_out) { + if (master->using_merged_upsample) { +#ifdef UPSAMPLE_MERGING_SUPPORTED + jinit_merged_upsampler(cinfo); /* does color conversion too */ +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + jinit_color_deconverter(cinfo); + jinit_upsampler(cinfo); + } + jinit_d_post_controller(cinfo, cinfo->enable_2pass_quant); + } + /* Inverse DCT */ + jinit_inverse_dct(cinfo); + /* Entropy decoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) { + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); + } else { + if (cinfo->progressive_mode) { +#ifdef D_PROGRESSIVE_SUPPORTED + jinit_phuff_decoder(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else + jinit_huff_decoder(cinfo); + } + + /* Initialize principal buffer controllers. */ + use_c_buffer = cinfo->inputctl->has_multiple_scans || cinfo->buffered_image; + jinit_d_coef_controller(cinfo, use_c_buffer); + + if (! cinfo->raw_data_out) + jinit_d_main_controller(cinfo, FALSE /* never need full buffer here */); + + /* We can now tell the memory manager to allocate virtual arrays. */ + (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); + + /* Initialize input side of decompressor to consume first scan. */ + (*cinfo->inputctl->start_input_pass) (cinfo); + +#ifdef D_MULTISCAN_FILES_SUPPORTED + /* If jpeg_start_decompress will read the whole file, initialize + * progress monitoring appropriately. The input step is counted + * as one pass. + */ + if (cinfo->progress != NULL && ! cinfo->buffered_image && + cinfo->inputctl->has_multiple_scans) { + int nscans; + /* Estimate number of scans to set pass_limit. */ + if (cinfo->progressive_mode) { + /* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */ + nscans = 2 + 3 * cinfo->num_components; + } else { + /* For a nonprogressive multiscan file, estimate 1 scan per component. */ + nscans = cinfo->num_components; + } + cinfo->progress->pass_counter = 0L; + cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans; + cinfo->progress->completed_passes = 0; + cinfo->progress->total_passes = (cinfo->enable_2pass_quant ? 3 : 2); + /* Count the input pass as done */ + master->pass_number++; + } +#endif /* D_MULTISCAN_FILES_SUPPORTED */ +} + + +/* + * Per-pass setup. + * This is called at the beginning of each output pass. We determine which + * modules will be active during this pass and give them appropriate + * start_pass calls. We also set is_dummy_pass to indicate whether this + * is a "real" output pass or a dummy pass for color quantization. + * (In the latter case, jdapistd.c will crank the pass to completion.) + */ + +METHODDEF(void) +prepare_for_output_pass (j_decompress_ptr cinfo) +{ + my_master_ptr master = (my_master_ptr) cinfo->master; + + if (master->pub.is_dummy_pass) { +#ifdef QUANT_2PASS_SUPPORTED + /* Final pass of 2-pass quantization */ + master->pub.is_dummy_pass = FALSE; + (*cinfo->cquantize->start_pass) (cinfo, FALSE); + (*cinfo->post->start_pass) (cinfo, JBUF_CRANK_DEST); + (*cinfo->main->start_pass) (cinfo, JBUF_CRANK_DEST); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif /* QUANT_2PASS_SUPPORTED */ + } else { + if (cinfo->quantize_colors && cinfo->colormap == NULL) { + /* Select new quantization method */ + if (cinfo->two_pass_quantize && cinfo->enable_2pass_quant) { + cinfo->cquantize = master->quantizer_2pass; + master->pub.is_dummy_pass = TRUE; + } else if (cinfo->enable_1pass_quant) { + cinfo->cquantize = master->quantizer_1pass; + } else { + ERREXIT(cinfo, JERR_MODE_CHANGE); + } + } + (*cinfo->idct->start_pass) (cinfo); + (*cinfo->coef->start_output_pass) (cinfo); + if (! cinfo->raw_data_out) { + if (! master->using_merged_upsample) + (*cinfo->cconvert->start_pass) (cinfo); + (*cinfo->upsample->start_pass) (cinfo); + if (cinfo->quantize_colors) + (*cinfo->cquantize->start_pass) (cinfo, master->pub.is_dummy_pass); + (*cinfo->post->start_pass) (cinfo, + (master->pub.is_dummy_pass ? JBUF_SAVE_AND_PASS : JBUF_PASS_THRU)); + (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU); + } + } + + /* Set up progress monitor's pass info if present */ + if (cinfo->progress != NULL) { + cinfo->progress->completed_passes = master->pass_number; + cinfo->progress->total_passes = master->pass_number + + (master->pub.is_dummy_pass ? 2 : 1); + /* In buffered-image mode, we assume one more output pass if EOI not + * yet reached, but no more passes if EOI has been reached. + */ + if (cinfo->buffered_image && ! cinfo->inputctl->eoi_reached) { + cinfo->progress->total_passes += (cinfo->enable_2pass_quant ? 2 : 1); + } + } +} + + +/* + * Finish up at end of an output pass. + */ + +METHODDEF(void) +finish_output_pass (j_decompress_ptr cinfo) +{ + my_master_ptr master = (my_master_ptr) cinfo->master; + + if (cinfo->quantize_colors) + (*cinfo->cquantize->finish_pass) (cinfo); + master->pass_number++; +} + + +#ifdef D_MULTISCAN_FILES_SUPPORTED + +/* + * Switch to a new external colormap between output passes. + */ + +GLOBAL(void) +jpeg_new_colormap (j_decompress_ptr cinfo) +{ + my_master_ptr master = (my_master_ptr) cinfo->master; + + /* Prevent application from calling me at wrong times */ + if (cinfo->global_state != DSTATE_BUFIMAGE) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + if (cinfo->quantize_colors && cinfo->enable_external_quant && + cinfo->colormap != NULL) { + /* Select 2-pass quantizer for external colormap use */ + cinfo->cquantize = master->quantizer_2pass; + /* Notify quantizer of colormap change */ + (*cinfo->cquantize->new_color_map) (cinfo); + master->pub.is_dummy_pass = FALSE; /* just in case */ + } else + ERREXIT(cinfo, JERR_MODE_CHANGE); +} + +#endif /* D_MULTISCAN_FILES_SUPPORTED */ + + +/* + * Initialize master decompression control and select active modules. + * This is performed at the start of jpeg_start_decompress. + */ + +GLOBAL(void) +jinit_master_decompress (j_decompress_ptr cinfo) +{ + my_master_ptr master; + + master = (my_master_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_decomp_master)); + cinfo->master = (struct jpeg_decomp_master *) master; + master->pub.prepare_for_output_pass = prepare_for_output_pass; + master->pub.finish_output_pass = finish_output_pass; + + master->pub.is_dummy_pass = FALSE; + + master_selection(cinfo); +} diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jdmerge.c b/lc-continuity/mk4/modimage/jpeg-6b/jdmerge.c new file mode 100644 index 0000000000000000000000000000000000000000..37444468c2370a71f1317a50ddaf3287e3e04969 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jdmerge.c @@ -0,0 +1,400 @@ +/* + * jdmerge.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains code for merged upsampling/color conversion. + * + * This file combines functions from jdsample.c and jdcolor.c; + * read those files first to understand what's going on. + * + * When the chroma components are to be upsampled by simple replication + * (ie, box filtering), we can save some work in color conversion by + * calculating all the output pixels corresponding to a pair of chroma + * samples at one time. In the conversion equations + * R = Y + K1 * Cr + * G = Y + K2 * Cb + K3 * Cr + * B = Y + K4 * Cb + * only the Y term varies among the group of pixels corresponding to a pair + * of chroma samples, so the rest of the terms can be calculated just once. + * At typical sampling ratios, this eliminates half or three-quarters of the + * multiplications needed for color conversion. + * + * This file currently provides implementations for the following cases: + * YCbCr => RGB color conversion only. + * Sampling ratios of 2h1v or 2h2v. + * No scaling needed at upsample time. + * Corner-aligned (non-CCIR601) sampling alignment. + * Other special cases could be added, but in most applications these are + * the only common cases. (For uncommon cases we fall back on the more + * general code in jdsample.c and jdcolor.c.) + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + +#ifdef UPSAMPLE_MERGING_SUPPORTED + + +/* Private subobject */ + +typedef struct { + struct jpeg_upsampler pub; /* public fields */ + + /* Pointer to routine to do actual upsampling/conversion of one row group */ + JMETHOD(void, upmethod, (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, + JSAMPARRAY output_buf)); + + /* Private state for YCC->RGB conversion */ + int * Cr_r_tab; /* => table for Cr to R conversion */ + int * Cb_b_tab; /* => table for Cb to B conversion */ + INT32 * Cr_g_tab; /* => table for Cr to G conversion */ + INT32 * Cb_g_tab; /* => table for Cb to G conversion */ + + /* For 2:1 vertical sampling, we produce two output rows at a time. + * We need a "spare" row buffer to hold the second output row if the + * application provides just a one-row buffer; we also use the spare + * to discard the dummy last row if the image height is odd. + */ + JSAMPROW spare_row; + boolean spare_full; /* T if spare buffer is occupied */ + + JDIMENSION out_row_width; /* samples per output row */ + JDIMENSION rows_to_go; /* counts rows remaining in image */ +} my_upsampler; + +typedef my_upsampler * my_upsample_ptr; + +#define SCALEBITS 16 /* speediest right-shift on some machines */ +#define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) +#define FIX(x) ((INT32) ((x) * (1L<RGB colorspace conversion. + * This is taken directly from jdcolor.c; see that file for more info. + */ + +LOCAL(void) +build_ycc_rgb_table (j_decompress_ptr cinfo) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + int i; + INT32 x; + SHIFT_TEMPS + + upsample->Cr_r_tab = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(int)); + upsample->Cb_b_tab = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(int)); + upsample->Cr_g_tab = (INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(INT32)); + upsample->Cb_g_tab = (INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(INT32)); + + for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { + /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ + /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ + /* Cr=>R value is nearest int to 1.40200 * x */ + upsample->Cr_r_tab[i] = (int) + RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS); + /* Cb=>B value is nearest int to 1.77200 * x */ + upsample->Cb_b_tab[i] = (int) + RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS); + /* Cr=>G value is scaled-up -0.71414 * x */ + upsample->Cr_g_tab[i] = (- FIX(0.71414)) * x; + /* Cb=>G value is scaled-up -0.34414 * x */ + /* We also add in ONE_HALF so that need not do it in inner loop */ + upsample->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF; + } +} + + +/* + * Initialize for an upsampling pass. + */ + +METHODDEF(void) +start_pass_merged_upsample (j_decompress_ptr cinfo) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + + /* Mark the spare buffer empty */ + upsample->spare_full = FALSE; + /* Initialize total-height counter for detecting bottom of image */ + upsample->rows_to_go = cinfo->output_height; +} + + +/* + * Control routine to do upsampling (and color conversion). + * + * The control routine just handles the row buffering considerations. + */ + +METHODDEF(void) +merged_2v_upsample (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +/* 2:1 vertical sampling case: may need a spare row. */ +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + JSAMPROW work_ptrs[2]; + JDIMENSION num_rows; /* number of rows returned to caller */ + + if (upsample->spare_full) { + /* If we have a spare row saved from a previous cycle, just return it. */ + jcopy_sample_rows(& upsample->spare_row, 0, output_buf + *out_row_ctr, 0, + 1, upsample->out_row_width); + num_rows = 1; + upsample->spare_full = FALSE; + } else { + /* Figure number of rows to return to caller. */ + num_rows = 2; + /* Not more than the distance to the end of the image. */ + if (num_rows > upsample->rows_to_go) + num_rows = upsample->rows_to_go; + /* And not more than what the client can accept: */ + out_rows_avail -= *out_row_ctr; + if (num_rows > out_rows_avail) + num_rows = out_rows_avail; + /* Create output pointer array for upsampler. */ + work_ptrs[0] = output_buf[*out_row_ctr]; + if (num_rows > 1) { + work_ptrs[1] = output_buf[*out_row_ctr + 1]; + } else { + work_ptrs[1] = upsample->spare_row; + upsample->spare_full = TRUE; + } + /* Now do the upsampling. */ + (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, work_ptrs); + } + + /* Adjust counts */ + *out_row_ctr += num_rows; + upsample->rows_to_go -= num_rows; + /* When the buffer is emptied, declare this input row group consumed */ + if (! upsample->spare_full) + (*in_row_group_ctr)++; +} + + +METHODDEF(void) +merged_1v_upsample (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +/* 1:1 vertical sampling case: much easier, never need a spare row. */ +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + + /* Just do the upsampling. */ + (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, + output_buf + *out_row_ctr); + /* Adjust counts */ + (*out_row_ctr)++; + (*in_row_group_ctr)++; +} + + +/* + * These are the routines invoked by the control routines to do + * the actual upsampling/conversion. One row group is processed per call. + * + * Note: since we may be writing directly into application-supplied buffers, + * we have to be honest about the output width; we can't assume the buffer + * has been rounded up to an even width. + */ + + +/* + * Upsample and color convert for the case of 2:1 horizontal and 1:1 vertical. + */ + +METHODDEF(void) +h2v1_merged_upsample (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, + JSAMPARRAY output_buf) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + register int y, cred, cgreen, cblue; + int cb, cr; + register JSAMPROW outptr; + JSAMPROW inptr0, inptr1, inptr2; + JDIMENSION col; + /* copy these pointers into registers if possible */ + register JSAMPLE * range_limit = cinfo->sample_range_limit; + int * Crrtab = upsample->Cr_r_tab; + int * Cbbtab = upsample->Cb_b_tab; + INT32 * Crgtab = upsample->Cr_g_tab; + INT32 * Cbgtab = upsample->Cb_g_tab; + SHIFT_TEMPS + + inptr0 = input_buf[0][in_row_group_ctr]; + inptr1 = input_buf[1][in_row_group_ctr]; + inptr2 = input_buf[2][in_row_group_ctr]; + outptr = output_buf[0]; + /* Loop for each pair of output pixels */ + for (col = cinfo->output_width >> 1; col > 0; col--) { + /* Do the chroma part of the calculation */ + cb = GETJSAMPLE(*inptr1++); + cr = GETJSAMPLE(*inptr2++); + cred = Crrtab[cr]; + cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); + cblue = Cbbtab[cb]; + /* Fetch 2 Y values and emit 2 pixels */ + y = GETJSAMPLE(*inptr0++); + outptr[RGB_RED] = range_limit[y + cred]; + outptr[RGB_GREEN] = range_limit[y + cgreen]; + outptr[RGB_BLUE] = range_limit[y + cblue]; + outptr += RGB_PIXELSIZE; + y = GETJSAMPLE(*inptr0++); + outptr[RGB_RED] = range_limit[y + cred]; + outptr[RGB_GREEN] = range_limit[y + cgreen]; + outptr[RGB_BLUE] = range_limit[y + cblue]; + outptr += RGB_PIXELSIZE; + } + /* If image width is odd, do the last output column separately */ + if (cinfo->output_width & 1) { + cb = GETJSAMPLE(*inptr1); + cr = GETJSAMPLE(*inptr2); + cred = Crrtab[cr]; + cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); + cblue = Cbbtab[cb]; + y = GETJSAMPLE(*inptr0); + outptr[RGB_RED] = range_limit[y + cred]; + outptr[RGB_GREEN] = range_limit[y + cgreen]; + outptr[RGB_BLUE] = range_limit[y + cblue]; + } +} + + +/* + * Upsample and color convert for the case of 2:1 horizontal and 2:1 vertical. + */ + +METHODDEF(void) +h2v2_merged_upsample (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, + JSAMPARRAY output_buf) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + register int y, cred, cgreen, cblue; + int cb, cr; + register JSAMPROW outptr0, outptr1; + JSAMPROW inptr00, inptr01, inptr1, inptr2; + JDIMENSION col; + /* copy these pointers into registers if possible */ + register JSAMPLE * range_limit = cinfo->sample_range_limit; + int * Crrtab = upsample->Cr_r_tab; + int * Cbbtab = upsample->Cb_b_tab; + INT32 * Crgtab = upsample->Cr_g_tab; + INT32 * Cbgtab = upsample->Cb_g_tab; + SHIFT_TEMPS + + inptr00 = input_buf[0][in_row_group_ctr*2]; + inptr01 = input_buf[0][in_row_group_ctr*2 + 1]; + inptr1 = input_buf[1][in_row_group_ctr]; + inptr2 = input_buf[2][in_row_group_ctr]; + outptr0 = output_buf[0]; + outptr1 = output_buf[1]; + /* Loop for each group of output pixels */ + for (col = cinfo->output_width >> 1; col > 0; col--) { + /* Do the chroma part of the calculation */ + cb = GETJSAMPLE(*inptr1++); + cr = GETJSAMPLE(*inptr2++); + cred = Crrtab[cr]; + cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); + cblue = Cbbtab[cb]; + /* Fetch 4 Y values and emit 4 pixels */ + y = GETJSAMPLE(*inptr00++); + outptr0[RGB_RED] = range_limit[y + cred]; + outptr0[RGB_GREEN] = range_limit[y + cgreen]; + outptr0[RGB_BLUE] = range_limit[y + cblue]; + outptr0 += RGB_PIXELSIZE; + y = GETJSAMPLE(*inptr00++); + outptr0[RGB_RED] = range_limit[y + cred]; + outptr0[RGB_GREEN] = range_limit[y + cgreen]; + outptr0[RGB_BLUE] = range_limit[y + cblue]; + outptr0 += RGB_PIXELSIZE; + y = GETJSAMPLE(*inptr01++); + outptr1[RGB_RED] = range_limit[y + cred]; + outptr1[RGB_GREEN] = range_limit[y + cgreen]; + outptr1[RGB_BLUE] = range_limit[y + cblue]; + outptr1 += RGB_PIXELSIZE; + y = GETJSAMPLE(*inptr01++); + outptr1[RGB_RED] = range_limit[y + cred]; + outptr1[RGB_GREEN] = range_limit[y + cgreen]; + outptr1[RGB_BLUE] = range_limit[y + cblue]; + outptr1 += RGB_PIXELSIZE; + } + /* If image width is odd, do the last output column separately */ + if (cinfo->output_width & 1) { + cb = GETJSAMPLE(*inptr1); + cr = GETJSAMPLE(*inptr2); + cred = Crrtab[cr]; + cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); + cblue = Cbbtab[cb]; + y = GETJSAMPLE(*inptr00); + outptr0[RGB_RED] = range_limit[y + cred]; + outptr0[RGB_GREEN] = range_limit[y + cgreen]; + outptr0[RGB_BLUE] = range_limit[y + cblue]; + y = GETJSAMPLE(*inptr01); + outptr1[RGB_RED] = range_limit[y + cred]; + outptr1[RGB_GREEN] = range_limit[y + cgreen]; + outptr1[RGB_BLUE] = range_limit[y + cblue]; + } +} + + +/* + * Module initialization routine for merged upsampling/color conversion. + * + * NB: this is called under the conditions determined by use_merged_upsample() + * in jdmaster.c. That routine MUST correspond to the actual capabilities + * of this module; no safety checks are made here. + */ + +GLOBAL(void) +jinit_merged_upsampler (j_decompress_ptr cinfo) +{ + my_upsample_ptr upsample; + + upsample = (my_upsample_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_upsampler)); + cinfo->upsample = (struct jpeg_upsampler *) upsample; + upsample->pub.start_pass = start_pass_merged_upsample; + upsample->pub.need_context_rows = FALSE; + + upsample->out_row_width = cinfo->output_width * cinfo->out_color_components; + + if (cinfo->max_v_samp_factor == 2) { + upsample->pub.upsample = merged_2v_upsample; + upsample->upmethod = h2v2_merged_upsample; + /* Allocate a spare row buffer */ + upsample->spare_row = (JSAMPROW) + (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (size_t) (upsample->out_row_width * SIZEOF(JSAMPLE))); + } else { + upsample->pub.upsample = merged_1v_upsample; + upsample->upmethod = h2v1_merged_upsample; + /* No spare row needed */ + upsample->spare_row = NULL; + } + + build_ycc_rgb_table(cinfo); +} + +#endif /* UPSAMPLE_MERGING_SUPPORTED */ diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jdphuff.c b/lc-continuity/mk4/modimage/jpeg-6b/jdphuff.c new file mode 100644 index 0000000000000000000000000000000000000000..22678099451a7f606c5cb2652940d569ba7885d5 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jdphuff.c @@ -0,0 +1,668 @@ +/* + * jdphuff.c + * + * Copyright (C) 1995-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains Huffman entropy decoding routines for progressive JPEG. + * + * Much of the complexity here has to do with supporting input suspension. + * If the data source module demands suspension, we want to be able to back + * up to the start of the current MCU. To do this, we copy state variables + * into local working storage, and update them back to the permanent + * storage only upon successful completion of an MCU. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdhuff.h" /* Declarations shared with jdhuff.c */ + + +#ifdef D_PROGRESSIVE_SUPPORTED + +/* + * Expanded entropy decoder object for progressive Huffman decoding. + * + * The savable_state subrecord contains fields that change within an MCU, + * but must not be updated permanently until we complete the MCU. + */ + +typedef struct { + unsigned int EOBRUN; /* remaining EOBs in EOBRUN */ + int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ +} savable_state; + +/* This macro is to work around compilers with missing or broken + * structure assignment. You'll need to fix this code if you have + * such a compiler and you change MAX_COMPS_IN_SCAN. + */ + +#ifndef NO_STRUCT_ASSIGN +#define ASSIGN_STATE(dest,src) ((dest) = (src)) +#else +#if MAX_COMPS_IN_SCAN == 4 +#define ASSIGN_STATE(dest,src) \ + ((dest).EOBRUN = (src).EOBRUN, \ + (dest).last_dc_val[0] = (src).last_dc_val[0], \ + (dest).last_dc_val[1] = (src).last_dc_val[1], \ + (dest).last_dc_val[2] = (src).last_dc_val[2], \ + (dest).last_dc_val[3] = (src).last_dc_val[3]) +#endif +#endif + + +typedef struct { + struct jpeg_entropy_decoder pub; /* public fields */ + + /* These fields are loaded into local variables at start of each MCU. + * In case of suspension, we exit WITHOUT updating them. + */ + bitread_perm_state bitstate; /* Bit buffer at start of MCU */ + savable_state saved; /* Other state at start of MCU */ + + /* These fields are NOT loaded into local working state. */ + unsigned int restarts_to_go; /* MCUs left in this restart interval */ + + /* Pointers to derived tables (these workspaces have image lifespan) */ + d_derived_tbl * derived_tbls[NUM_HUFF_TBLS]; + + d_derived_tbl * ac_derived_tbl; /* active table during an AC scan */ +} phuff_entropy_decoder; + +typedef phuff_entropy_decoder * phuff_entropy_ptr; + +/* Forward declarations */ +METHODDEF(boolean) decode_mcu_DC_first JPP((j_decompress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(boolean) decode_mcu_AC_first JPP((j_decompress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(boolean) decode_mcu_DC_refine JPP((j_decompress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(boolean) decode_mcu_AC_refine JPP((j_decompress_ptr cinfo, + JBLOCKROW *MCU_data)); + + +/* + * Initialize for a Huffman-compressed scan. + */ + +METHODDEF(void) +start_pass_phuff_decoder (j_decompress_ptr cinfo) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + boolean is_DC_band, bad; + int ci, coefi, tbl; + int *coef_bit_ptr; + jpeg_component_info * compptr; + + is_DC_band = (cinfo->Ss == 0); + + /* Validate scan parameters */ + bad = FALSE; + if (is_DC_band) { + if (cinfo->Se != 0) + bad = TRUE; + } else { + /* need not check Ss/Se < 0 since they came from unsigned bytes */ + if (cinfo->Ss > cinfo->Se || cinfo->Se >= DCTSIZE2) + bad = TRUE; + /* AC scans may have only one component */ + if (cinfo->comps_in_scan != 1) + bad = TRUE; + } + if (cinfo->Ah != 0) { + /* Successive approximation refinement scan: must have Al = Ah-1. */ + if (cinfo->Al != cinfo->Ah-1) + bad = TRUE; + } + if (cinfo->Al > 13) /* need not check for < 0 */ + bad = TRUE; + /* Arguably the maximum Al value should be less than 13 for 8-bit precision, + * but the spec doesn't say so, and we try to be liberal about what we + * accept. Note: large Al values could result in out-of-range DC + * coefficients during early scans, leading to bizarre displays due to + * overflows in the IDCT math. But we won't crash. + */ + if (bad) + ERREXIT4(cinfo, JERR_BAD_PROGRESSION, + cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); + /* Update progression status, and verify that scan order is legal. + * Note that inter-scan inconsistencies are treated as warnings + * not fatal errors ... not clear if this is right way to behave. + */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + int cindex = cinfo->cur_comp_info[ci]->component_index; + coef_bit_ptr = & cinfo->coef_bits[cindex][0]; + if (!is_DC_band && coef_bit_ptr[0] < 0) /* AC without prior DC scan */ + WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, 0); + for (coefi = cinfo->Ss; coefi <= cinfo->Se; coefi++) { + int expected = (coef_bit_ptr[coefi] < 0) ? 0 : coef_bit_ptr[coefi]; + if (cinfo->Ah != expected) + WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, coefi); + coef_bit_ptr[coefi] = cinfo->Al; + } + } + + /* Select MCU decoding routine */ + if (cinfo->Ah == 0) { + if (is_DC_band) + entropy->pub.decode_mcu = decode_mcu_DC_first; + else + entropy->pub.decode_mcu = decode_mcu_AC_first; + } else { + if (is_DC_band) + entropy->pub.decode_mcu = decode_mcu_DC_refine; + else + entropy->pub.decode_mcu = decode_mcu_AC_refine; + } + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* Make sure requested tables are present, and compute derived tables. + * We may build same derived table more than once, but it's not expensive. + */ + if (is_DC_band) { + if (cinfo->Ah == 0) { /* DC refinement needs no table */ + tbl = compptr->dc_tbl_no; + jpeg_make_d_derived_tbl(cinfo, TRUE, tbl, + & entropy->derived_tbls[tbl]); + } + } else { + tbl = compptr->ac_tbl_no; + jpeg_make_d_derived_tbl(cinfo, FALSE, tbl, + & entropy->derived_tbls[tbl]); + /* remember the single active table */ + entropy->ac_derived_tbl = entropy->derived_tbls[tbl]; + } + /* Initialize DC predictions to 0 */ + entropy->saved.last_dc_val[ci] = 0; + } + + /* Initialize bitread state variables */ + entropy->bitstate.bits_left = 0; + entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */ + entropy->pub.insufficient_data = FALSE; + + /* Initialize private state variables */ + entropy->saved.EOBRUN = 0; + + /* Initialize restart counter */ + entropy->restarts_to_go = cinfo->restart_interval; +} + + +/* + * Figure F.12: extend sign bit. + * On some machines, a shift and add will be faster than a table lookup. + */ + +#ifdef AVOID_TABLES + +#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x)) + +#else + +#define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x)) + +static const int extend_test[16] = /* entry n is 2**(n-1) */ + { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, + 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 }; + +static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */ + { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1, + ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1, + ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1, + ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 }; + +#endif /* AVOID_TABLES */ + + +/* + * Check for a restart marker & resynchronize decoder. + * Returns FALSE if must suspend. + */ + +LOCAL(boolean) +process_restart (j_decompress_ptr cinfo) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + int ci; + + /* Throw away any unused bits remaining in bit buffer; */ + /* include any full bytes in next_marker's count of discarded bytes */ + cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8; + entropy->bitstate.bits_left = 0; + + /* Advance past the RSTn marker */ + if (! (*cinfo->marker->read_restart_marker) (cinfo)) + return FALSE; + + /* Re-initialize DC predictions to 0 */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) + entropy->saved.last_dc_val[ci] = 0; + /* Re-init EOB run count, too */ + entropy->saved.EOBRUN = 0; + + /* Reset restart counter */ + entropy->restarts_to_go = cinfo->restart_interval; + + /* Reset out-of-data flag, unless read_restart_marker left us smack up + * against a marker. In that case we will end up treating the next data + * segment as empty, and we can avoid producing bogus output pixels by + * leaving the flag set. + */ + if (cinfo->unread_marker == 0) + entropy->pub.insufficient_data = FALSE; + + return TRUE; +} + + +/* + * Huffman MCU decoding. + * Each of these routines decodes and returns one MCU's worth of + * Huffman-compressed coefficients. + * The coefficients are reordered from zigzag order into natural array order, + * but are not dequantized. + * + * The i'th block of the MCU is stored into the block pointed to by + * MCU_data[i]. WE ASSUME THIS AREA IS INITIALLY ZEROED BY THE CALLER. + * + * We return FALSE if data source requested suspension. In that case no + * changes have been made to permanent state. (Exception: some output + * coefficients may already have been assigned. This is harmless for + * spectral selection, since we'll just re-assign them on the next call. + * Successive approximation AC refinement has to be more careful, however.) + */ + +/* + * MCU decoding for DC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + int Al = cinfo->Al; + register int s, r; + int blkn, ci; + JBLOCKROW block; + BITREAD_STATE_VARS; + savable_state state; + d_derived_tbl * tbl; + jpeg_component_info * compptr; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* If we've run out of data, just leave the MCU set to zeroes. + * This way, we return uniform gray for the remainder of the segment. + */ + if (! entropy->pub.insufficient_data) { + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(state, entropy->saved); + + /* Outer loop handles each block in the MCU */ + + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + block = MCU_data[blkn]; + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + tbl = entropy->derived_tbls[compptr->dc_tbl_no]; + + /* Decode a single block's worth of coefficients */ + + /* Section F.2.2.1: decode the DC coefficient difference */ + HUFF_DECODE(s, br_state, tbl, return FALSE, label1); + if (s) { + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + } + + /* Convert DC difference to actual value, update last_dc_val */ + s += state.last_dc_val[ci]; + state.last_dc_val[ci] = s; + /* Scale and output the coefficient (assumes jpeg_natural_order[0]=0) */ + (*block)[0] = (JCOEF) (s << Al); + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(entropy->saved, state); + } + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; +} + + +/* + * MCU decoding for AC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + int Se = cinfo->Se; + int Al = cinfo->Al; + register int s, k, r; + unsigned int EOBRUN; + JBLOCKROW block; + BITREAD_STATE_VARS; + d_derived_tbl * tbl; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* If we've run out of data, just leave the MCU set to zeroes. + * This way, we return uniform gray for the remainder of the segment. + */ + if (! entropy->pub.insufficient_data) { + + /* Load up working state. + * We can avoid loading/saving bitread state if in an EOB run. + */ + EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */ + + /* There is always only one block per MCU */ + + if (EOBRUN > 0) /* if it's a band of zeroes... */ + EOBRUN--; /* ...process it now (we do nothing) */ + else { + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + block = MCU_data[0]; + tbl = entropy->ac_derived_tbl; + + for (k = cinfo->Ss; k <= Se; k++) { + HUFF_DECODE(s, br_state, tbl, return FALSE, label2); + r = s >> 4; + s &= 15; + if (s) { + k += r; + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + /* Scale and output coefficient in natural (dezigzagged) order */ + (*block)[jpeg_natural_order[k]] = (JCOEF) (s << Al); + } else { + if (r == 15) { /* ZRL */ + k += 15; /* skip 15 zeroes in band */ + } else { /* EOBr, run length is 2^r + appended bits */ + EOBRUN = 1 << r; + if (r) { /* EOBr, r > 0 */ + CHECK_BIT_BUFFER(br_state, r, return FALSE); + r = GET_BITS(r); + EOBRUN += r; + } + EOBRUN--; /* this band is processed at this moment */ + break; /* force end-of-band */ + } + } + } + + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + } + + /* Completed MCU, so update state */ + entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */ + } + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; +} + + +/* + * MCU decoding for DC successive approximation refinement scan. + * Note: we assume such scans can be multi-component, although the spec + * is not very clear on the point. + */ + +METHODDEF(boolean) +decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + int p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ + int blkn; + JBLOCKROW block; + BITREAD_STATE_VARS; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* Not worth the cycles to check insufficient_data here, + * since we will not change the data anyway if we read zeroes. + */ + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + + /* Outer loop handles each block in the MCU */ + + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + block = MCU_data[blkn]; + + /* Encoded data is simply the next bit of the two's-complement DC value */ + CHECK_BIT_BUFFER(br_state, 1, return FALSE); + if (GET_BITS(1)) + (*block)[0] |= p1; + /* Note: since we use |=, repeating the assignment later is safe */ + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; +} + + +/* + * MCU decoding for AC successive approximation refinement scan. + */ + +METHODDEF(boolean) +decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + int Se = cinfo->Se; + int p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ + int m1 = (-1) << cinfo->Al; /* -1 in the bit position being coded */ + register int s, k, r; + unsigned int EOBRUN; + JBLOCKROW block; + JCOEFPTR thiscoef; + BITREAD_STATE_VARS; + d_derived_tbl * tbl; + int num_newnz; + int newnz_pos[DCTSIZE2]; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* If we've run out of data, don't modify the MCU. + */ + if (! entropy->pub.insufficient_data) { + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */ + + /* There is always only one block per MCU */ + block = MCU_data[0]; + tbl = entropy->ac_derived_tbl; + + /* If we are forced to suspend, we must undo the assignments to any newly + * nonzero coefficients in the block, because otherwise we'd get confused + * next time about which coefficients were already nonzero. + * But we need not undo addition of bits to already-nonzero coefficients; + * instead, we can test the current bit to see if we already did it. + */ + num_newnz = 0; + + /* initialize coefficient loop counter to start of band */ + k = cinfo->Ss; + + if (EOBRUN == 0) { + for (; k <= Se; k++) { + HUFF_DECODE(s, br_state, tbl, goto undoit, label3); + r = s >> 4; + s &= 15; + if (s) { + if (s != 1) /* size of new coef should always be 1 */ + WARNMS(cinfo, JWRN_HUFF_BAD_CODE); + CHECK_BIT_BUFFER(br_state, 1, goto undoit); + if (GET_BITS(1)) + s = p1; /* newly nonzero coef is positive */ + else + s = m1; /* newly nonzero coef is negative */ + } else { + if (r != 15) { + EOBRUN = 1 << r; /* EOBr, run length is 2^r + appended bits */ + if (r) { + CHECK_BIT_BUFFER(br_state, r, goto undoit); + r = GET_BITS(r); + EOBRUN += r; + } + break; /* rest of block is handled by EOB logic */ + } + /* note s = 0 for processing ZRL */ + } + /* Advance over already-nonzero coefs and r still-zero coefs, + * appending correction bits to the nonzeroes. A correction bit is 1 + * if the absolute value of the coefficient must be increased. + */ + do { + thiscoef = *block + jpeg_natural_order[k]; + if (*thiscoef != 0) { + CHECK_BIT_BUFFER(br_state, 1, goto undoit); + if (GET_BITS(1)) { + if ((*thiscoef & p1) == 0) { /* do nothing if already set it */ + if (*thiscoef >= 0) + *thiscoef += p1; + else + *thiscoef += m1; + } + } + } else { + if (--r < 0) + break; /* reached target zero coefficient */ + } + k++; + } while (k <= Se); + if (s) { + int pos = jpeg_natural_order[k]; + /* Output newly nonzero coefficient */ + (*block)[pos] = (JCOEF) s; + /* Remember its position in case we have to suspend */ + newnz_pos[num_newnz++] = pos; + } + } + } + + if (EOBRUN > 0) { + /* Scan any remaining coefficient positions after the end-of-band + * (the last newly nonzero coefficient, if any). Append a correction + * bit to each already-nonzero coefficient. A correction bit is 1 + * if the absolute value of the coefficient must be increased. + */ + for (; k <= Se; k++) { + thiscoef = *block + jpeg_natural_order[k]; + if (*thiscoef != 0) { + CHECK_BIT_BUFFER(br_state, 1, goto undoit); + if (GET_BITS(1)) { + if ((*thiscoef & p1) == 0) { /* do nothing if already changed it */ + if (*thiscoef >= 0) + *thiscoef += p1; + else + *thiscoef += m1; + } + } + } + } + /* Count one block completed in EOB run */ + EOBRUN--; + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */ + } + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; + +undoit: + /* Re-zero any output coefficients that we made newly nonzero */ + while (num_newnz > 0) + (*block)[newnz_pos[--num_newnz]] = 0; + + return FALSE; +} + + +/* + * Module initialization routine for progressive Huffman entropy decoding. + */ + +GLOBAL(void) +jinit_phuff_decoder (j_decompress_ptr cinfo) +{ + phuff_entropy_ptr entropy; + int *coef_bit_ptr; + int ci, i; + + entropy = (phuff_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(phuff_entropy_decoder)); + cinfo->entropy = (struct jpeg_entropy_decoder *) entropy; + entropy->pub.start_pass = start_pass_phuff_decoder; + + /* Mark derived tables unallocated */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + entropy->derived_tbls[i] = NULL; + } + + /* Create progression status table */ + cinfo->coef_bits = (int (*)[DCTSIZE2]) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + cinfo->num_components*DCTSIZE2*SIZEOF(int)); + coef_bit_ptr = & cinfo->coef_bits[0][0]; + for (ci = 0; ci < cinfo->num_components; ci++) + for (i = 0; i < DCTSIZE2; i++) + *coef_bit_ptr++ = -1; +} + +#endif /* D_PROGRESSIVE_SUPPORTED */ diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jdpostct.c b/lc-continuity/mk4/modimage/jpeg-6b/jdpostct.c new file mode 100644 index 0000000000000000000000000000000000000000..571563d728e7135996cc982b8f8dfba3d69a9846 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jdpostct.c @@ -0,0 +1,290 @@ +/* + * jdpostct.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the decompression postprocessing controller. + * This controller manages the upsampling, color conversion, and color + * quantization/reduction steps; specifically, it controls the buffering + * between upsample/color conversion and color quantization/reduction. + * + * If no color quantization/reduction is required, then this module has no + * work to do, and it just hands off to the upsample/color conversion code. + * An integrated upsample/convert/quantize process would replace this module + * entirely. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_d_post_controller pub; /* public fields */ + + /* Color quantization source buffer: this holds output data from + * the upsample/color conversion step to be passed to the quantizer. + * For two-pass color quantization, we need a full-image buffer; + * for one-pass operation, a strip buffer is sufficient. + */ + jvirt_sarray_ptr whole_image; /* virtual array, or NULL if one-pass */ + JSAMPARRAY buffer; /* strip buffer, or current strip of virtual */ + JDIMENSION strip_height; /* buffer size in rows */ + /* for two-pass mode only: */ + JDIMENSION starting_row; /* row # of first row in current strip */ + JDIMENSION next_row; /* index of next row to fill/empty in strip */ +} my_post_controller; + +typedef my_post_controller * my_post_ptr; + + +/* Forward declarations */ +METHODDEF(void) post_process_1pass + JPP((j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); +#ifdef QUANT_2PASS_SUPPORTED +METHODDEF(void) post_process_prepass + JPP((j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); +METHODDEF(void) post_process_2pass + JPP((j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); +#endif + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_dpost (j_decompress_ptr cinfo, J_BUF_MODE pass_mode) +{ + my_post_ptr post = (my_post_ptr) cinfo->post; + + switch (pass_mode) { + case JBUF_PASS_THRU: + if (cinfo->quantize_colors) { + /* Single-pass processing with color quantization. */ + post->pub.post_process_data = post_process_1pass; + /* We could be doing buffered-image output before starting a 2-pass + * color quantization; in that case, jinit_d_post_controller did not + * allocate a strip buffer. Use the virtual-array buffer as workspace. + */ + if (post->buffer == NULL) { + post->buffer = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, post->whole_image, + (JDIMENSION) 0, post->strip_height, TRUE); + } + } else { + /* For single-pass processing without color quantization, + * I have no work to do; just call the upsampler directly. + */ + post->pub.post_process_data = cinfo->upsample->upsample; + } + break; +#ifdef QUANT_2PASS_SUPPORTED + case JBUF_SAVE_AND_PASS: + /* First pass of 2-pass quantization */ + if (post->whole_image == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + post->pub.post_process_data = post_process_prepass; + break; + case JBUF_CRANK_DEST: + /* Second pass of 2-pass quantization */ + if (post->whole_image == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + post->pub.post_process_data = post_process_2pass; + break; +#endif /* QUANT_2PASS_SUPPORTED */ + default: + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + break; + } + post->starting_row = post->next_row = 0; +} + + +/* + * Process some data in the one-pass (strip buffer) case. + * This is used for color precision reduction as well as one-pass quantization. + */ + +METHODDEF(void) +post_process_1pass (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_post_ptr post = (my_post_ptr) cinfo->post; + JDIMENSION num_rows, max_rows; + + /* Fill the buffer, but not more than what we can dump out in one go. */ + /* Note we rely on the upsampler to detect bottom of image. */ + max_rows = out_rows_avail - *out_row_ctr; + if (max_rows > post->strip_height) + max_rows = post->strip_height; + num_rows = 0; + (*cinfo->upsample->upsample) (cinfo, + input_buf, in_row_group_ctr, in_row_groups_avail, + post->buffer, &num_rows, max_rows); + /* Quantize and emit data. */ + (*cinfo->cquantize->color_quantize) (cinfo, + post->buffer, output_buf + *out_row_ctr, (int) num_rows); + *out_row_ctr += num_rows; +} + + +#ifdef QUANT_2PASS_SUPPORTED + +/* + * Process some data in the first pass of 2-pass quantization. + */ + +METHODDEF(void) +post_process_prepass (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_post_ptr post = (my_post_ptr) cinfo->post; + JDIMENSION old_next_row, num_rows; + + /* Reposition virtual buffer if at start of strip. */ + if (post->next_row == 0) { + post->buffer = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, post->whole_image, + post->starting_row, post->strip_height, TRUE); + } + + /* Upsample some data (up to a strip height's worth). */ + old_next_row = post->next_row; + (*cinfo->upsample->upsample) (cinfo, + input_buf, in_row_group_ctr, in_row_groups_avail, + post->buffer, &post->next_row, post->strip_height); + + /* Allow quantizer to scan new data. No data is emitted, */ + /* but we advance out_row_ctr so outer loop can tell when we're done. */ + if (post->next_row > old_next_row) { + num_rows = post->next_row - old_next_row; + (*cinfo->cquantize->color_quantize) (cinfo, post->buffer + old_next_row, + (JSAMPARRAY) NULL, (int) num_rows); + *out_row_ctr += num_rows; + } + + /* Advance if we filled the strip. */ + if (post->next_row >= post->strip_height) { + post->starting_row += post->strip_height; + post->next_row = 0; + } +} + + +/* + * Process some data in the second pass of 2-pass quantization. + */ + +METHODDEF(void) +post_process_2pass (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_post_ptr post = (my_post_ptr) cinfo->post; + JDIMENSION num_rows, max_rows; + + /* Reposition virtual buffer if at start of strip. */ + if (post->next_row == 0) { + post->buffer = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, post->whole_image, + post->starting_row, post->strip_height, FALSE); + } + + /* Determine number of rows to emit. */ + num_rows = post->strip_height - post->next_row; /* available in strip */ + max_rows = out_rows_avail - *out_row_ctr; /* available in output area */ + if (num_rows > max_rows) + num_rows = max_rows; + /* We have to check bottom of image here, can't depend on upsampler. */ + max_rows = cinfo->output_height - post->starting_row; + if (num_rows > max_rows) + num_rows = max_rows; + + /* Quantize and emit data. */ + (*cinfo->cquantize->color_quantize) (cinfo, + post->buffer + post->next_row, output_buf + *out_row_ctr, + (int) num_rows); + *out_row_ctr += num_rows; + + /* Advance if we filled the strip. */ + post->next_row += num_rows; + if (post->next_row >= post->strip_height) { + post->starting_row += post->strip_height; + post->next_row = 0; + } +} + +#endif /* QUANT_2PASS_SUPPORTED */ + + +/* + * Initialize postprocessing controller. + */ + +GLOBAL(void) +jinit_d_post_controller (j_decompress_ptr cinfo, boolean need_full_buffer) +{ + my_post_ptr post; + + post = (my_post_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_post_controller)); + cinfo->post = (struct jpeg_d_post_controller *) post; + post->pub.start_pass = start_pass_dpost; + post->whole_image = NULL; /* flag for no virtual arrays */ + post->buffer = NULL; /* flag for no strip buffer */ + + /* Create the quantization buffer, if needed */ + if (cinfo->quantize_colors) { + /* The buffer strip height is max_v_samp_factor, which is typically + * an efficient number of rows for upsampling to return. + * (In the presence of output rescaling, we might want to be smarter?) + */ + post->strip_height = (JDIMENSION) cinfo->max_v_samp_factor; + if (need_full_buffer) { + /* Two-pass color quantization: need full-image storage. */ + /* We round up the number of rows to a multiple of the strip height. */ +#ifdef QUANT_2PASS_SUPPORTED + post->whole_image = (*cinfo->mem->request_virt_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, + cinfo->output_width * cinfo->out_color_components, + (JDIMENSION) jround_up((long) cinfo->output_height, + (long) post->strip_height), + post->strip_height); +#else + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); +#endif /* QUANT_2PASS_SUPPORTED */ + } else { + /* One-pass color quantization: just make a strip buffer. */ + post->buffer = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + cinfo->output_width * cinfo->out_color_components, + post->strip_height); + } + } +} diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jdsample.c b/lc-continuity/mk4/modimage/jpeg-6b/jdsample.c new file mode 100644 index 0000000000000000000000000000000000000000..80ffefb2a1ccf5ddc1530b921df0eef6e3e45c18 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jdsample.c @@ -0,0 +1,478 @@ +/* + * jdsample.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains upsampling routines. + * + * Upsampling input data is counted in "row groups". A row group + * is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size) + * sample rows of each component. Upsampling will normally produce + * max_v_samp_factor pixel rows from each row group (but this could vary + * if the upsampler is applying a scale factor of its own). + * + * An excellent reference for image resampling is + * Digital Image Warping, George Wolberg, 1990. + * Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Pointer to routine to upsample a single component */ +typedef JMETHOD(void, upsample1_ptr, + (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)); + +/* Private subobject */ + +typedef struct { + struct jpeg_upsampler pub; /* public fields */ + + /* Color conversion buffer. When using separate upsampling and color + * conversion steps, this buffer holds one upsampled row group until it + * has been color converted and output. + * Note: we do not allocate any storage for component(s) which are full-size, + * ie do not need rescaling. The corresponding entry of color_buf[] is + * simply set to point to the input data array, thereby avoiding copying. + */ + JSAMPARRAY color_buf[MAX_COMPONENTS]; + + /* Per-component upsampling method pointers */ + upsample1_ptr methods[MAX_COMPONENTS]; + + int next_row_out; /* counts rows emitted from color_buf */ + JDIMENSION rows_to_go; /* counts rows remaining in image */ + + /* Height of an input row group for each component. */ + int rowgroup_height[MAX_COMPONENTS]; + + /* These arrays save pixel expansion factors so that int_expand need not + * recompute them each time. They are unused for other upsampling methods. + */ + UINT8 h_expand[MAX_COMPONENTS]; + UINT8 v_expand[MAX_COMPONENTS]; +} my_upsampler; + +typedef my_upsampler * my_upsample_ptr; + + +/* + * Initialize for an upsampling pass. + */ + +METHODDEF(void) +start_pass_upsample (j_decompress_ptr cinfo) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + + /* Mark the conversion buffer empty */ + upsample->next_row_out = cinfo->max_v_samp_factor; + /* Initialize total-height counter for detecting bottom of image */ + upsample->rows_to_go = cinfo->output_height; +} + + +/* + * Control routine to do upsampling (and color conversion). + * + * In this version we upsample each component independently. + * We upsample one row group into the conversion buffer, then apply + * color conversion a row at a time. + */ + +METHODDEF(void) +sep_upsample (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + int ci; + jpeg_component_info * compptr; + JDIMENSION num_rows; + + /* Fill the conversion buffer, if it's empty */ + if (upsample->next_row_out >= cinfo->max_v_samp_factor) { + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Invoke per-component upsample method. Notice we pass a POINTER + * to color_buf[ci], so that fullsize_upsample can change it. + */ + (*upsample->methods[ci]) (cinfo, compptr, + input_buf[ci] + (*in_row_group_ctr * upsample->rowgroup_height[ci]), + upsample->color_buf + ci); + } + upsample->next_row_out = 0; + } + + /* Color-convert and emit rows */ + + /* How many we have in the buffer: */ + num_rows = (JDIMENSION) (cinfo->max_v_samp_factor - upsample->next_row_out); + /* Not more than the distance to the end of the image. Need this test + * in case the image height is not a multiple of max_v_samp_factor: + */ + if (num_rows > upsample->rows_to_go) + num_rows = upsample->rows_to_go; + /* And not more than what the client can accept: */ + out_rows_avail -= *out_row_ctr; + if (num_rows > out_rows_avail) + num_rows = out_rows_avail; + + (*cinfo->cconvert->color_convert) (cinfo, upsample->color_buf, + (JDIMENSION) upsample->next_row_out, + output_buf + *out_row_ctr, + (int) num_rows); + + /* Adjust counts */ + *out_row_ctr += num_rows; + upsample->rows_to_go -= num_rows; + upsample->next_row_out += num_rows; + /* When the buffer is emptied, declare this input row group consumed */ + if (upsample->next_row_out >= cinfo->max_v_samp_factor) + (*in_row_group_ctr)++; +} + + +/* + * These are the routines invoked by sep_upsample to upsample pixel values + * of a single component. One row group is processed per call. + */ + + +/* + * For full-size components, we just make color_buf[ci] point at the + * input buffer, and thus avoid copying any data. Note that this is + * safe only because sep_upsample doesn't declare the input row group + * "consumed" until we are done color converting and emitting it. + */ + +METHODDEF(void) +fullsize_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + *output_data_ptr = input_data; +} + + +/* + * This is a no-op version used for "uninteresting" components. + * These components will not be referenced by color conversion. + */ + +METHODDEF(void) +noop_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + *output_data_ptr = NULL; /* safety check */ +} + + +/* + * This version handles any integral sampling ratios. + * This is not used for typical JPEG files, so it need not be fast. + * Nor, for that matter, is it particularly accurate: the algorithm is + * simple replication of the input pixel onto the corresponding output + * pixels. The hi-falutin sampling literature refers to this as a + * "box filter". A box filter tends to introduce visible artifacts, + * so if you are actually going to use 3:1 or 4:1 sampling ratios + * you would be well advised to improve this code. + */ + +METHODDEF(void) +int_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + JSAMPARRAY output_data = *output_data_ptr; + register JSAMPROW inptr, outptr; + register JSAMPLE invalue; + register int h; + JSAMPROW outend; + int h_expand, v_expand; + int inrow, outrow; + + h_expand = upsample->h_expand[compptr->component_index]; + v_expand = upsample->v_expand[compptr->component_index]; + + inrow = outrow = 0; + while (outrow < cinfo->max_v_samp_factor) { + /* Generate one output row with proper horizontal expansion */ + inptr = input_data[inrow]; + outptr = output_data[outrow]; + outend = outptr + cinfo->output_width; + while (outptr < outend) { + invalue = *inptr++; /* don't need GETJSAMPLE() here */ + for (h = h_expand; h > 0; h--) { + *outptr++ = invalue; + } + } + /* Generate any additional output rows by duplicating the first one */ + if (v_expand > 1) { + jcopy_sample_rows(output_data, outrow, output_data, outrow+1, + v_expand-1, cinfo->output_width); + } + inrow++; + outrow += v_expand; + } +} + + +/* + * Fast processing for the common case of 2:1 horizontal and 1:1 vertical. + * It's still a box filter. + */ + +METHODDEF(void) +h2v1_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + JSAMPARRAY output_data = *output_data_ptr; + register JSAMPROW inptr, outptr; + register JSAMPLE invalue; + JSAMPROW outend; + int inrow; + + for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) { + inptr = input_data[inrow]; + outptr = output_data[inrow]; + outend = outptr + cinfo->output_width; + while (outptr < outend) { + invalue = *inptr++; /* don't need GETJSAMPLE() here */ + *outptr++ = invalue; + *outptr++ = invalue; + } + } +} + + +/* + * Fast processing for the common case of 2:1 horizontal and 2:1 vertical. + * It's still a box filter. + */ + +METHODDEF(void) +h2v2_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + JSAMPARRAY output_data = *output_data_ptr; + register JSAMPROW inptr, outptr; + register JSAMPLE invalue; + JSAMPROW outend; + int inrow, outrow; + + inrow = outrow = 0; + while (outrow < cinfo->max_v_samp_factor) { + inptr = input_data[inrow]; + outptr = output_data[outrow]; + outend = outptr + cinfo->output_width; + while (outptr < outend) { + invalue = *inptr++; /* don't need GETJSAMPLE() here */ + *outptr++ = invalue; + *outptr++ = invalue; + } + jcopy_sample_rows(output_data, outrow, output_data, outrow+1, + 1, cinfo->output_width); + inrow++; + outrow += 2; + } +} + + +/* + * Fancy processing for the common case of 2:1 horizontal and 1:1 vertical. + * + * The upsampling algorithm is linear interpolation between pixel centers, + * also known as a "triangle filter". This is a good compromise between + * speed and visual quality. The centers of the output pixels are 1/4 and 3/4 + * of the way between input pixel centers. + * + * A note about the "bias" calculations: when rounding fractional values to + * integer, we do not want to always round 0.5 up to the next integer. + * If we did that, we'd introduce a noticeable bias towards larger values. + * Instead, this code is arranged so that 0.5 will be rounded up or down at + * alternate pixel locations (a simple ordered dither pattern). + */ + +METHODDEF(void) +h2v1_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + JSAMPARRAY output_data = *output_data_ptr; + register JSAMPROW inptr, outptr; + register int invalue; + register JDIMENSION colctr; + int inrow; + + for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) { + inptr = input_data[inrow]; + outptr = output_data[inrow]; + /* Special case for first column */ + invalue = GETJSAMPLE(*inptr++); + *outptr++ = (JSAMPLE) invalue; + *outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(*inptr) + 2) >> 2); + + for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) { + /* General case: 3/4 * nearer pixel + 1/4 * further pixel */ + invalue = GETJSAMPLE(*inptr++) * 3; + *outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(inptr[-2]) + 1) >> 2); + *outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(*inptr) + 2) >> 2); + } + + /* Special case for last column */ + invalue = GETJSAMPLE(*inptr); + *outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(inptr[-1]) + 1) >> 2); + *outptr++ = (JSAMPLE) invalue; + } +} + + +/* + * Fancy processing for the common case of 2:1 horizontal and 2:1 vertical. + * Again a triangle filter; see comments for h2v1 case, above. + * + * It is OK for us to reference the adjacent input rows because we demanded + * context from the main buffer controller (see initialization code). + */ + +METHODDEF(void) +h2v2_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + JSAMPARRAY output_data = *output_data_ptr; + register JSAMPROW inptr0, inptr1, outptr; +#if BITS_IN_JSAMPLE == 8 + register int thiscolsum, lastcolsum, nextcolsum; +#else + register INT32 thiscolsum, lastcolsum, nextcolsum; +#endif + register JDIMENSION colctr; + int inrow, outrow, v; + + inrow = outrow = 0; + while (outrow < cinfo->max_v_samp_factor) { + for (v = 0; v < 2; v++) { + /* inptr0 points to nearest input row, inptr1 points to next nearest */ + inptr0 = input_data[inrow]; + if (v == 0) /* next nearest is row above */ + inptr1 = input_data[inrow-1]; + else /* next nearest is row below */ + inptr1 = input_data[inrow+1]; + outptr = output_data[outrow++]; + + /* Special case for first column */ + thiscolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); + nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); + *outptr++ = (JSAMPLE) ((thiscolsum * 4 + 8) >> 4); + *outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4); + lastcolsum = thiscolsum; thiscolsum = nextcolsum; + + for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) { + /* General case: 3/4 * nearer pixel + 1/4 * further pixel in each */ + /* dimension, thus 9/16, 3/16, 3/16, 1/16 overall */ + nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); + *outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4); + *outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4); + lastcolsum = thiscolsum; thiscolsum = nextcolsum; + } + + /* Special case for last column */ + *outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4); + *outptr++ = (JSAMPLE) ((thiscolsum * 4 + 7) >> 4); + } + inrow++; + } +} + + +/* + * Module initialization routine for upsampling. + */ + +GLOBAL(void) +jinit_upsampler (j_decompress_ptr cinfo) +{ + my_upsample_ptr upsample; + int ci; + jpeg_component_info * compptr; + boolean need_buffer, do_fancy; + int h_in_group, v_in_group, h_out_group, v_out_group; + + upsample = (my_upsample_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_upsampler)); + cinfo->upsample = (struct jpeg_upsampler *) upsample; + upsample->pub.start_pass = start_pass_upsample; + upsample->pub.upsample = sep_upsample; + upsample->pub.need_context_rows = FALSE; /* until we find out differently */ + + if (cinfo->CCIR601_sampling) /* this isn't supported */ + ERREXIT(cinfo, JERR_CCIR601_NOTIMPL); + + /* jdmainct.c doesn't support context rows when min_DCT_scaled_size = 1, + * so don't ask for it. + */ + do_fancy = cinfo->do_fancy_upsampling && cinfo->min_DCT_scaled_size > 1; + + /* Verify we can handle the sampling factors, select per-component methods, + * and create storage as needed. + */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Compute size of an "input group" after IDCT scaling. This many samples + * are to be converted to max_h_samp_factor * max_v_samp_factor pixels. + */ + h_in_group = (compptr->h_samp_factor * compptr->DCT_scaled_size) / + cinfo->min_DCT_scaled_size; + v_in_group = (compptr->v_samp_factor * compptr->DCT_scaled_size) / + cinfo->min_DCT_scaled_size; + h_out_group = cinfo->max_h_samp_factor; + v_out_group = cinfo->max_v_samp_factor; + upsample->rowgroup_height[ci] = v_in_group; /* save for use later */ + need_buffer = TRUE; + if (! compptr->component_needed) { + /* Don't bother to upsample an uninteresting component. */ + upsample->methods[ci] = noop_upsample; + need_buffer = FALSE; + } else if (h_in_group == h_out_group && v_in_group == v_out_group) { + /* Fullsize components can be processed without any work. */ + upsample->methods[ci] = fullsize_upsample; + need_buffer = FALSE; + } else if (h_in_group * 2 == h_out_group && + v_in_group == v_out_group) { + /* Special cases for 2h1v upsampling */ + if (do_fancy && compptr->downsampled_width > 2) + upsample->methods[ci] = h2v1_fancy_upsample; + else + upsample->methods[ci] = h2v1_upsample; + } else if (h_in_group * 2 == h_out_group && + v_in_group * 2 == v_out_group) { + /* Special cases for 2h2v upsampling */ + if (do_fancy && compptr->downsampled_width > 2) { + upsample->methods[ci] = h2v2_fancy_upsample; + upsample->pub.need_context_rows = TRUE; + } else + upsample->methods[ci] = h2v2_upsample; + } else if ((h_out_group % h_in_group) == 0 && + (v_out_group % v_in_group) == 0) { + /* Generic integral-factors upsampling method */ + upsample->methods[ci] = int_upsample; + upsample->h_expand[ci] = (UINT8) (h_out_group / h_in_group); + upsample->v_expand[ci] = (UINT8) (v_out_group / v_in_group); + } else + ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL); + if (need_buffer) { + upsample->color_buf[ci] = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) jround_up((long) cinfo->output_width, + (long) cinfo->max_h_samp_factor), + (JDIMENSION) cinfo->max_v_samp_factor); + } + } +} diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jdtrans.c b/lc-continuity/mk4/modimage/jpeg-6b/jdtrans.c new file mode 100644 index 0000000000000000000000000000000000000000..6c0ab715d32ab470950f6db9537381adced9741d --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jdtrans.c @@ -0,0 +1,143 @@ +/* + * jdtrans.c + * + * Copyright (C) 1995-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains library routines for transcoding decompression, + * that is, reading raw DCT coefficient arrays from an input JPEG file. + * The routines in jdapimin.c will also be needed by a transcoder. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Forward declarations */ +LOCAL(void) transdecode_master_selection JPP((j_decompress_ptr cinfo)); + + +/* + * Read the coefficient arrays from a JPEG file. + * jpeg_read_header must be completed before calling this. + * + * The entire image is read into a set of virtual coefficient-block arrays, + * one per component. The return value is a pointer to the array of + * virtual-array descriptors. These can be manipulated directly via the + * JPEG memory manager, or handed off to jpeg_write_coefficients(). + * To release the memory occupied by the virtual arrays, call + * jpeg_finish_decompress() when done with the data. + * + * An alternative usage is to simply obtain access to the coefficient arrays + * during a buffered-image-mode decompression operation. This is allowed + * after any jpeg_finish_output() call. The arrays can be accessed until + * jpeg_finish_decompress() is called. (Note that any call to the library + * may reposition the arrays, so don't rely on access_virt_barray() results + * to stay valid across library calls.) + * + * Returns NULL if suspended. This case need be checked only if + * a suspending data source is used. + */ + +GLOBAL(jvirt_barray_ptr *) +jpeg_read_coefficients (j_decompress_ptr cinfo) +{ + if (cinfo->global_state == DSTATE_READY) { + /* First call: initialize active modules */ + transdecode_master_selection(cinfo); + cinfo->global_state = DSTATE_RDCOEFS; + } + if (cinfo->global_state == DSTATE_RDCOEFS) { + /* Absorb whole file into the coef buffer */ + for (;;) { + int retcode; + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + /* Absorb some more input */ + retcode = (*cinfo->inputctl->consume_input) (cinfo); + if (retcode == JPEG_SUSPENDED) + return NULL; + if (retcode == JPEG_REACHED_EOI) + break; + /* Advance progress counter if appropriate */ + if (cinfo->progress != NULL && + (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) { + if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) { + /* startup underestimated number of scans; ratchet up one scan */ + cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows; + } + } + } + /* Set state so that jpeg_finish_decompress does the right thing */ + cinfo->global_state = DSTATE_STOPPING; + } + /* At this point we should be in state DSTATE_STOPPING if being used + * standalone, or in state DSTATE_BUFIMAGE if being invoked to get access + * to the coefficients during a full buffered-image-mode decompression. + */ + if ((cinfo->global_state == DSTATE_STOPPING || + cinfo->global_state == DSTATE_BUFIMAGE) && cinfo->buffered_image) { + return cinfo->coef->coef_arrays; + } + /* Oops, improper usage */ + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + return NULL; /* keep compiler happy */ +} + + +/* + * Master selection of decompression modules for transcoding. + * This substitutes for jdmaster.c's initialization of the full decompressor. + */ + +LOCAL(void) +transdecode_master_selection (j_decompress_ptr cinfo) +{ + /* This is effectively a buffered-image operation. */ + cinfo->buffered_image = TRUE; + + /* Entropy decoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) { + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); + } else { + if (cinfo->progressive_mode) { +#ifdef D_PROGRESSIVE_SUPPORTED + jinit_phuff_decoder(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else + jinit_huff_decoder(cinfo); + } + + /* Always get a full-image coefficient buffer. */ + jinit_d_coef_controller(cinfo, TRUE); + + /* We can now tell the memory manager to allocate virtual arrays. */ + (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); + + /* Initialize input side of decompressor to consume first scan. */ + (*cinfo->inputctl->start_input_pass) (cinfo); + + /* Initialize progress monitoring. */ + if (cinfo->progress != NULL) { + int nscans; + /* Estimate number of scans to set pass_limit. */ + if (cinfo->progressive_mode) { + /* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */ + nscans = 2 + 3 * cinfo->num_components; + } else if (cinfo->inputctl->has_multiple_scans) { + /* For a nonprogressive multiscan file, estimate 1 scan per component. */ + nscans = cinfo->num_components; + } else { + nscans = 1; + } + cinfo->progress->pass_counter = 0L; + cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans; + cinfo->progress->completed_passes = 0; + cinfo->progress->total_passes = 1; + } +} diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jerror.c b/lc-continuity/mk4/modimage/jpeg-6b/jerror.c new file mode 100644 index 0000000000000000000000000000000000000000..3da7be86a00f989d0f7a8094d4619f4d305b6c45 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jerror.c @@ -0,0 +1,252 @@ +/* + * jerror.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains simple error-reporting and trace-message routines. + * These are suitable for Unix-like systems and others where writing to + * stderr is the right thing to do. Many applications will want to replace + * some or all of these routines. + * + * If you define USE_WINDOWS_MESSAGEBOX in jconfig.h or in the makefile, + * you get a Windows-specific hack to display error messages in a dialog box. + * It ain't much, but it beats dropping error messages into the bit bucket, + * which is what happens to output to stderr under most Windows C compilers. + * + * These routines are used by both the compression and decompression code. + */ + +/* this is not a core library module, so it doesn't define JPEG_INTERNALS */ +#include "jinclude.h" +#include "jpeglib.h" +#include "jversion.h" +#include "jerror.h" + +#ifdef USE_WINDOWS_MESSAGEBOX +#include +#endif + +#ifndef EXIT_FAILURE /* define exit() codes if not provided */ +#define EXIT_FAILURE 1 +#endif + + +/* + * Create the message string table. + * We do this from the master message list in jerror.h by re-reading + * jerror.h with a suitable definition for macro JMESSAGE. + * The message table is made an external symbol just in case any applications + * want to refer to it directly. + */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_std_message_table jMsgTable +#endif + +#define JMESSAGE(code,string) string , + +const char * const jpeg_std_message_table[] = { +#include "jerror.h" + NULL +}; + + +/* + * Error exit handler: must not return to caller. + * + * Applications may override this if they want to get control back after + * an error. Typically one would longjmp somewhere instead of exiting. + * The setjmp buffer can be made a private field within an expanded error + * handler object. Note that the info needed to generate an error message + * is stored in the error object, so you can generate the message now or + * later, at your convenience. + * You should make sure that the JPEG object is cleaned up (with jpeg_abort + * or jpeg_destroy) at some point. + */ + +METHODDEF(void) +error_exit (j_common_ptr cinfo) +{ + /* Always display the message */ + (*cinfo->err->output_message) (cinfo); + + /* Let the memory manager delete any temp files before we die */ + jpeg_destroy(cinfo); + + exit(EXIT_FAILURE); +} + + +/* + * Actual output of an error or trace message. + * Applications may override this method to send JPEG messages somewhere + * other than stderr. + * + * On Windows, printing to stderr is generally completely useless, + * so we provide optional code to produce an error-dialog popup. + * Most Windows applications will still prefer to override this routine, + * but if they don't, it'll do something at least marginally useful. + * + * NOTE: to use the library in an environment that doesn't support the + * C stdio library, you may have to delete the call to fprintf() entirely, + * not just not use this routine. + */ + +METHODDEF(void) +output_message (j_common_ptr cinfo) +{ + char buffer[JMSG_LENGTH_MAX]; + + /* Create the message */ + (*cinfo->err->format_message) (cinfo, buffer); + +#ifdef USE_WINDOWS_MESSAGEBOX + /* Display it in a message dialog box */ + MessageBox(GetActiveWindow(), buffer, "JPEG Library Error", + MB_OK | MB_ICONERROR); +#else + /* Send it to stderr, adding a newline */ + fprintf(stderr, "%s\n", buffer); +#endif +} + + +/* + * Decide whether to emit a trace or warning message. + * msg_level is one of: + * -1: recoverable corrupt-data warning, may want to abort. + * 0: important advisory messages (always display to user). + * 1: first level of tracing detail. + * 2,3,...: successively more detailed tracing messages. + * An application might override this method if it wanted to abort on warnings + * or change the policy about which messages to display. + */ + +METHODDEF(void) +emit_message (j_common_ptr cinfo, int msg_level) +{ + struct jpeg_error_mgr * err = cinfo->err; + + if (msg_level < 0) { + /* It's a warning message. Since corrupt files may generate many warnings, + * the policy implemented here is to show only the first warning, + * unless trace_level >= 3. + */ + if (err->num_warnings == 0 || err->trace_level >= 3) + (*err->output_message) (cinfo); + /* Always count warnings in num_warnings. */ + err->num_warnings++; + } else { + /* It's a trace message. Show it if trace_level >= msg_level. */ + if (err->trace_level >= msg_level) + (*err->output_message) (cinfo); + } +} + + +/* + * Format a message string for the most recent JPEG error or message. + * The message is stored into buffer, which should be at least JMSG_LENGTH_MAX + * characters. Note that no '\n' character is added to the string. + * Few applications should need to override this method. + */ + +METHODDEF(void) +format_message (j_common_ptr cinfo, char * buffer) +{ + struct jpeg_error_mgr * err = cinfo->err; + int msg_code = err->msg_code; + const char * msgtext = NULL; + const char * msgptr; + char ch; + boolean isstring; + + /* Look up message string in proper table */ + if (msg_code > 0 && msg_code <= err->last_jpeg_message) { + msgtext = err->jpeg_message_table[msg_code]; + } else if (err->addon_message_table != NULL && + msg_code >= err->first_addon_message && + msg_code <= err->last_addon_message) { + msgtext = err->addon_message_table[msg_code - err->first_addon_message]; + } + + /* Defend against bogus message number */ + if (msgtext == NULL) { + err->msg_parm.i[0] = msg_code; + msgtext = err->jpeg_message_table[0]; + } + + /* Check for string parameter, as indicated by %s in the message text */ + isstring = FALSE; + msgptr = msgtext; + while ((ch = *msgptr++) != '\0') { + if (ch == '%') { + if (*msgptr == 's') isstring = TRUE; + break; + } + } + + /* Format the message into the passed buffer */ + if (isstring) + sprintf(buffer, msgtext, err->msg_parm.s); + else + sprintf(buffer, msgtext, + err->msg_parm.i[0], err->msg_parm.i[1], + err->msg_parm.i[2], err->msg_parm.i[3], + err->msg_parm.i[4], err->msg_parm.i[5], + err->msg_parm.i[6], err->msg_parm.i[7]); +} + + +/* + * Reset error state variables at start of a new image. + * This is called during compression startup to reset trace/error + * processing to default state, without losing any application-specific + * method pointers. An application might possibly want to override + * this method if it has additional error processing state. + */ + +METHODDEF(void) +reset_error_mgr (j_common_ptr cinfo) +{ + cinfo->err->num_warnings = 0; + /* trace_level is not reset since it is an application-supplied parameter */ + cinfo->err->msg_code = 0; /* may be useful as a flag for "no error" */ +} + + +/* + * Fill in the standard error-handling methods in a jpeg_error_mgr object. + * Typical call is: + * struct jpeg_compress_struct cinfo; + * struct jpeg_error_mgr err; + * + * cinfo.err = jpeg_std_error(&err); + * after which the application may override some of the methods. + */ + +GLOBAL(struct jpeg_error_mgr *) +jpeg_std_error (struct jpeg_error_mgr * err) +{ + err->error_exit = error_exit; + err->emit_message = emit_message; + err->output_message = output_message; + err->format_message = format_message; + err->reset_error_mgr = reset_error_mgr; + + err->trace_level = 0; /* default = no tracing */ + err->num_warnings = 0; /* no warnings emitted yet */ + err->msg_code = 0; /* may be useful as a flag for "no error" */ + + /* Initialize message table pointers */ + err->jpeg_message_table = jpeg_std_message_table; + err->last_jpeg_message = (int) JMSG_LASTMSGCODE - 1; + + err->addon_message_table = NULL; + err->first_addon_message = 0; /* for safety */ + err->last_addon_message = 0; + + return err; +} diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jerror.h b/lc-continuity/mk4/modimage/jpeg-6b/jerror.h new file mode 100644 index 0000000000000000000000000000000000000000..fc2fffeac297bcee557400beefb7b6ce790e79a7 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jerror.h @@ -0,0 +1,291 @@ +/* + * jerror.h + * + * Copyright (C) 1994-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file defines the error and message codes for the JPEG library. + * Edit this file to add new codes, or to translate the message strings to + * some other language. + * A set of error-reporting macros are defined too. Some applications using + * the JPEG library may wish to include this file to get the error codes + * and/or the macros. + */ + +/* + * To define the enum list of message codes, include this file without + * defining macro JMESSAGE. To create a message string table, include it + * again with a suitable JMESSAGE definition (see jerror.c for an example). + */ +#ifndef JMESSAGE +#ifndef JERROR_H +/* First time through, define the enum list */ +#define JMAKE_ENUM_LIST +#else +/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */ +#define JMESSAGE(code,string) +#endif /* JERROR_H */ +#endif /* JMESSAGE */ + +#ifdef JMAKE_ENUM_LIST + +typedef enum { + +#define JMESSAGE(code,string) code , + +#endif /* JMAKE_ENUM_LIST */ + +JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */ + +/* For maintenance convenience, list is alphabetical by message code name */ +JMESSAGE(JERR_ARITH_NOTIMPL, + "Sorry, there are legal restrictions on arithmetic coding") +JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix") +JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix") +JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode") +JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS") +JMESSAGE(JERR_BAD_DCT_COEF, "DCT coefficient out of range") +JMESSAGE(JERR_BAD_DCTSIZE, "IDCT output block size %d not supported") +JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition") +JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace") +JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace") +JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length") +JMESSAGE(JERR_BAD_LIB_VERSION, + "Wrong JPEG library version: library is %d, caller expects %d") +JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan") +JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d") +JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d") +JMESSAGE(JERR_BAD_PROGRESSION, + "Invalid progressive parameters Ss=%d Se=%d Ah=%d Al=%d") +JMESSAGE(JERR_BAD_PROG_SCRIPT, + "Invalid progressive parameters at scan script entry %d") +JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors") +JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d") +JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d") +JMESSAGE(JERR_BAD_STRUCT_SIZE, + "JPEG parameter struct mismatch: library thinks size is %u, caller expects %u") +JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access") +JMESSAGE(JERR_BUFFER_SIZE, "Buffer passed to JPEG library is too small") +JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here") +JMESSAGE(JERR_CCIR601_NOTIMPL, "CCIR601 sampling not implemented yet") +JMESSAGE(JERR_COMPONENT_COUNT, "Too many color components: %d, max %d") +JMESSAGE(JERR_CONVERSION_NOTIMPL, "Unsupported color conversion request") +JMESSAGE(JERR_DAC_INDEX, "Bogus DAC index %d") +JMESSAGE(JERR_DAC_VALUE, "Bogus DAC value 0x%x") +JMESSAGE(JERR_DHT_INDEX, "Bogus DHT index %d") +JMESSAGE(JERR_DQT_INDEX, "Bogus DQT index %d") +JMESSAGE(JERR_EMPTY_IMAGE, "Empty JPEG image (DNL not supported)") +JMESSAGE(JERR_EMS_READ, "Read from EMS failed") +JMESSAGE(JERR_EMS_WRITE, "Write to EMS failed") +JMESSAGE(JERR_EOI_EXPECTED, "Didn't expect more than one scan") +JMESSAGE(JERR_FILE_READ, "Input file read error") +JMESSAGE(JERR_FILE_WRITE, "Output file write error --- out of disk space?") +JMESSAGE(JERR_FRACT_SAMPLE_NOTIMPL, "Fractional sampling not implemented yet") +JMESSAGE(JERR_HUFF_CLEN_OVERFLOW, "Huffman code size table overflow") +JMESSAGE(JERR_HUFF_MISSING_CODE, "Missing Huffman code table entry") +JMESSAGE(JERR_IMAGE_TOO_BIG, "Maximum supported image dimension is %u pixels") +JMESSAGE(JERR_INPUT_EMPTY, "Empty input file") +JMESSAGE(JERR_INPUT_EOF, "Premature end of input file") +JMESSAGE(JERR_MISMATCHED_QUANT_TABLE, + "Cannot transcode due to multiple use of quantization table %d") +JMESSAGE(JERR_MISSING_DATA, "Scan script does not transmit all data") +JMESSAGE(JERR_MODE_CHANGE, "Invalid color quantization mode change") +JMESSAGE(JERR_NOTIMPL, "Not implemented yet") +JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time") +JMESSAGE(JERR_NO_BACKING_STORE, "Backing store not supported") +JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined") +JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image") +JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined") +JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x") +JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)") +JMESSAGE(JERR_QUANT_COMPONENTS, + "Cannot quantize more than %d color components") +JMESSAGE(JERR_QUANT_FEW_COLORS, "Cannot quantize to fewer than %d colors") +JMESSAGE(JERR_QUANT_MANY_COLORS, "Cannot quantize to more than %d colors") +JMESSAGE(JERR_SOF_DUPLICATE, "Invalid JPEG file structure: two SOF markers") +JMESSAGE(JERR_SOF_NO_SOS, "Invalid JPEG file structure: missing SOS marker") +JMESSAGE(JERR_SOF_UNSUPPORTED, "Unsupported JPEG process: SOF type 0x%02x") +JMESSAGE(JERR_SOI_DUPLICATE, "Invalid JPEG file structure: two SOI markers") +JMESSAGE(JERR_SOS_NO_SOF, "Invalid JPEG file structure: SOS before SOF") +JMESSAGE(JERR_TFILE_CREATE, "Failed to create temporary file %s") +JMESSAGE(JERR_TFILE_READ, "Read failed on temporary file") +JMESSAGE(JERR_TFILE_SEEK, "Seek failed on temporary file") +JMESSAGE(JERR_TFILE_WRITE, + "Write failed on temporary file --- out of disk space?") +JMESSAGE(JERR_TOO_LITTLE_DATA, "Application transferred too few scanlines") +JMESSAGE(JERR_UNKNOWN_MARKER, "Unsupported marker type 0x%02x") +JMESSAGE(JERR_VIRTUAL_BUG, "Virtual array controller messed up") +JMESSAGE(JERR_WIDTH_OVERFLOW, "Image too wide for this implementation") +JMESSAGE(JERR_XMS_READ, "Read from XMS failed") +JMESSAGE(JERR_XMS_WRITE, "Write to XMS failed") +JMESSAGE(JMSG_COPYRIGHT, JCOPYRIGHT) +JMESSAGE(JMSG_VERSION, JVERSION) +JMESSAGE(JTRC_16BIT_TABLES, + "Caution: quantization tables are too coarse for baseline JPEG") +JMESSAGE(JTRC_ADOBE, + "Adobe APP14 marker: version %d, flags 0x%04x 0x%04x, transform %d") +JMESSAGE(JTRC_APP0, "Unknown APP0 marker (not JFIF), length %u") +JMESSAGE(JTRC_APP14, "Unknown APP14 marker (not Adobe), length %u") +JMESSAGE(JTRC_DAC, "Define Arithmetic Table 0x%02x: 0x%02x") +JMESSAGE(JTRC_DHT, "Define Huffman Table 0x%02x") +JMESSAGE(JTRC_DQT, "Define Quantization Table %d precision %d") +JMESSAGE(JTRC_DRI, "Define Restart Interval %u") +JMESSAGE(JTRC_EMS_CLOSE, "Freed EMS handle %u") +JMESSAGE(JTRC_EMS_OPEN, "Obtained EMS handle %u") +JMESSAGE(JTRC_EOI, "End Of Image") +JMESSAGE(JTRC_HUFFBITS, " %3d %3d %3d %3d %3d %3d %3d %3d") +JMESSAGE(JTRC_JFIF, "JFIF APP0 marker: version %d.%02d, density %dx%d %d") +JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE, + "Warning: thumbnail image size does not match data length %u") +JMESSAGE(JTRC_JFIF_EXTENSION, + "JFIF extension marker: type 0x%02x, length %u") +JMESSAGE(JTRC_JFIF_THUMBNAIL, " with %d x %d thumbnail image") +JMESSAGE(JTRC_MISC_MARKER, "Miscellaneous marker 0x%02x, length %u") +JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x") +JMESSAGE(JTRC_QUANTVALS, " %4u %4u %4u %4u %4u %4u %4u %4u") +JMESSAGE(JTRC_QUANT_3_NCOLORS, "Quantizing to %d = %d*%d*%d colors") +JMESSAGE(JTRC_QUANT_NCOLORS, "Quantizing to %d colors") +JMESSAGE(JTRC_QUANT_SELECTED, "Selected %d colors for quantization") +JMESSAGE(JTRC_RECOVERY_ACTION, "At marker 0x%02x, recovery action %d") +JMESSAGE(JTRC_RST, "RST%d") +JMESSAGE(JTRC_SMOOTH_NOTIMPL, + "Smoothing not supported with nonstandard sampling ratios") +JMESSAGE(JTRC_SOF, "Start Of Frame 0x%02x: width=%u, height=%u, components=%d") +JMESSAGE(JTRC_SOF_COMPONENT, " Component %d: %dhx%dv q=%d") +JMESSAGE(JTRC_SOI, "Start of Image") +JMESSAGE(JTRC_SOS, "Start Of Scan: %d components") +JMESSAGE(JTRC_SOS_COMPONENT, " Component %d: dc=%d ac=%d") +JMESSAGE(JTRC_SOS_PARAMS, " Ss=%d, Se=%d, Ah=%d, Al=%d") +JMESSAGE(JTRC_TFILE_CLOSE, "Closed temporary file %s") +JMESSAGE(JTRC_TFILE_OPEN, "Opened temporary file %s") +JMESSAGE(JTRC_THUMB_JPEG, + "JFIF extension marker: JPEG-compressed thumbnail image, length %u") +JMESSAGE(JTRC_THUMB_PALETTE, + "JFIF extension marker: palette thumbnail image, length %u") +JMESSAGE(JTRC_THUMB_RGB, + "JFIF extension marker: RGB thumbnail image, length %u") +JMESSAGE(JTRC_UNKNOWN_IDS, + "Unrecognized component IDs %d %d %d, assuming YCbCr") +JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u") +JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u") +JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d") +JMESSAGE(JWRN_BOGUS_PROGRESSION, + "Inconsistent progression sequence for component %d coefficient %d") +JMESSAGE(JWRN_EXTRANEOUS_DATA, + "Corrupt JPEG data: %u extraneous bytes before marker 0x%02x") +JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment") +JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code") +JMESSAGE(JWRN_JFIF_MAJOR, "Warning: unknown JFIF revision number %d.%02d") +JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file") +JMESSAGE(JWRN_MUST_RESYNC, + "Corrupt JPEG data: found marker 0x%02x instead of RST%d") +JMESSAGE(JWRN_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG") +JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines") + +#ifdef JMAKE_ENUM_LIST + + JMSG_LASTMSGCODE +} J_MESSAGE_CODE; + +#undef JMAKE_ENUM_LIST +#endif /* JMAKE_ENUM_LIST */ + +/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */ +#undef JMESSAGE + + +#ifndef JERROR_H +#define JERROR_H + +/* Macros to simplify using the error and trace message stuff */ +/* The first parameter is either type of cinfo pointer */ + +/* Fatal errors (print message and exit) */ +#define ERREXIT(cinfo,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT1(cinfo,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT2(cinfo,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT3(cinfo,code,p1,p2,p3) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT4(cinfo,code,p1,p2,p3,p4) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (cinfo)->err->msg_parm.i[3] = (p4), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXITS(cinfo,code,str) \ + ((cinfo)->err->msg_code = (code), \ + strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) + +#define MAKESTMT(stuff) do { stuff } while (0) + +/* Nonfatal errors (we can keep going, but the data is probably corrupt) */ +#define WARNMS(cinfo,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) +#define WARNMS1(cinfo,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) +#define WARNMS2(cinfo,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) + +/* Informational/debugging messages */ +#define TRACEMS(cinfo,lvl,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS1(cinfo,lvl,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS2(cinfo,lvl,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS3(cinfo,lvl,code,p1,p2,p3) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS4(cinfo,lvl,code,p1,p2,p3,p4) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS5(cinfo,lvl,code,p1,p2,p3,p4,p5) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + _mp[4] = (p5); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS8(cinfo,lvl,code,p1,p2,p3,p4,p5,p6,p7,p8) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + _mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMSS(cinfo,lvl,code,str) \ + ((cinfo)->err->msg_code = (code), \ + strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) + +#endif /* JERROR_H */ diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jfdctflt.c b/lc-continuity/mk4/modimage/jpeg-6b/jfdctflt.c new file mode 100644 index 0000000000000000000000000000000000000000..79d7a0078749c33f7f05cf11de6e55717c3a0fbf --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jfdctflt.c @@ -0,0 +1,168 @@ +/* + * jfdctflt.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a floating-point implementation of the + * forward DCT (Discrete Cosine Transform). + * + * This implementation should be more accurate than either of the integer + * DCT implementations. However, it may not give the same results on all + * machines because of differences in roundoff behavior. Speed will depend + * on the hardware's floating point capacity. + * + * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT + * on each column. Direct algorithms are also available, but they are + * much more complex and seem not to be any faster when reduced to code. + * + * This implementation is based on Arai, Agui, and Nakajima's algorithm for + * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in + * Japanese, but the algorithm is described in the Pennebaker & Mitchell + * JPEG textbook (see REFERENCES section in file README). The following code + * is based directly on figure 4-8 in P&M. + * While an 8-point DCT cannot be done in less than 11 multiplies, it is + * possible to arrange the computation so that many of the multiplies are + * simple scalings of the final outputs. These multiplies can then be + * folded into the multiplications or divisions by the JPEG quantization + * table entries. The AA&N method leaves only 5 multiplies and 29 adds + * to be done in the DCT itself. + * The primary disadvantage of this method is that with a fixed-point + * implementation, accuracy is lost due to imprecise representation of the + * scaled quantization values. However, that problem does not arise if + * we use floating point arithmetic. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdct.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_FLOAT_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* + * Perform the forward DCT on one block of samples. + */ + +GLOBAL(void) +jpeg_fdct_float (FAST_FLOAT * data) +{ + FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + FAST_FLOAT tmp10, tmp11, tmp12, tmp13; + FAST_FLOAT z1, z2, z3, z4, z5, z11, z13; + FAST_FLOAT *dataptr; + int ctr; + + /* Pass 1: process rows. */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[0] + dataptr[7]; + tmp7 = dataptr[0] - dataptr[7]; + tmp1 = dataptr[1] + dataptr[6]; + tmp6 = dataptr[1] - dataptr[6]; + tmp2 = dataptr[2] + dataptr[5]; + tmp5 = dataptr[2] - dataptr[5]; + tmp3 = dataptr[3] + dataptr[4]; + tmp4 = dataptr[3] - dataptr[4]; + + /* Even part */ + + tmp10 = tmp0 + tmp3; /* phase 2 */ + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[0] = tmp10 + tmp11; /* phase 3 */ + dataptr[4] = tmp10 - tmp11; + + z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */ + dataptr[2] = tmp13 + z1; /* phase 5 */ + dataptr[6] = tmp13 - z1; + + /* Odd part */ + + tmp10 = tmp4 + tmp5; /* phase 2 */ + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + /* The rotator is modified from fig 4-8 to avoid extra negations. */ + z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */ + z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */ + z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */ + z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */ + + z11 = tmp7 + z3; /* phase 5 */ + z13 = tmp7 - z3; + + dataptr[5] = z13 + z2; /* phase 6 */ + dataptr[3] = z13 - z2; + dataptr[1] = z11 + z4; + dataptr[7] = z11 - z4; + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; + tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; + tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; + tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; + tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; + + /* Even part */ + + tmp10 = tmp0 + tmp3; /* phase 2 */ + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */ + dataptr[DCTSIZE*4] = tmp10 - tmp11; + + z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */ + dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */ + dataptr[DCTSIZE*6] = tmp13 - z1; + + /* Odd part */ + + tmp10 = tmp4 + tmp5; /* phase 2 */ + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + /* The rotator is modified from fig 4-8 to avoid extra negations. */ + z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */ + z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */ + z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */ + z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */ + + z11 = tmp7 + z3; /* phase 5 */ + z13 = tmp7 - z3; + + dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */ + dataptr[DCTSIZE*3] = z13 - z2; + dataptr[DCTSIZE*1] = z11 + z4; + dataptr[DCTSIZE*7] = z11 - z4; + + dataptr++; /* advance pointer to next column */ + } +} + +#endif /* DCT_FLOAT_SUPPORTED */ diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jfdctfst.c b/lc-continuity/mk4/modimage/jpeg-6b/jfdctfst.c new file mode 100644 index 0000000000000000000000000000000000000000..ccb378a3b45339e05167514a038cc2db616e8fe7 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jfdctfst.c @@ -0,0 +1,224 @@ +/* + * jfdctfst.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a fast, not so accurate integer implementation of the + * forward DCT (Discrete Cosine Transform). + * + * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT + * on each column. Direct algorithms are also available, but they are + * much more complex and seem not to be any faster when reduced to code. + * + * This implementation is based on Arai, Agui, and Nakajima's algorithm for + * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in + * Japanese, but the algorithm is described in the Pennebaker & Mitchell + * JPEG textbook (see REFERENCES section in file README). The following code + * is based directly on figure 4-8 in P&M. + * While an 8-point DCT cannot be done in less than 11 multiplies, it is + * possible to arrange the computation so that many of the multiplies are + * simple scalings of the final outputs. These multiplies can then be + * folded into the multiplications or divisions by the JPEG quantization + * table entries. The AA&N method leaves only 5 multiplies and 29 adds + * to be done in the DCT itself. + * The primary disadvantage of this method is that with fixed-point math, + * accuracy is lost due to imprecise representation of the scaled + * quantization values. The smaller the quantization table entry, the less + * precise the scaled value, so this implementation does worse with high- + * quality-setting files than with low-quality ones. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdct.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_IFAST_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* Scaling decisions are generally the same as in the LL&M algorithm; + * see jfdctint.c for more details. However, we choose to descale + * (right shift) multiplication products as soon as they are formed, + * rather than carrying additional fractional bits into subsequent additions. + * This compromises accuracy slightly, but it lets us save a few shifts. + * More importantly, 16-bit arithmetic is then adequate (for 8-bit samples) + * everywhere except in the multiplications proper; this saves a good deal + * of work on 16-bit-int machines. + * + * Again to save a few shifts, the intermediate results between pass 1 and + * pass 2 are not upscaled, but are represented only to integral precision. + * + * A final compromise is to represent the multiplicative constants to only + * 8 fractional bits, rather than 13. This saves some shifting work on some + * machines, and may also reduce the cost of multiplication (since there + * are fewer one-bits in the constants). + */ + +#define CONST_BITS 8 + + +/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus + * causing a lot of useless floating-point operations at run time. + * To get around this we use the following pre-calculated constants. + * If you change CONST_BITS you may want to add appropriate values. + * (With a reasonable C compiler, you can just rely on the FIX() macro...) + */ + +#if CONST_BITS == 8 +#define FIX_0_382683433 ((INT32) 98) /* FIX(0.382683433) */ +#define FIX_0_541196100 ((INT32) 139) /* FIX(0.541196100) */ +#define FIX_0_707106781 ((INT32) 181) /* FIX(0.707106781) */ +#define FIX_1_306562965 ((INT32) 334) /* FIX(1.306562965) */ +#else +#define FIX_0_382683433 FIX(0.382683433) +#define FIX_0_541196100 FIX(0.541196100) +#define FIX_0_707106781 FIX(0.707106781) +#define FIX_1_306562965 FIX(1.306562965) +#endif + + +/* We can gain a little more speed, with a further compromise in accuracy, + * by omitting the addition in a descaling shift. This yields an incorrectly + * rounded result half the time... + */ + +#ifndef USE_ACCURATE_ROUNDING +#undef DESCALE +#define DESCALE(x,n) RIGHT_SHIFT(x, n) +#endif + + +/* Multiply a DCTELEM variable by an INT32 constant, and immediately + * descale to yield a DCTELEM result. + */ + +#define MULTIPLY(var,const) ((DCTELEM) DESCALE((var) * (const), CONST_BITS)) + + +/* + * Perform the forward DCT on one block of samples. + */ + +GLOBAL(void) +jpeg_fdct_ifast (DCTELEM * data) +{ + DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + DCTELEM tmp10, tmp11, tmp12, tmp13; + DCTELEM z1, z2, z3, z4, z5, z11, z13; + DCTELEM *dataptr; + int ctr; + SHIFT_TEMPS + + /* Pass 1: process rows. */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[0] + dataptr[7]; + tmp7 = dataptr[0] - dataptr[7]; + tmp1 = dataptr[1] + dataptr[6]; + tmp6 = dataptr[1] - dataptr[6]; + tmp2 = dataptr[2] + dataptr[5]; + tmp5 = dataptr[2] - dataptr[5]; + tmp3 = dataptr[3] + dataptr[4]; + tmp4 = dataptr[3] - dataptr[4]; + + /* Even part */ + + tmp10 = tmp0 + tmp3; /* phase 2 */ + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[0] = tmp10 + tmp11; /* phase 3 */ + dataptr[4] = tmp10 - tmp11; + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */ + dataptr[2] = tmp13 + z1; /* phase 5 */ + dataptr[6] = tmp13 - z1; + + /* Odd part */ + + tmp10 = tmp4 + tmp5; /* phase 2 */ + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + /* The rotator is modified from fig 4-8 to avoid extra negations. */ + z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */ + z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */ + z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */ + z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */ + + z11 = tmp7 + z3; /* phase 5 */ + z13 = tmp7 - z3; + + dataptr[5] = z13 + z2; /* phase 6 */ + dataptr[3] = z13 - z2; + dataptr[1] = z11 + z4; + dataptr[7] = z11 - z4; + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; + tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; + tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; + tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; + tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; + + /* Even part */ + + tmp10 = tmp0 + tmp3; /* phase 2 */ + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */ + dataptr[DCTSIZE*4] = tmp10 - tmp11; + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */ + dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */ + dataptr[DCTSIZE*6] = tmp13 - z1; + + /* Odd part */ + + tmp10 = tmp4 + tmp5; /* phase 2 */ + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + /* The rotator is modified from fig 4-8 to avoid extra negations. */ + z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */ + z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */ + z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */ + z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */ + + z11 = tmp7 + z3; /* phase 5 */ + z13 = tmp7 - z3; + + dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */ + dataptr[DCTSIZE*3] = z13 - z2; + dataptr[DCTSIZE*1] = z11 + z4; + dataptr[DCTSIZE*7] = z11 - z4; + + dataptr++; /* advance pointer to next column */ + } +} + +#endif /* DCT_IFAST_SUPPORTED */ diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jfdctint.c b/lc-continuity/mk4/modimage/jpeg-6b/jfdctint.c new file mode 100644 index 0000000000000000000000000000000000000000..0a78b64aee8ffd7fc6c3469495ec577a59d44ed1 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jfdctint.c @@ -0,0 +1,283 @@ +/* + * jfdctint.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a slow-but-accurate integer implementation of the + * forward DCT (Discrete Cosine Transform). + * + * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT + * on each column. Direct algorithms are also available, but they are + * much more complex and seem not to be any faster when reduced to code. + * + * This implementation is based on an algorithm described in + * C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT + * Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics, + * Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991. + * The primary algorithm described there uses 11 multiplies and 29 adds. + * We use their alternate method with 12 multiplies and 32 adds. + * The advantage of this method is that no data path contains more than one + * multiplication; this allows a very simple and accurate implementation in + * scaled fixed-point arithmetic, with a minimal number of shifts. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdct.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_ISLOW_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* + * The poop on this scaling stuff is as follows: + * + * Each 1-D DCT step produces outputs which are a factor of sqrt(N) + * larger than the true DCT outputs. The final outputs are therefore + * a factor of N larger than desired; since N=8 this can be cured by + * a simple right shift at the end of the algorithm. The advantage of + * this arrangement is that we save two multiplications per 1-D DCT, + * because the y0 and y4 outputs need not be divided by sqrt(N). + * In the IJG code, this factor of 8 is removed by the quantization step + * (in jcdctmgr.c), NOT in this module. + * + * We have to do addition and subtraction of the integer inputs, which + * is no problem, and multiplication by fractional constants, which is + * a problem to do in integer arithmetic. We multiply all the constants + * by CONST_SCALE and convert them to integer constants (thus retaining + * CONST_BITS bits of precision in the constants). After doing a + * multiplication we have to divide the product by CONST_SCALE, with proper + * rounding, to produce the correct output. This division can be done + * cheaply as a right shift of CONST_BITS bits. We postpone shifting + * as long as possible so that partial sums can be added together with + * full fractional precision. + * + * The outputs of the first pass are scaled up by PASS1_BITS bits so that + * they are represented to better-than-integral precision. These outputs + * require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word + * with the recommended scaling. (For 12-bit sample data, the intermediate + * array is INT32 anyway.) + * + * To avoid overflow of the 32-bit intermediate results in pass 2, we must + * have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis + * shows that the values given below are the most effective. + */ + +#if BITS_IN_JSAMPLE == 8 +#define CONST_BITS 13 +#define PASS1_BITS 2 +#else +#define CONST_BITS 13 +#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ +#endif + +/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus + * causing a lot of useless floating-point operations at run time. + * To get around this we use the following pre-calculated constants. + * If you change CONST_BITS you may want to add appropriate values. + * (With a reasonable C compiler, you can just rely on the FIX() macro...) + */ + +#if CONST_BITS == 13 +#define FIX_0_298631336 ((INT32) 2446) /* FIX(0.298631336) */ +#define FIX_0_390180644 ((INT32) 3196) /* FIX(0.390180644) */ +#define FIX_0_541196100 ((INT32) 4433) /* FIX(0.541196100) */ +#define FIX_0_765366865 ((INT32) 6270) /* FIX(0.765366865) */ +#define FIX_0_899976223 ((INT32) 7373) /* FIX(0.899976223) */ +#define FIX_1_175875602 ((INT32) 9633) /* FIX(1.175875602) */ +#define FIX_1_501321110 ((INT32) 12299) /* FIX(1.501321110) */ +#define FIX_1_847759065 ((INT32) 15137) /* FIX(1.847759065) */ +#define FIX_1_961570560 ((INT32) 16069) /* FIX(1.961570560) */ +#define FIX_2_053119869 ((INT32) 16819) /* FIX(2.053119869) */ +#define FIX_2_562915447 ((INT32) 20995) /* FIX(2.562915447) */ +#define FIX_3_072711026 ((INT32) 25172) /* FIX(3.072711026) */ +#else +#define FIX_0_298631336 FIX(0.298631336) +#define FIX_0_390180644 FIX(0.390180644) +#define FIX_0_541196100 FIX(0.541196100) +#define FIX_0_765366865 FIX(0.765366865) +#define FIX_0_899976223 FIX(0.899976223) +#define FIX_1_175875602 FIX(1.175875602) +#define FIX_1_501321110 FIX(1.501321110) +#define FIX_1_847759065 FIX(1.847759065) +#define FIX_1_961570560 FIX(1.961570560) +#define FIX_2_053119869 FIX(2.053119869) +#define FIX_2_562915447 FIX(2.562915447) +#define FIX_3_072711026 FIX(3.072711026) +#endif + + +/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. + * For 8-bit samples with the recommended scaling, all the variable + * and constant values involved are no more than 16 bits wide, so a + * 16x16->32 bit multiply can be used instead of a full 32x32 multiply. + * For 12-bit samples, a full 32-bit multiplication will be needed. + */ + +#if BITS_IN_JSAMPLE == 8 +#define MULTIPLY(var,const) MULTIPLY16C16(var,const) +#else +#define MULTIPLY(var,const) ((var) * (const)) +#endif + + +/* + * Perform the forward DCT on one block of samples. + */ + +GLOBAL(void) +jpeg_fdct_islow (DCTELEM * data) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + INT32 tmp10, tmp11, tmp12, tmp13; + INT32 z1, z2, z3, z4, z5; + DCTELEM *dataptr; + int ctr; + SHIFT_TEMPS + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[0] + dataptr[7]; + tmp7 = dataptr[0] - dataptr[7]; + tmp1 = dataptr[1] + dataptr[6]; + tmp6 = dataptr[1] - dataptr[6]; + tmp2 = dataptr[2] + dataptr[5]; + tmp5 = dataptr[2] - dataptr[5]; + tmp3 = dataptr[3] + dataptr[4]; + tmp4 = dataptr[3] - dataptr[4]; + + /* Even part per LL&M figure 1 --- note that published figure is faulty; + * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". + */ + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[0] = (DCTELEM) ((tmp10 + tmp11) << PASS1_BITS); + dataptr[4] = (DCTELEM) ((tmp10 - tmp11) << PASS1_BITS); + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); + dataptr[2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865), + CONST_BITS-PASS1_BITS); + dataptr[6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065), + CONST_BITS-PASS1_BITS); + + /* Odd part per figure 8 --- note paper omits factor of sqrt(2). + * cK represents cos(K*pi/16). + * i0..i3 in the paper are tmp4..tmp7 here. + */ + + z1 = tmp4 + tmp7; + z2 = tmp5 + tmp6; + z3 = tmp4 + tmp6; + z4 = tmp5 + tmp7; + z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ + + tmp4 = MULTIPLY(tmp4, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ + tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ + tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ + z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ + z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ + z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + + z3 += z5; + z4 += z5; + + dataptr[7] = (DCTELEM) DESCALE(tmp4 + z1 + z3, CONST_BITS-PASS1_BITS); + dataptr[5] = (DCTELEM) DESCALE(tmp5 + z2 + z4, CONST_BITS-PASS1_BITS); + dataptr[3] = (DCTELEM) DESCALE(tmp6 + z2 + z3, CONST_BITS-PASS1_BITS); + dataptr[1] = (DCTELEM) DESCALE(tmp7 + z1 + z4, CONST_BITS-PASS1_BITS); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; + tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; + tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; + tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; + tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; + + /* Even part per LL&M figure 1 --- note that published figure is faulty; + * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". + */ + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(tmp10 + tmp11, PASS1_BITS); + dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp10 - tmp11, PASS1_BITS); + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); + dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865), + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065), + CONST_BITS+PASS1_BITS); + + /* Odd part per figure 8 --- note paper omits factor of sqrt(2). + * cK represents cos(K*pi/16). + * i0..i3 in the paper are tmp4..tmp7 here. + */ + + z1 = tmp4 + tmp7; + z2 = tmp5 + tmp6; + z3 = tmp4 + tmp6; + z4 = tmp5 + tmp7; + z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ + + tmp4 = MULTIPLY(tmp4, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ + tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ + tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ + z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ + z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ + z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + + z3 += z5; + z4 += z5; + + dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp4 + z1 + z3, + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp5 + z2 + z4, + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp6 + z2 + z3, + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp7 + z1 + z4, + CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + } +} + +#endif /* DCT_ISLOW_SUPPORTED */ diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jidctflt.c b/lc-continuity/mk4/modimage/jpeg-6b/jidctflt.c new file mode 100644 index 0000000000000000000000000000000000000000..0188ce3dfcd2ce2ebaa57c17da22101de01b6f2a --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jidctflt.c @@ -0,0 +1,242 @@ +/* + * jidctflt.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a floating-point implementation of the + * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine + * must also perform dequantization of the input coefficients. + * + * This implementation should be more accurate than either of the integer + * IDCT implementations. However, it may not give the same results on all + * machines because of differences in roundoff behavior. Speed will depend + * on the hardware's floating point capacity. + * + * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT + * on each row (or vice versa, but it's more convenient to emit a row at + * a time). Direct algorithms are also available, but they are much more + * complex and seem not to be any faster when reduced to code. + * + * This implementation is based on Arai, Agui, and Nakajima's algorithm for + * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in + * Japanese, but the algorithm is described in the Pennebaker & Mitchell + * JPEG textbook (see REFERENCES section in file README). The following code + * is based directly on figure 4-8 in P&M. + * While an 8-point DCT cannot be done in less than 11 multiplies, it is + * possible to arrange the computation so that many of the multiplies are + * simple scalings of the final outputs. These multiplies can then be + * folded into the multiplications or divisions by the JPEG quantization + * table entries. The AA&N method leaves only 5 multiplies and 29 adds + * to be done in the DCT itself. + * The primary disadvantage of this method is that with a fixed-point + * implementation, accuracy is lost due to imprecise representation of the + * scaled quantization values. However, that problem does not arise if + * we use floating point arithmetic. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdct.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_FLOAT_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* Dequantize a coefficient by multiplying it by the multiplier-table + * entry; produce a float result. + */ + +#define DEQUANTIZE(coef,quantval) (((FAST_FLOAT) (coef)) * (quantval)) + + +/* + * Perform dequantization and inverse DCT on one block of coefficients. + */ + +GLOBAL(void) +jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + FAST_FLOAT tmp10, tmp11, tmp12, tmp13; + FAST_FLOAT z5, z10, z11, z12, z13; + JCOEFPTR inptr; + FLOAT_MULT_TYPE * quantptr; + FAST_FLOAT * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + FAST_FLOAT workspace[DCTSIZE2]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (FLOAT_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = DCTSIZE; ctr > 0; ctr--) { + /* Due to quantization, we will usually find that many of the input + * coefficients are zero, especially the AC terms. We can exploit this + * by short-circuiting the IDCT calculation for any column in which all + * the AC terms are zero. In that case each output is equal to the + * DC coefficient (with scale factor as needed). + * With typical images and quantization tables, half or more of the + * column DCT calculations can be simplified this way. + */ + + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && + inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && + inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && + inptr[DCTSIZE*7] == 0) { + /* AC terms all zero */ + FAST_FLOAT dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; + wsptr[DCTSIZE*2] = dcval; + wsptr[DCTSIZE*3] = dcval; + wsptr[DCTSIZE*4] = dcval; + wsptr[DCTSIZE*5] = dcval; + wsptr[DCTSIZE*6] = dcval; + wsptr[DCTSIZE*7] = dcval; + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + continue; + } + + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + tmp10 = tmp0 + tmp2; /* phase 3 */ + tmp11 = tmp0 - tmp2; + + tmp13 = tmp1 + tmp3; /* phases 5-3 */ + tmp12 = (tmp1 - tmp3) * ((FAST_FLOAT) 1.414213562) - tmp13; /* 2*c4 */ + + tmp0 = tmp10 + tmp13; /* phase 2 */ + tmp3 = tmp10 - tmp13; + tmp1 = tmp11 + tmp12; + tmp2 = tmp11 - tmp12; + + /* Odd part */ + + tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + z13 = tmp6 + tmp5; /* phase 6 */ + z10 = tmp6 - tmp5; + z11 = tmp4 + tmp7; + z12 = tmp4 - tmp7; + + tmp7 = z11 + z13; /* phase 5 */ + tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); /* 2*c4 */ + + z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */ + tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */ + tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */ + + tmp6 = tmp12 - tmp7; /* phase 2 */ + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 + tmp5; + + wsptr[DCTSIZE*0] = tmp0 + tmp7; + wsptr[DCTSIZE*7] = tmp0 - tmp7; + wsptr[DCTSIZE*1] = tmp1 + tmp6; + wsptr[DCTSIZE*6] = tmp1 - tmp6; + wsptr[DCTSIZE*2] = tmp2 + tmp5; + wsptr[DCTSIZE*5] = tmp2 - tmp5; + wsptr[DCTSIZE*4] = tmp3 + tmp4; + wsptr[DCTSIZE*3] = tmp3 - tmp4; + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + } + + /* Pass 2: process rows from work array, store into output array. */ + /* Note that we must descale the results by a factor of 8 == 2**3. */ + + wsptr = workspace; + for (ctr = 0; ctr < DCTSIZE; ctr++) { + outptr = output_buf[ctr] + output_col; + /* Rows of zeroes can be exploited in the same way as we did with columns. + * However, the column calculation has created many nonzero AC terms, so + * the simplification applies less often (typically 5% to 10% of the time). + * And testing floats for zero is relatively expensive, so we don't bother. + */ + + /* Even part */ + + tmp10 = wsptr[0] + wsptr[4]; + tmp11 = wsptr[0] - wsptr[4]; + + tmp13 = wsptr[2] + wsptr[6]; + tmp12 = (wsptr[2] - wsptr[6]) * ((FAST_FLOAT) 1.414213562) - tmp13; + + tmp0 = tmp10 + tmp13; + tmp3 = tmp10 - tmp13; + tmp1 = tmp11 + tmp12; + tmp2 = tmp11 - tmp12; + + /* Odd part */ + + z13 = wsptr[5] + wsptr[3]; + z10 = wsptr[5] - wsptr[3]; + z11 = wsptr[1] + wsptr[7]; + z12 = wsptr[1] - wsptr[7]; + + tmp7 = z11 + z13; + tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); + + z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */ + tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */ + tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */ + + tmp6 = tmp12 - tmp7; + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 + tmp5; + + /* Final output stage: scale down by a factor of 8 and range-limit */ + + outptr[0] = range_limit[(int) DESCALE((INT32) (tmp0 + tmp7), 3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) DESCALE((INT32) (tmp0 - tmp7), 3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) DESCALE((INT32) (tmp1 + tmp6), 3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) DESCALE((INT32) (tmp1 - tmp6), 3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) DESCALE((INT32) (tmp2 + tmp5), 3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) DESCALE((INT32) (tmp2 - tmp5), 3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) DESCALE((INT32) (tmp3 + tmp4), 3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) DESCALE((INT32) (tmp3 - tmp4), 3) + & RANGE_MASK]; + + wsptr += DCTSIZE; /* advance pointer to next row */ + } +} + +#endif /* DCT_FLOAT_SUPPORTED */ diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jidctfst.c b/lc-continuity/mk4/modimage/jpeg-6b/jidctfst.c new file mode 100644 index 0000000000000000000000000000000000000000..dba4216fb95e7148c24f2d6f6bba8309bb9be24e --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jidctfst.c @@ -0,0 +1,368 @@ +/* + * jidctfst.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a fast, not so accurate integer implementation of the + * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine + * must also perform dequantization of the input coefficients. + * + * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT + * on each row (or vice versa, but it's more convenient to emit a row at + * a time). Direct algorithms are also available, but they are much more + * complex and seem not to be any faster when reduced to code. + * + * This implementation is based on Arai, Agui, and Nakajima's algorithm for + * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in + * Japanese, but the algorithm is described in the Pennebaker & Mitchell + * JPEG textbook (see REFERENCES section in file README). The following code + * is based directly on figure 4-8 in P&M. + * While an 8-point DCT cannot be done in less than 11 multiplies, it is + * possible to arrange the computation so that many of the multiplies are + * simple scalings of the final outputs. These multiplies can then be + * folded into the multiplications or divisions by the JPEG quantization + * table entries. The AA&N method leaves only 5 multiplies and 29 adds + * to be done in the DCT itself. + * The primary disadvantage of this method is that with fixed-point math, + * accuracy is lost due to imprecise representation of the scaled + * quantization values. The smaller the quantization table entry, the less + * precise the scaled value, so this implementation does worse with high- + * quality-setting files than with low-quality ones. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdct.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_IFAST_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* Scaling decisions are generally the same as in the LL&M algorithm; + * see jidctint.c for more details. However, we choose to descale + * (right shift) multiplication products as soon as they are formed, + * rather than carrying additional fractional bits into subsequent additions. + * This compromises accuracy slightly, but it lets us save a few shifts. + * More importantly, 16-bit arithmetic is then adequate (for 8-bit samples) + * everywhere except in the multiplications proper; this saves a good deal + * of work on 16-bit-int machines. + * + * The dequantized coefficients are not integers because the AA&N scaling + * factors have been incorporated. We represent them scaled up by PASS1_BITS, + * so that the first and second IDCT rounds have the same input scaling. + * For 8-bit JSAMPLEs, we choose IFAST_SCALE_BITS = PASS1_BITS so as to + * avoid a descaling shift; this compromises accuracy rather drastically + * for small quantization table entries, but it saves a lot of shifts. + * For 12-bit JSAMPLEs, there's no hope of using 16x16 multiplies anyway, + * so we use a much larger scaling factor to preserve accuracy. + * + * A final compromise is to represent the multiplicative constants to only + * 8 fractional bits, rather than 13. This saves some shifting work on some + * machines, and may also reduce the cost of multiplication (since there + * are fewer one-bits in the constants). + */ + +#if BITS_IN_JSAMPLE == 8 +#define CONST_BITS 8 +#define PASS1_BITS 2 +#else +#define CONST_BITS 8 +#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ +#endif + +/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus + * causing a lot of useless floating-point operations at run time. + * To get around this we use the following pre-calculated constants. + * If you change CONST_BITS you may want to add appropriate values. + * (With a reasonable C compiler, you can just rely on the FIX() macro...) + */ + +#if CONST_BITS == 8 +#define FIX_1_082392200 ((INT32) 277) /* FIX(1.082392200) */ +#define FIX_1_414213562 ((INT32) 362) /* FIX(1.414213562) */ +#define FIX_1_847759065 ((INT32) 473) /* FIX(1.847759065) */ +#define FIX_2_613125930 ((INT32) 669) /* FIX(2.613125930) */ +#else +#define FIX_1_082392200 FIX(1.082392200) +#define FIX_1_414213562 FIX(1.414213562) +#define FIX_1_847759065 FIX(1.847759065) +#define FIX_2_613125930 FIX(2.613125930) +#endif + + +/* We can gain a little more speed, with a further compromise in accuracy, + * by omitting the addition in a descaling shift. This yields an incorrectly + * rounded result half the time... + */ + +#ifndef USE_ACCURATE_ROUNDING +#undef DESCALE +#define DESCALE(x,n) RIGHT_SHIFT(x, n) +#endif + + +/* Multiply a DCTELEM variable by an INT32 constant, and immediately + * descale to yield a DCTELEM result. + */ + +#define MULTIPLY(var,const) ((DCTELEM) DESCALE((var) * (const), CONST_BITS)) + + +/* Dequantize a coefficient by multiplying it by the multiplier-table + * entry; produce a DCTELEM result. For 8-bit data a 16x16->16 + * multiplication will do. For 12-bit data, the multiplier table is + * declared INT32, so a 32-bit multiply will be used. + */ + +#if BITS_IN_JSAMPLE == 8 +#define DEQUANTIZE(coef,quantval) (((IFAST_MULT_TYPE) (coef)) * (quantval)) +#else +#define DEQUANTIZE(coef,quantval) \ + DESCALE((coef)*(quantval), IFAST_SCALE_BITS-PASS1_BITS) +#endif + + +/* Like DESCALE, but applies to a DCTELEM and produces an int. + * We assume that int right shift is unsigned if INT32 right shift is. + */ + +#ifdef RIGHT_SHIFT_IS_UNSIGNED +#define ISHIFT_TEMPS DCTELEM ishift_temp; +#if BITS_IN_JSAMPLE == 8 +#define DCTELEMBITS 16 /* DCTELEM may be 16 or 32 bits */ +#else +#define DCTELEMBITS 32 /* DCTELEM must be 32 bits */ +#endif +#define IRIGHT_SHIFT(x,shft) \ + ((ishift_temp = (x)) < 0 ? \ + (ishift_temp >> (shft)) | ((~((DCTELEM) 0)) << (DCTELEMBITS-(shft))) : \ + (ishift_temp >> (shft))) +#else +#define ISHIFT_TEMPS +#define IRIGHT_SHIFT(x,shft) ((x) >> (shft)) +#endif + +#ifdef USE_ACCURATE_ROUNDING +#define IDESCALE(x,n) ((int) IRIGHT_SHIFT((x) + (1 << ((n)-1)), n)) +#else +#define IDESCALE(x,n) ((int) IRIGHT_SHIFT(x, n)) +#endif + + +/* + * Perform dequantization and inverse DCT on one block of coefficients. + */ + +GLOBAL(void) +jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + DCTELEM tmp10, tmp11, tmp12, tmp13; + DCTELEM z5, z10, z11, z12, z13; + JCOEFPTR inptr; + IFAST_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[DCTSIZE2]; /* buffers data between passes */ + SHIFT_TEMPS /* for DESCALE */ + ISHIFT_TEMPS /* for IDESCALE */ + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (IFAST_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = DCTSIZE; ctr > 0; ctr--) { + /* Due to quantization, we will usually find that many of the input + * coefficients are zero, especially the AC terms. We can exploit this + * by short-circuiting the IDCT calculation for any column in which all + * the AC terms are zero. In that case each output is equal to the + * DC coefficient (with scale factor as needed). + * With typical images and quantization tables, half or more of the + * column DCT calculations can be simplified this way. + */ + + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && + inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && + inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && + inptr[DCTSIZE*7] == 0) { + /* AC terms all zero */ + int dcval = (int) DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; + wsptr[DCTSIZE*2] = dcval; + wsptr[DCTSIZE*3] = dcval; + wsptr[DCTSIZE*4] = dcval; + wsptr[DCTSIZE*5] = dcval; + wsptr[DCTSIZE*6] = dcval; + wsptr[DCTSIZE*7] = dcval; + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + continue; + } + + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + tmp10 = tmp0 + tmp2; /* phase 3 */ + tmp11 = tmp0 - tmp2; + + tmp13 = tmp1 + tmp3; /* phases 5-3 */ + tmp12 = MULTIPLY(tmp1 - tmp3, FIX_1_414213562) - tmp13; /* 2*c4 */ + + tmp0 = tmp10 + tmp13; /* phase 2 */ + tmp3 = tmp10 - tmp13; + tmp1 = tmp11 + tmp12; + tmp2 = tmp11 - tmp12; + + /* Odd part */ + + tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + z13 = tmp6 + tmp5; /* phase 6 */ + z10 = tmp6 - tmp5; + z11 = tmp4 + tmp7; + z12 = tmp4 - tmp7; + + tmp7 = z11 + z13; /* phase 5 */ + tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */ + + z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */ + tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */ + tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */ + + tmp6 = tmp12 - tmp7; /* phase 2 */ + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 + tmp5; + + wsptr[DCTSIZE*0] = (int) (tmp0 + tmp7); + wsptr[DCTSIZE*7] = (int) (tmp0 - tmp7); + wsptr[DCTSIZE*1] = (int) (tmp1 + tmp6); + wsptr[DCTSIZE*6] = (int) (tmp1 - tmp6); + wsptr[DCTSIZE*2] = (int) (tmp2 + tmp5); + wsptr[DCTSIZE*5] = (int) (tmp2 - tmp5); + wsptr[DCTSIZE*4] = (int) (tmp3 + tmp4); + wsptr[DCTSIZE*3] = (int) (tmp3 - tmp4); + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + } + + /* Pass 2: process rows from work array, store into output array. */ + /* Note that we must descale the results by a factor of 8 == 2**3, */ + /* and also undo the PASS1_BITS scaling. */ + + wsptr = workspace; + for (ctr = 0; ctr < DCTSIZE; ctr++) { + outptr = output_buf[ctr] + output_col; + /* Rows of zeroes can be exploited in the same way as we did with columns. + * However, the column calculation has created many nonzero AC terms, so + * the simplification applies less often (typically 5% to 10% of the time). + * On machines with very fast multiplication, it's possible that the + * test takes more time than it's worth. In that case this section + * may be commented out. + */ + +#ifndef NO_ZERO_ROW_TEST + if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 && + wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { + /* AC terms all zero */ + JSAMPLE dcval = range_limit[IDESCALE(wsptr[0], PASS1_BITS+3) + & RANGE_MASK]; + + outptr[0] = dcval; + outptr[1] = dcval; + outptr[2] = dcval; + outptr[3] = dcval; + outptr[4] = dcval; + outptr[5] = dcval; + outptr[6] = dcval; + outptr[7] = dcval; + + wsptr += DCTSIZE; /* advance pointer to next row */ + continue; + } +#endif + + /* Even part */ + + tmp10 = ((DCTELEM) wsptr[0] + (DCTELEM) wsptr[4]); + tmp11 = ((DCTELEM) wsptr[0] - (DCTELEM) wsptr[4]); + + tmp13 = ((DCTELEM) wsptr[2] + (DCTELEM) wsptr[6]); + tmp12 = MULTIPLY((DCTELEM) wsptr[2] - (DCTELEM) wsptr[6], FIX_1_414213562) + - tmp13; + + tmp0 = tmp10 + tmp13; + tmp3 = tmp10 - tmp13; + tmp1 = tmp11 + tmp12; + tmp2 = tmp11 - tmp12; + + /* Odd part */ + + z13 = (DCTELEM) wsptr[5] + (DCTELEM) wsptr[3]; + z10 = (DCTELEM) wsptr[5] - (DCTELEM) wsptr[3]; + z11 = (DCTELEM) wsptr[1] + (DCTELEM) wsptr[7]; + z12 = (DCTELEM) wsptr[1] - (DCTELEM) wsptr[7]; + + tmp7 = z11 + z13; /* phase 5 */ + tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */ + + z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */ + tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */ + tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */ + + tmp6 = tmp12 - tmp7; /* phase 2 */ + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 + tmp5; + + /* Final output stage: scale down by a factor of 8 and range-limit */ + + outptr[0] = range_limit[IDESCALE(tmp0 + tmp7, PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[IDESCALE(tmp0 - tmp7, PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[IDESCALE(tmp1 + tmp6, PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[IDESCALE(tmp1 - tmp6, PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[IDESCALE(tmp2 + tmp5, PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[IDESCALE(tmp2 - tmp5, PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[IDESCALE(tmp3 + tmp4, PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[IDESCALE(tmp3 - tmp4, PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += DCTSIZE; /* advance pointer to next row */ + } +} + +#endif /* DCT_IFAST_SUPPORTED */ diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jidctint.c b/lc-continuity/mk4/modimage/jpeg-6b/jidctint.c new file mode 100644 index 0000000000000000000000000000000000000000..a72b3207caf5556457b8ed1f60f7446fa101f8f8 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jidctint.c @@ -0,0 +1,389 @@ +/* + * jidctint.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a slow-but-accurate integer implementation of the + * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine + * must also perform dequantization of the input coefficients. + * + * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT + * on each row (or vice versa, but it's more convenient to emit a row at + * a time). Direct algorithms are also available, but they are much more + * complex and seem not to be any faster when reduced to code. + * + * This implementation is based on an algorithm described in + * C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT + * Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics, + * Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991. + * The primary algorithm described there uses 11 multiplies and 29 adds. + * We use their alternate method with 12 multiplies and 32 adds. + * The advantage of this method is that no data path contains more than one + * multiplication; this allows a very simple and accurate implementation in + * scaled fixed-point arithmetic, with a minimal number of shifts. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdct.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_ISLOW_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* + * The poop on this scaling stuff is as follows: + * + * Each 1-D IDCT step produces outputs which are a factor of sqrt(N) + * larger than the true IDCT outputs. The final outputs are therefore + * a factor of N larger than desired; since N=8 this can be cured by + * a simple right shift at the end of the algorithm. The advantage of + * this arrangement is that we save two multiplications per 1-D IDCT, + * because the y0 and y4 inputs need not be divided by sqrt(N). + * + * We have to do addition and subtraction of the integer inputs, which + * is no problem, and multiplication by fractional constants, which is + * a problem to do in integer arithmetic. We multiply all the constants + * by CONST_SCALE and convert them to integer constants (thus retaining + * CONST_BITS bits of precision in the constants). After doing a + * multiplication we have to divide the product by CONST_SCALE, with proper + * rounding, to produce the correct output. This division can be done + * cheaply as a right shift of CONST_BITS bits. We postpone shifting + * as long as possible so that partial sums can be added together with + * full fractional precision. + * + * The outputs of the first pass are scaled up by PASS1_BITS bits so that + * they are represented to better-than-integral precision. These outputs + * require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word + * with the recommended scaling. (To scale up 12-bit sample data further, an + * intermediate INT32 array would be needed.) + * + * To avoid overflow of the 32-bit intermediate results in pass 2, we must + * have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis + * shows that the values given below are the most effective. + */ + +#if BITS_IN_JSAMPLE == 8 +#define CONST_BITS 13 +#define PASS1_BITS 2 +#else +#define CONST_BITS 13 +#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ +#endif + +/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus + * causing a lot of useless floating-point operations at run time. + * To get around this we use the following pre-calculated constants. + * If you change CONST_BITS you may want to add appropriate values. + * (With a reasonable C compiler, you can just rely on the FIX() macro...) + */ + +#if CONST_BITS == 13 +#define FIX_0_298631336 ((INT32) 2446) /* FIX(0.298631336) */ +#define FIX_0_390180644 ((INT32) 3196) /* FIX(0.390180644) */ +#define FIX_0_541196100 ((INT32) 4433) /* FIX(0.541196100) */ +#define FIX_0_765366865 ((INT32) 6270) /* FIX(0.765366865) */ +#define FIX_0_899976223 ((INT32) 7373) /* FIX(0.899976223) */ +#define FIX_1_175875602 ((INT32) 9633) /* FIX(1.175875602) */ +#define FIX_1_501321110 ((INT32) 12299) /* FIX(1.501321110) */ +#define FIX_1_847759065 ((INT32) 15137) /* FIX(1.847759065) */ +#define FIX_1_961570560 ((INT32) 16069) /* FIX(1.961570560) */ +#define FIX_2_053119869 ((INT32) 16819) /* FIX(2.053119869) */ +#define FIX_2_562915447 ((INT32) 20995) /* FIX(2.562915447) */ +#define FIX_3_072711026 ((INT32) 25172) /* FIX(3.072711026) */ +#else +#define FIX_0_298631336 FIX(0.298631336) +#define FIX_0_390180644 FIX(0.390180644) +#define FIX_0_541196100 FIX(0.541196100) +#define FIX_0_765366865 FIX(0.765366865) +#define FIX_0_899976223 FIX(0.899976223) +#define FIX_1_175875602 FIX(1.175875602) +#define FIX_1_501321110 FIX(1.501321110) +#define FIX_1_847759065 FIX(1.847759065) +#define FIX_1_961570560 FIX(1.961570560) +#define FIX_2_053119869 FIX(2.053119869) +#define FIX_2_562915447 FIX(2.562915447) +#define FIX_3_072711026 FIX(3.072711026) +#endif + + +/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. + * For 8-bit samples with the recommended scaling, all the variable + * and constant values involved are no more than 16 bits wide, so a + * 16x16->32 bit multiply can be used instead of a full 32x32 multiply. + * For 12-bit samples, a full 32-bit multiplication will be needed. + */ + +#if BITS_IN_JSAMPLE == 8 +#define MULTIPLY(var,const) MULTIPLY16C16(var,const) +#else +#define MULTIPLY(var,const) ((var) * (const)) +#endif + + +/* Dequantize a coefficient by multiplying it by the multiplier-table + * entry; produce an int result. In this module, both inputs and result + * are 16 bits or less, so either int or short multiply will work. + */ + +#define DEQUANTIZE(coef,quantval) (((ISLOW_MULT_TYPE) (coef)) * (quantval)) + + +/* + * Perform dequantization and inverse DCT on one block of coefficients. + */ + +GLOBAL(void) +jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3; + INT32 tmp10, tmp11, tmp12, tmp13; + INT32 z1, z2, z3, z4, z5; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[DCTSIZE2]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + /* Note results are scaled up by sqrt(8) compared to a true IDCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = DCTSIZE; ctr > 0; ctr--) { + /* Due to quantization, we will usually find that many of the input + * coefficients are zero, especially the AC terms. We can exploit this + * by short-circuiting the IDCT calculation for any column in which all + * the AC terms are zero. In that case each output is equal to the + * DC coefficient (with scale factor as needed). + * With typical images and quantization tables, half or more of the + * column DCT calculations can be simplified this way. + */ + + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && + inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && + inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && + inptr[DCTSIZE*7] == 0) { + /* AC terms all zero */ + int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; + + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; + wsptr[DCTSIZE*2] = dcval; + wsptr[DCTSIZE*3] = dcval; + wsptr[DCTSIZE*4] = dcval; + wsptr[DCTSIZE*5] = dcval; + wsptr[DCTSIZE*6] = dcval; + wsptr[DCTSIZE*7] = dcval; + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + continue; + } + + /* Even part: reverse the even part of the forward DCT. */ + /* The rotator is sqrt(2)*c(-6). */ + + z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); + tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065); + tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865); + + z2 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + + tmp0 = (z2 + z3) << CONST_BITS; + tmp1 = (z2 - z3) << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + /* Odd part per figure 8; the matrix is unitary and hence its + * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. + */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + tmp1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + tmp3 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + + z1 = tmp0 + tmp3; + z2 = tmp1 + tmp2; + z3 = tmp0 + tmp2; + z4 = tmp1 + tmp3; + z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ + + tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ + tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ + tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ + z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ + z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ + z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + + z3 += z5; + z4 += z5; + + tmp0 += z1 + z3; + tmp1 += z2 + z4; + tmp2 += z2 + z3; + tmp3 += z1 + z4; + + /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ + + wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*7] = (int) DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*1] = (int) DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*6] = (int) DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*2] = (int) DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*5] = (int) DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*3] = (int) DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*4] = (int) DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS); + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + } + + /* Pass 2: process rows from work array, store into output array. */ + /* Note that we must descale the results by a factor of 8 == 2**3, */ + /* and also undo the PASS1_BITS scaling. */ + + wsptr = workspace; + for (ctr = 0; ctr < DCTSIZE; ctr++) { + outptr = output_buf[ctr] + output_col; + /* Rows of zeroes can be exploited in the same way as we did with columns. + * However, the column calculation has created many nonzero AC terms, so + * the simplification applies less often (typically 5% to 10% of the time). + * On machines with very fast multiplication, it's possible that the + * test takes more time than it's worth. In that case this section + * may be commented out. + */ + +#ifndef NO_ZERO_ROW_TEST + if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 && + wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { + /* AC terms all zero */ + JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3) + & RANGE_MASK]; + + outptr[0] = dcval; + outptr[1] = dcval; + outptr[2] = dcval; + outptr[3] = dcval; + outptr[4] = dcval; + outptr[5] = dcval; + outptr[6] = dcval; + outptr[7] = dcval; + + wsptr += DCTSIZE; /* advance pointer to next row */ + continue; + } +#endif + + /* Even part: reverse the even part of the forward DCT. */ + /* The rotator is sqrt(2)*c(-6). */ + + z2 = (INT32) wsptr[2]; + z3 = (INT32) wsptr[6]; + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); + tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065); + tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865); + + tmp0 = ((INT32) wsptr[0] + (INT32) wsptr[4]) << CONST_BITS; + tmp1 = ((INT32) wsptr[0] - (INT32) wsptr[4]) << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + /* Odd part per figure 8; the matrix is unitary and hence its + * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. + */ + + tmp0 = (INT32) wsptr[7]; + tmp1 = (INT32) wsptr[5]; + tmp2 = (INT32) wsptr[3]; + tmp3 = (INT32) wsptr[1]; + + z1 = tmp0 + tmp3; + z2 = tmp1 + tmp2; + z3 = tmp0 + tmp2; + z4 = tmp1 + tmp3; + z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ + + tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ + tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ + tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ + z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ + z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ + z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + + z3 += z5; + z4 += z5; + + tmp0 += z1 + z3; + tmp1 += z2 + z4; + tmp2 += z2 + z3; + tmp3 += z1 + z4; + + /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ + + outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp3, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) DESCALE(tmp10 - tmp3, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) DESCALE(tmp11 + tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) DESCALE(tmp11 - tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) DESCALE(tmp12 + tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) DESCALE(tmp12 - tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) DESCALE(tmp13 + tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) DESCALE(tmp13 - tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += DCTSIZE; /* advance pointer to next row */ + } +} + +#endif /* DCT_ISLOW_SUPPORTED */ diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jidctred.c b/lc-continuity/mk4/modimage/jpeg-6b/jidctred.c new file mode 100644 index 0000000000000000000000000000000000000000..421f3c7ca1ed2ebc9335aeb29c990a08840a5b1d --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jidctred.c @@ -0,0 +1,398 @@ +/* + * jidctred.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains inverse-DCT routines that produce reduced-size output: + * either 4x4, 2x2, or 1x1 pixels from an 8x8 DCT block. + * + * The implementation is based on the Loeffler, Ligtenberg and Moschytz (LL&M) + * algorithm used in jidctint.c. We simply replace each 8-to-8 1-D IDCT step + * with an 8-to-4 step that produces the four averages of two adjacent outputs + * (or an 8-to-2 step producing two averages of four outputs, for 2x2 output). + * These steps were derived by computing the corresponding values at the end + * of the normal LL&M code, then simplifying as much as possible. + * + * 1x1 is trivial: just take the DC coefficient divided by 8. + * + * See jidctint.c for additional comments. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdct.h" /* Private declarations for DCT subsystem */ + +#ifdef IDCT_SCALING_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* Scaling is the same as in jidctint.c. */ + +#if BITS_IN_JSAMPLE == 8 +#define CONST_BITS 13 +#define PASS1_BITS 2 +#else +#define CONST_BITS 13 +#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ +#endif + +/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus + * causing a lot of useless floating-point operations at run time. + * To get around this we use the following pre-calculated constants. + * If you change CONST_BITS you may want to add appropriate values. + * (With a reasonable C compiler, you can just rely on the FIX() macro...) + */ + +#if CONST_BITS == 13 +#define FIX_0_211164243 ((INT32) 1730) /* FIX(0.211164243) */ +#define FIX_0_509795579 ((INT32) 4176) /* FIX(0.509795579) */ +#define FIX_0_601344887 ((INT32) 4926) /* FIX(0.601344887) */ +#define FIX_0_720959822 ((INT32) 5906) /* FIX(0.720959822) */ +#define FIX_0_765366865 ((INT32) 6270) /* FIX(0.765366865) */ +#define FIX_0_850430095 ((INT32) 6967) /* FIX(0.850430095) */ +#define FIX_0_899976223 ((INT32) 7373) /* FIX(0.899976223) */ +#define FIX_1_061594337 ((INT32) 8697) /* FIX(1.061594337) */ +#define FIX_1_272758580 ((INT32) 10426) /* FIX(1.272758580) */ +#define FIX_1_451774981 ((INT32) 11893) /* FIX(1.451774981) */ +#define FIX_1_847759065 ((INT32) 15137) /* FIX(1.847759065) */ +#define FIX_2_172734803 ((INT32) 17799) /* FIX(2.172734803) */ +#define FIX_2_562915447 ((INT32) 20995) /* FIX(2.562915447) */ +#define FIX_3_624509785 ((INT32) 29692) /* FIX(3.624509785) */ +#else +#define FIX_0_211164243 FIX(0.211164243) +#define FIX_0_509795579 FIX(0.509795579) +#define FIX_0_601344887 FIX(0.601344887) +#define FIX_0_720959822 FIX(0.720959822) +#define FIX_0_765366865 FIX(0.765366865) +#define FIX_0_850430095 FIX(0.850430095) +#define FIX_0_899976223 FIX(0.899976223) +#define FIX_1_061594337 FIX(1.061594337) +#define FIX_1_272758580 FIX(1.272758580) +#define FIX_1_451774981 FIX(1.451774981) +#define FIX_1_847759065 FIX(1.847759065) +#define FIX_2_172734803 FIX(2.172734803) +#define FIX_2_562915447 FIX(2.562915447) +#define FIX_3_624509785 FIX(3.624509785) +#endif + + +/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. + * For 8-bit samples with the recommended scaling, all the variable + * and constant values involved are no more than 16 bits wide, so a + * 16x16->32 bit multiply can be used instead of a full 32x32 multiply. + * For 12-bit samples, a full 32-bit multiplication will be needed. + */ + +#if BITS_IN_JSAMPLE == 8 +#define MULTIPLY(var,const) MULTIPLY16C16(var,const) +#else +#define MULTIPLY(var,const) ((var) * (const)) +#endif + + +/* Dequantize a coefficient by multiplying it by the multiplier-table + * entry; produce an int result. In this module, both inputs and result + * are 16 bits or less, so either int or short multiply will work. + */ + +#define DEQUANTIZE(coef,quantval) (((ISLOW_MULT_TYPE) (coef)) * (quantval)) + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a reduced-size 4x4 output block. + */ + +GLOBAL(void) +jpeg_idct_4x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp2, tmp10, tmp12; + INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[DCTSIZE*4]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = DCTSIZE; ctr > 0; inptr++, quantptr++, wsptr++, ctr--) { + /* Don't bother to process column 4, because second pass won't use it */ + if (ctr == DCTSIZE-4) + continue; + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && + inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*5] == 0 && + inptr[DCTSIZE*6] == 0 && inptr[DCTSIZE*7] == 0) { + /* AC terms all zero; we need not examine term 4 for 4x4 output */ + int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; + + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; + wsptr[DCTSIZE*2] = dcval; + wsptr[DCTSIZE*3] = dcval; + + continue; + } + + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp0 <<= (CONST_BITS+1); + + z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + tmp2 = MULTIPLY(z2, FIX_1_847759065) + MULTIPLY(z3, - FIX_0_765366865); + + tmp10 = tmp0 + tmp2; + tmp12 = tmp0 - tmp2; + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + z2 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + + tmp0 = MULTIPLY(z1, - FIX_0_211164243) /* sqrt(2) * (c3-c1) */ + + MULTIPLY(z2, FIX_1_451774981) /* sqrt(2) * (c3+c7) */ + + MULTIPLY(z3, - FIX_2_172734803) /* sqrt(2) * (-c1-c5) */ + + MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * (c5+c7) */ + + tmp2 = MULTIPLY(z1, - FIX_0_509795579) /* sqrt(2) * (c7-c5) */ + + MULTIPLY(z2, - FIX_0_601344887) /* sqrt(2) * (c5-c1) */ + + MULTIPLY(z3, FIX_0_899976223) /* sqrt(2) * (c3-c7) */ + + MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */ + + /* Final output stage */ + + wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp2, CONST_BITS-PASS1_BITS+1); + wsptr[DCTSIZE*3] = (int) DESCALE(tmp10 - tmp2, CONST_BITS-PASS1_BITS+1); + wsptr[DCTSIZE*1] = (int) DESCALE(tmp12 + tmp0, CONST_BITS-PASS1_BITS+1); + wsptr[DCTSIZE*2] = (int) DESCALE(tmp12 - tmp0, CONST_BITS-PASS1_BITS+1); + } + + /* Pass 2: process 4 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 4; ctr++) { + outptr = output_buf[ctr] + output_col; + /* It's not clear whether a zero row test is worthwhile here ... */ + +#ifndef NO_ZERO_ROW_TEST + if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && + wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { + /* AC terms all zero */ + JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3) + & RANGE_MASK]; + + outptr[0] = dcval; + outptr[1] = dcval; + outptr[2] = dcval; + outptr[3] = dcval; + + wsptr += DCTSIZE; /* advance pointer to next row */ + continue; + } +#endif + + /* Even part */ + + tmp0 = ((INT32) wsptr[0]) << (CONST_BITS+1); + + tmp2 = MULTIPLY((INT32) wsptr[2], FIX_1_847759065) + + MULTIPLY((INT32) wsptr[6], - FIX_0_765366865); + + tmp10 = tmp0 + tmp2; + tmp12 = tmp0 - tmp2; + + /* Odd part */ + + z1 = (INT32) wsptr[7]; + z2 = (INT32) wsptr[5]; + z3 = (INT32) wsptr[3]; + z4 = (INT32) wsptr[1]; + + tmp0 = MULTIPLY(z1, - FIX_0_211164243) /* sqrt(2) * (c3-c1) */ + + MULTIPLY(z2, FIX_1_451774981) /* sqrt(2) * (c3+c7) */ + + MULTIPLY(z3, - FIX_2_172734803) /* sqrt(2) * (-c1-c5) */ + + MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * (c5+c7) */ + + tmp2 = MULTIPLY(z1, - FIX_0_509795579) /* sqrt(2) * (c7-c5) */ + + MULTIPLY(z2, - FIX_0_601344887) /* sqrt(2) * (c5-c1) */ + + MULTIPLY(z3, FIX_0_899976223) /* sqrt(2) * (c3-c7) */ + + MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp2, + CONST_BITS+PASS1_BITS+3+1) + & RANGE_MASK]; + outptr[3] = range_limit[(int) DESCALE(tmp10 - tmp2, + CONST_BITS+PASS1_BITS+3+1) + & RANGE_MASK]; + outptr[1] = range_limit[(int) DESCALE(tmp12 + tmp0, + CONST_BITS+PASS1_BITS+3+1) + & RANGE_MASK]; + outptr[2] = range_limit[(int) DESCALE(tmp12 - tmp0, + CONST_BITS+PASS1_BITS+3+1) + & RANGE_MASK]; + + wsptr += DCTSIZE; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a reduced-size 2x2 output block. + */ + +GLOBAL(void) +jpeg_idct_2x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp10, z1; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[DCTSIZE*2]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = DCTSIZE; ctr > 0; inptr++, quantptr++, wsptr++, ctr--) { + /* Don't bother to process columns 2,4,6 */ + if (ctr == DCTSIZE-2 || ctr == DCTSIZE-4 || ctr == DCTSIZE-6) + continue; + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*3] == 0 && + inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*7] == 0) { + /* AC terms all zero; we need not examine terms 2,4,6 for 2x2 output */ + int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; + + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; + + continue; + } + + /* Even part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp10 = z1 << (CONST_BITS+2); + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + tmp0 = MULTIPLY(z1, - FIX_0_720959822); /* sqrt(2) * (c7-c5+c3-c1) */ + z1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp0 += MULTIPLY(z1, FIX_0_850430095); /* sqrt(2) * (-c1+c3+c5+c7) */ + z1 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + tmp0 += MULTIPLY(z1, - FIX_1_272758580); /* sqrt(2) * (-c1+c3-c5-c7) */ + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + tmp0 += MULTIPLY(z1, FIX_3_624509785); /* sqrt(2) * (c1+c3+c5+c7) */ + + /* Final output stage */ + + wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp0, CONST_BITS-PASS1_BITS+2); + wsptr[DCTSIZE*1] = (int) DESCALE(tmp10 - tmp0, CONST_BITS-PASS1_BITS+2); + } + + /* Pass 2: process 2 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 2; ctr++) { + outptr = output_buf[ctr] + output_col; + /* It's not clear whether a zero row test is worthwhile here ... */ + +#ifndef NO_ZERO_ROW_TEST + if (wsptr[1] == 0 && wsptr[3] == 0 && wsptr[5] == 0 && wsptr[7] == 0) { + /* AC terms all zero */ + JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3) + & RANGE_MASK]; + + outptr[0] = dcval; + outptr[1] = dcval; + + wsptr += DCTSIZE; /* advance pointer to next row */ + continue; + } +#endif + + /* Even part */ + + tmp10 = ((INT32) wsptr[0]) << (CONST_BITS+2); + + /* Odd part */ + + tmp0 = MULTIPLY((INT32) wsptr[7], - FIX_0_720959822) /* sqrt(2) * (c7-c5+c3-c1) */ + + MULTIPLY((INT32) wsptr[5], FIX_0_850430095) /* sqrt(2) * (-c1+c3+c5+c7) */ + + MULTIPLY((INT32) wsptr[3], - FIX_1_272758580) /* sqrt(2) * (-c1+c3-c5-c7) */ + + MULTIPLY((INT32) wsptr[1], FIX_3_624509785); /* sqrt(2) * (c1+c3+c5+c7) */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp0, + CONST_BITS+PASS1_BITS+3+2) + & RANGE_MASK]; + outptr[1] = range_limit[(int) DESCALE(tmp10 - tmp0, + CONST_BITS+PASS1_BITS+3+2) + & RANGE_MASK]; + + wsptr += DCTSIZE; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a reduced-size 1x1 output block. + */ + +GLOBAL(void) +jpeg_idct_1x1 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + int dcval; + ISLOW_MULT_TYPE * quantptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + SHIFT_TEMPS + + /* We hardly need an inverse DCT routine for this: just take the + * average pixel value, which is one-eighth of the DC coefficient. + */ + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + dcval = DEQUANTIZE(coef_block[0], quantptr[0]); + dcval = (int) DESCALE((INT32) dcval, 3); + + output_buf[0][output_col] = range_limit[dcval & RANGE_MASK]; +} + +#endif /* IDCT_SCALING_SUPPORTED */ diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jinclude.h b/lc-continuity/mk4/modimage/jpeg-6b/jinclude.h new file mode 100644 index 0000000000000000000000000000000000000000..0a4f15146aeb2070601838439e169509f6fe5b7d --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jinclude.h @@ -0,0 +1,91 @@ +/* + * jinclude.h + * + * Copyright (C) 1991-1994, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file exists to provide a single place to fix any problems with + * including the wrong system include files. (Common problems are taken + * care of by the standard jconfig symbols, but on really weird systems + * you may have to edit this file.) + * + * NOTE: this file is NOT intended to be included by applications using the + * JPEG library. Most applications need only include jpeglib.h. + */ + + +/* Include auto-config file to find out which system include files we need. */ + +#include "jconfig.h" /* auto configuration options */ +#define JCONFIG_INCLUDED /* so that jpeglib.h doesn't do it again */ + +/* + * We need the NULL macro and size_t typedef. + * On an ANSI-conforming system it is sufficient to include . + * Otherwise, we get them from or ; we may have to + * pull in as well. + * Note that the core JPEG library does not require ; + * only the default error handler and data source/destination modules do. + * But we must pull it in because of the references to FILE in jpeglib.h. + * You can remove those references if you want to compile without . + */ + +#ifdef HAVE_STDDEF_H +#include +#endif + +#ifdef HAVE_STDLIB_H +#include +#endif + +#ifdef NEED_SYS_TYPES_H +#include +#endif + +#include + +/* + * We need memory copying and zeroing functions, plus strncpy(). + * ANSI and System V implementations declare these in . + * BSD doesn't have the mem() functions, but it does have bcopy()/bzero(). + * Some systems may declare memset and memcpy in . + * + * NOTE: we assume the size parameters to these functions are of type size_t. + * Change the casts in these macros if not! + */ + +#ifdef NEED_BSD_STRINGS + +#include +#define MEMZERO(target,size) bzero((void *)(target), (size_t)(size)) +#define MEMCOPY(dest,src,size) bcopy((const void *)(src), (void *)(dest), (size_t)(size)) + +#else /* not BSD, assume ANSI/SysV string lib */ + +#include +#define MEMZERO(target,size) memset((void *)(target), 0, (size_t)(size)) +#define MEMCOPY(dest,src,size) memcpy((void *)(dest), (const void *)(src), (size_t)(size)) + +#endif + +/* + * In ANSI C, and indeed any rational implementation, size_t is also the + * type returned by sizeof(). However, it seems there are some irrational + * implementations out there, in which sizeof() returns an int even though + * size_t is defined as long or unsigned long. To ensure consistent results + * we always use this SIZEOF() macro in place of using sizeof() directly. + */ + +#define SIZEOF(object) ((size_t) sizeof(object)) + +/* + * The modules that use fread() and fwrite() always invoke them through + * these macros. On some systems you may need to twiddle the argument casts. + * CAUTION: argument order is different from underlying functions! + */ + +#define JFREAD(file,buf,sizeofbuf) \ + ((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) +#define JFWRITE(file,buf,sizeofbuf) \ + ((size_t) fwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jmemansi.c b/lc-continuity/mk4/modimage/jpeg-6b/jmemansi.c new file mode 100644 index 0000000000000000000000000000000000000000..2d93e496251c6c1ab0af020833d2d171f50b4e43 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jmemansi.c @@ -0,0 +1,167 @@ +/* + * jmemansi.c + * + * Copyright (C) 1992-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file provides a simple generic implementation of the system- + * dependent portion of the JPEG memory manager. This implementation + * assumes that you have the ANSI-standard library routine tmpfile(). + * Also, the problem of determining the amount of memory available + * is shoved onto the user. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jmemsys.h" /* import the system-dependent declarations */ + +#ifndef HAVE_STDLIB_H /* should declare malloc(),free() */ +extern void * malloc JPP((size_t size)); +extern void free JPP((void *ptr)); +#endif + +#ifndef SEEK_SET /* pre-ANSI systems may not define this; */ +#define SEEK_SET 0 /* if not, assume 0 is correct */ +#endif + + +/* + * Memory allocation and freeing are controlled by the regular library + * routines malloc() and free(). + */ + +GLOBAL(void *) +jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject) +{ + return (void *) malloc(sizeofobject); +} + +GLOBAL(void) +jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject) +{ + free(object); +} + + +/* + * "Large" objects are treated the same as "small" ones. + * NB: although we include FAR keywords in the routine declarations, + * this file won't actually work in 80x86 small/medium model; at least, + * you probably won't be able to process useful-size images in only 64KB. + */ + +GLOBAL(void FAR *) +jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject) +{ + return (void FAR *) malloc(sizeofobject); +} + +GLOBAL(void) +jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject) +{ + free(object); +} + + +/* + * This routine computes the total memory space available for allocation. + * It's impossible to do this in a portable way; our current solution is + * to make the user tell us (with a default value set at compile time). + * If you can actually get the available space, it's a good idea to subtract + * a slop factor of 5% or so. + */ + +#ifndef DEFAULT_MAX_MEM /* so can override from makefile */ +#define DEFAULT_MAX_MEM 1000000L /* default: one megabyte */ +#endif + +GLOBAL(long) +jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed, + long max_bytes_needed, long already_allocated) +{ + return cinfo->mem->max_memory_to_use - already_allocated; +} + + +/* + * Backing store (temporary file) management. + * Backing store objects are only used when the value returned by + * jpeg_mem_available is less than the total space needed. You can dispense + * with these routines if you have plenty of virtual memory; see jmemnobs.c. + */ + + +METHODDEF(void) +read_backing_store (j_common_ptr cinfo, backing_store_ptr info, + void FAR * buffer_address, + long file_offset, long byte_count) +{ + if (fseek(info->temp_file, file_offset, SEEK_SET)) + ERREXIT(cinfo, JERR_TFILE_SEEK); + if (JFREAD(info->temp_file, buffer_address, byte_count) + != (size_t) byte_count) + ERREXIT(cinfo, JERR_TFILE_READ); +} + + +METHODDEF(void) +write_backing_store (j_common_ptr cinfo, backing_store_ptr info, + void FAR * buffer_address, + long file_offset, long byte_count) +{ + if (fseek(info->temp_file, file_offset, SEEK_SET)) + ERREXIT(cinfo, JERR_TFILE_SEEK); + if (JFWRITE(info->temp_file, buffer_address, byte_count) + != (size_t) byte_count) + ERREXIT(cinfo, JERR_TFILE_WRITE); +} + + +METHODDEF(void) +close_backing_store (j_common_ptr cinfo, backing_store_ptr info) +{ + fclose(info->temp_file); + /* Since this implementation uses tmpfile() to create the file, + * no explicit file deletion is needed. + */ +} + + +/* + * Initial opening of a backing-store object. + * + * This version uses tmpfile(), which constructs a suitable file name + * behind the scenes. We don't have to use info->temp_name[] at all; + * indeed, we can't even find out the actual name of the temp file. + */ + +GLOBAL(void) +jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info, + long total_bytes_needed) +{ + if ((info->temp_file = tmpfile()) == NULL) + ERREXITS(cinfo, JERR_TFILE_CREATE, ""); + info->read_backing_store = read_backing_store; + info->write_backing_store = write_backing_store; + info->close_backing_store = close_backing_store; +} + + +/* + * These routines take care of any system-dependent initialization and + * cleanup required. + */ + +GLOBAL(long) +jpeg_mem_init (j_common_ptr cinfo) +{ + return DEFAULT_MAX_MEM; /* default for max_memory_to_use */ +} + +GLOBAL(void) +jpeg_mem_term (j_common_ptr cinfo) +{ + /* no work */ +} diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jmemdos.c b/lc-continuity/mk4/modimage/jpeg-6b/jmemdos.c new file mode 100644 index 0000000000000000000000000000000000000000..60b45c6938843aa73a05de059f3823707c26b3cf --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jmemdos.c @@ -0,0 +1,638 @@ +/* + * jmemdos.c + * + * Copyright (C) 1992-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file provides an MS-DOS-compatible implementation of the system- + * dependent portion of the JPEG memory manager. Temporary data can be + * stored in extended or expanded memory as well as in regular DOS files. + * + * If you use this file, you must be sure that NEED_FAR_POINTERS is defined + * if you compile in a small-data memory model; it should NOT be defined if + * you use a large-data memory model. This file is not recommended if you + * are using a flat-memory-space 386 environment such as DJGCC or Watcom C. + * Also, this code will NOT work if struct fields are aligned on greater than + * 2-byte boundaries. + * + * Based on code contributed by Ge' Weijers. + */ + +/* + * If you have both extended and expanded memory, you may want to change the + * order in which they are tried in jopen_backing_store. On a 286 machine + * expanded memory is usually faster, since extended memory access involves + * an expensive protected-mode-and-back switch. On 386 and better, extended + * memory is usually faster. As distributed, the code tries extended memory + * first (what? not everyone has a 386? :-). + * + * You can disable use of extended/expanded memory entirely by altering these + * definitions or overriding them from the Makefile (eg, -DEMS_SUPPORTED=0). + */ + +#ifndef XMS_SUPPORTED +#define XMS_SUPPORTED 1 +#endif +#ifndef EMS_SUPPORTED +#define EMS_SUPPORTED 1 +#endif + + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jmemsys.h" /* import the system-dependent declarations */ + +#ifndef HAVE_STDLIB_H /* should declare these */ +extern void * malloc JPP((size_t size)); +extern void free JPP((void *ptr)); +extern char * getenv JPP((const char * name)); +#endif + +#ifdef NEED_FAR_POINTERS + +#ifdef __TURBOC__ +/* These definitions work for Borland C (Turbo C) */ +#include /* need farmalloc(), farfree() */ +#define far_malloc(x) farmalloc(x) +#define far_free(x) farfree(x) +#else +/* These definitions work for Microsoft C and compatible compilers */ +#include /* need _fmalloc(), _ffree() */ +#define far_malloc(x) _fmalloc(x) +#define far_free(x) _ffree(x) +#endif + +#else /* not NEED_FAR_POINTERS */ + +#define far_malloc(x) malloc(x) +#define far_free(x) free(x) + +#endif /* NEED_FAR_POINTERS */ + +#ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */ +#define READ_BINARY "r" +#else +#define READ_BINARY "rb" +#endif + +#ifndef USE_MSDOS_MEMMGR /* make sure user got configuration right */ + You forgot to define USE_MSDOS_MEMMGR in jconfig.h. /* deliberate syntax error */ +#endif + +#if MAX_ALLOC_CHUNK >= 65535L /* make sure jconfig.h got this right */ + MAX_ALLOC_CHUNK should be less than 64K. /* deliberate syntax error */ +#endif + + +/* + * Declarations for assembly-language support routines (see jmemdosa.asm). + * + * The functions are declared "far" as are all their pointer arguments; + * this ensures the assembly source code will work regardless of the + * compiler memory model. We assume "short" is 16 bits, "long" is 32. + */ + +typedef void far * XMSDRIVER; /* actually a pointer to code */ +typedef struct { /* registers for calling XMS driver */ + unsigned short ax, dx, bx; + void far * ds_si; + } XMScontext; +typedef struct { /* registers for calling EMS driver */ + unsigned short ax, dx, bx; + void far * ds_si; + } EMScontext; + +extern short far jdos_open JPP((short far * handle, char far * filename)); +extern short far jdos_close JPP((short handle)); +extern short far jdos_seek JPP((short handle, long offset)); +extern short far jdos_read JPP((short handle, void far * buffer, + unsigned short count)); +extern short far jdos_write JPP((short handle, void far * buffer, + unsigned short count)); +extern void far jxms_getdriver JPP((XMSDRIVER far *)); +extern void far jxms_calldriver JPP((XMSDRIVER, XMScontext far *)); +extern short far jems_available JPP((void)); +extern void far jems_calldriver JPP((EMScontext far *)); + + +/* + * Selection of a file name for a temporary file. + * This is highly system-dependent, and you may want to customize it. + */ + +static int next_file_num; /* to distinguish among several temp files */ + +LOCAL(void) +select_file_name (char * fname) +{ + const char * env; + char * ptr; + FILE * tfile; + + /* Keep generating file names till we find one that's not in use */ + for (;;) { + /* Get temp directory name from environment TMP or TEMP variable; + * if none, use "." + */ + if ((env = (const char *) getenv("TMP")) == NULL) + if ((env = (const char *) getenv("TEMP")) == NULL) + env = "."; + if (*env == '\0') /* null string means "." */ + env = "."; + ptr = fname; /* copy name to fname */ + while (*env != '\0') + *ptr++ = *env++; + if (ptr[-1] != '\\' && ptr[-1] != '/') + *ptr++ = '\\'; /* append backslash if not in env variable */ + /* Append a suitable file name */ + next_file_num++; /* advance counter */ + sprintf(ptr, "JPG%03d.TMP", next_file_num); + /* Probe to see if file name is already in use */ + if ((tfile = fopen(fname, READ_BINARY)) == NULL) + break; + fclose(tfile); /* oops, it's there; close tfile & try again */ + } +} + + +/* + * Near-memory allocation and freeing are controlled by the regular library + * routines malloc() and free(). + */ + +GLOBAL(void *) +jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject) +{ + return (void *) malloc(sizeofobject); +} + +GLOBAL(void) +jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject) +{ + free(object); +} + + +/* + * "Large" objects are allocated in far memory, if possible + */ + +GLOBAL(void FAR *) +jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject) +{ + return (void FAR *) far_malloc(sizeofobject); +} + +GLOBAL(void) +jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject) +{ + far_free(object); +} + + +/* + * This routine computes the total memory space available for allocation. + * It's impossible to do this in a portable way; our current solution is + * to make the user tell us (with a default value set at compile time). + * If you can actually get the available space, it's a good idea to subtract + * a slop factor of 5% or so. + */ + +#ifndef DEFAULT_MAX_MEM /* so can override from makefile */ +#define DEFAULT_MAX_MEM 300000L /* for total usage about 450K */ +#endif + +GLOBAL(long) +jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed, + long max_bytes_needed, long already_allocated) +{ + return cinfo->mem->max_memory_to_use - already_allocated; +} + + +/* + * Backing store (temporary file) management. + * Backing store objects are only used when the value returned by + * jpeg_mem_available is less than the total space needed. You can dispense + * with these routines if you have plenty of virtual memory; see jmemnobs.c. + */ + +/* + * For MS-DOS we support three types of backing storage: + * 1. Conventional DOS files. We access these by direct DOS calls rather + * than via the stdio package. This provides a bit better performance, + * but the real reason is that the buffers to be read or written are FAR. + * The stdio library for small-data memory models can't cope with that. + * 2. Extended memory, accessed per the XMS V2.0 specification. + * 3. Expanded memory, accessed per the LIM/EMS 4.0 specification. + * You'll need copies of those specs to make sense of the related code. + * The specs are available by Internet FTP from the SIMTEL archives + * (oak.oakland.edu and its various mirror sites). See files + * pub/msdos/microsoft/xms20.arc and pub/msdos/info/limems41.zip. + */ + + +/* + * Access methods for a DOS file. + */ + + +METHODDEF(void) +read_file_store (j_common_ptr cinfo, backing_store_ptr info, + void FAR * buffer_address, + long file_offset, long byte_count) +{ + if (jdos_seek(info->handle.file_handle, file_offset)) + ERREXIT(cinfo, JERR_TFILE_SEEK); + /* Since MAX_ALLOC_CHUNK is less than 64K, byte_count will be too. */ + if (byte_count > 65535L) /* safety check */ + ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK); + if (jdos_read(info->handle.file_handle, buffer_address, + (unsigned short) byte_count)) + ERREXIT(cinfo, JERR_TFILE_READ); +} + + +METHODDEF(void) +write_file_store (j_common_ptr cinfo, backing_store_ptr info, + void FAR * buffer_address, + long file_offset, long byte_count) +{ + if (jdos_seek(info->handle.file_handle, file_offset)) + ERREXIT(cinfo, JERR_TFILE_SEEK); + /* Since MAX_ALLOC_CHUNK is less than 64K, byte_count will be too. */ + if (byte_count > 65535L) /* safety check */ + ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK); + if (jdos_write(info->handle.file_handle, buffer_address, + (unsigned short) byte_count)) + ERREXIT(cinfo, JERR_TFILE_WRITE); +} + + +METHODDEF(void) +close_file_store (j_common_ptr cinfo, backing_store_ptr info) +{ + jdos_close(info->handle.file_handle); /* close the file */ + remove(info->temp_name); /* delete the file */ +/* If your system doesn't have remove(), try unlink() instead. + * remove() is the ANSI-standard name for this function, but + * unlink() was more common in pre-ANSI systems. + */ + TRACEMSS(cinfo, 1, JTRC_TFILE_CLOSE, info->temp_name); +} + + +LOCAL(boolean) +open_file_store (j_common_ptr cinfo, backing_store_ptr info, + long total_bytes_needed) +{ + short handle; + + select_file_name(info->temp_name); + if (jdos_open((short far *) & handle, (char far *) info->temp_name)) { + /* might as well exit since jpeg_open_backing_store will fail anyway */ + ERREXITS(cinfo, JERR_TFILE_CREATE, info->temp_name); + return FALSE; + } + info->handle.file_handle = handle; + info->read_backing_store = read_file_store; + info->write_backing_store = write_file_store; + info->close_backing_store = close_file_store; + TRACEMSS(cinfo, 1, JTRC_TFILE_OPEN, info->temp_name); + return TRUE; /* succeeded */ +} + + +/* + * Access methods for extended memory. + */ + +#if XMS_SUPPORTED + +static XMSDRIVER xms_driver; /* saved address of XMS driver */ + +typedef union { /* either long offset or real-mode pointer */ + long offset; + void far * ptr; + } XMSPTR; + +typedef struct { /* XMS move specification structure */ + long length; + XMSH src_handle; + XMSPTR src; + XMSH dst_handle; + XMSPTR dst; + } XMSspec; + +#define ODD(X) (((X) & 1L) != 0) + + +METHODDEF(void) +read_xms_store (j_common_ptr cinfo, backing_store_ptr info, + void FAR * buffer_address, + long file_offset, long byte_count) +{ + XMScontext ctx; + XMSspec spec; + char endbuffer[2]; + + /* The XMS driver can't cope with an odd length, so handle the last byte + * specially if byte_count is odd. We don't expect this to be common. + */ + + spec.length = byte_count & (~ 1L); + spec.src_handle = info->handle.xms_handle; + spec.src.offset = file_offset; + spec.dst_handle = 0; + spec.dst.ptr = buffer_address; + + ctx.ds_si = (void far *) & spec; + ctx.ax = 0x0b00; /* EMB move */ + jxms_calldriver(xms_driver, (XMScontext far *) & ctx); + if (ctx.ax != 1) + ERREXIT(cinfo, JERR_XMS_READ); + + if (ODD(byte_count)) { + read_xms_store(cinfo, info, (void FAR *) endbuffer, + file_offset + byte_count - 1L, 2L); + ((char FAR *) buffer_address)[byte_count - 1L] = endbuffer[0]; + } +} + + +METHODDEF(void) +write_xms_store (j_common_ptr cinfo, backing_store_ptr info, + void FAR * buffer_address, + long file_offset, long byte_count) +{ + XMScontext ctx; + XMSspec spec; + char endbuffer[2]; + + /* The XMS driver can't cope with an odd length, so handle the last byte + * specially if byte_count is odd. We don't expect this to be common. + */ + + spec.length = byte_count & (~ 1L); + spec.src_handle = 0; + spec.src.ptr = buffer_address; + spec.dst_handle = info->handle.xms_handle; + spec.dst.offset = file_offset; + + ctx.ds_si = (void far *) & spec; + ctx.ax = 0x0b00; /* EMB move */ + jxms_calldriver(xms_driver, (XMScontext far *) & ctx); + if (ctx.ax != 1) + ERREXIT(cinfo, JERR_XMS_WRITE); + + if (ODD(byte_count)) { + read_xms_store(cinfo, info, (void FAR *) endbuffer, + file_offset + byte_count - 1L, 2L); + endbuffer[0] = ((char FAR *) buffer_address)[byte_count - 1L]; + write_xms_store(cinfo, info, (void FAR *) endbuffer, + file_offset + byte_count - 1L, 2L); + } +} + + +METHODDEF(void) +close_xms_store (j_common_ptr cinfo, backing_store_ptr info) +{ + XMScontext ctx; + + ctx.dx = info->handle.xms_handle; + ctx.ax = 0x0a00; + jxms_calldriver(xms_driver, (XMScontext far *) & ctx); + TRACEMS1(cinfo, 1, JTRC_XMS_CLOSE, info->handle.xms_handle); + /* we ignore any error return from the driver */ +} + + +LOCAL(boolean) +open_xms_store (j_common_ptr cinfo, backing_store_ptr info, + long total_bytes_needed) +{ + XMScontext ctx; + + /* Get address of XMS driver */ + jxms_getdriver((XMSDRIVER far *) & xms_driver); + if (xms_driver == NULL) + return FALSE; /* no driver to be had */ + + /* Get version number, must be >= 2.00 */ + ctx.ax = 0x0000; + jxms_calldriver(xms_driver, (XMScontext far *) & ctx); + if (ctx.ax < (unsigned short) 0x0200) + return FALSE; + + /* Try to get space (expressed in kilobytes) */ + ctx.dx = (unsigned short) ((total_bytes_needed + 1023L) >> 10); + ctx.ax = 0x0900; + jxms_calldriver(xms_driver, (XMScontext far *) & ctx); + if (ctx.ax != 1) + return FALSE; + + /* Succeeded, save the handle and away we go */ + info->handle.xms_handle = ctx.dx; + info->read_backing_store = read_xms_store; + info->write_backing_store = write_xms_store; + info->close_backing_store = close_xms_store; + TRACEMS1(cinfo, 1, JTRC_XMS_OPEN, ctx.dx); + return TRUE; /* succeeded */ +} + +#endif /* XMS_SUPPORTED */ + + +/* + * Access methods for expanded memory. + */ + +#if EMS_SUPPORTED + +/* The EMS move specification structure requires word and long fields aligned + * at odd byte boundaries. Some compilers will align struct fields at even + * byte boundaries. While it's usually possible to force byte alignment, + * that causes an overall performance penalty and may pose problems in merging + * JPEG into a larger application. Instead we accept some rather dirty code + * here. Note this code would fail if the hardware did not allow odd-byte + * word & long accesses, but all 80x86 CPUs do. + */ + +typedef void far * EMSPTR; + +typedef union { /* EMS move specification structure */ + long length; /* It's easy to access first 4 bytes */ + char bytes[18]; /* Misaligned fields in here! */ + } EMSspec; + +/* Macros for accessing misaligned fields */ +#define FIELD_AT(spec,offset,type) (*((type *) &(spec.bytes[offset]))) +#define SRC_TYPE(spec) FIELD_AT(spec,4,char) +#define SRC_HANDLE(spec) FIELD_AT(spec,5,EMSH) +#define SRC_OFFSET(spec) FIELD_AT(spec,7,unsigned short) +#define SRC_PAGE(spec) FIELD_AT(spec,9,unsigned short) +#define SRC_PTR(spec) FIELD_AT(spec,7,EMSPTR) +#define DST_TYPE(spec) FIELD_AT(spec,11,char) +#define DST_HANDLE(spec) FIELD_AT(spec,12,EMSH) +#define DST_OFFSET(spec) FIELD_AT(spec,14,unsigned short) +#define DST_PAGE(spec) FIELD_AT(spec,16,unsigned short) +#define DST_PTR(spec) FIELD_AT(spec,14,EMSPTR) + +#define EMSPAGESIZE 16384L /* gospel, see the EMS specs */ + +#define HIBYTE(W) (((W) >> 8) & 0xFF) +#define LOBYTE(W) ((W) & 0xFF) + + +METHODDEF(void) +read_ems_store (j_common_ptr cinfo, backing_store_ptr info, + void FAR * buffer_address, + long file_offset, long byte_count) +{ + EMScontext ctx; + EMSspec spec; + + spec.length = byte_count; + SRC_TYPE(spec) = 1; + SRC_HANDLE(spec) = info->handle.ems_handle; + SRC_PAGE(spec) = (unsigned short) (file_offset / EMSPAGESIZE); + SRC_OFFSET(spec) = (unsigned short) (file_offset % EMSPAGESIZE); + DST_TYPE(spec) = 0; + DST_HANDLE(spec) = 0; + DST_PTR(spec) = buffer_address; + + ctx.ds_si = (void far *) & spec; + ctx.ax = 0x5700; /* move memory region */ + jems_calldriver((EMScontext far *) & ctx); + if (HIBYTE(ctx.ax) != 0) + ERREXIT(cinfo, JERR_EMS_READ); +} + + +METHODDEF(void) +write_ems_store (j_common_ptr cinfo, backing_store_ptr info, + void FAR * buffer_address, + long file_offset, long byte_count) +{ + EMScontext ctx; + EMSspec spec; + + spec.length = byte_count; + SRC_TYPE(spec) = 0; + SRC_HANDLE(spec) = 0; + SRC_PTR(spec) = buffer_address; + DST_TYPE(spec) = 1; + DST_HANDLE(spec) = info->handle.ems_handle; + DST_PAGE(spec) = (unsigned short) (file_offset / EMSPAGESIZE); + DST_OFFSET(spec) = (unsigned short) (file_offset % EMSPAGESIZE); + + ctx.ds_si = (void far *) & spec; + ctx.ax = 0x5700; /* move memory region */ + jems_calldriver((EMScontext far *) & ctx); + if (HIBYTE(ctx.ax) != 0) + ERREXIT(cinfo, JERR_EMS_WRITE); +} + + +METHODDEF(void) +close_ems_store (j_common_ptr cinfo, backing_store_ptr info) +{ + EMScontext ctx; + + ctx.ax = 0x4500; + ctx.dx = info->handle.ems_handle; + jems_calldriver((EMScontext far *) & ctx); + TRACEMS1(cinfo, 1, JTRC_EMS_CLOSE, info->handle.ems_handle); + /* we ignore any error return from the driver */ +} + + +LOCAL(boolean) +open_ems_store (j_common_ptr cinfo, backing_store_ptr info, + long total_bytes_needed) +{ + EMScontext ctx; + + /* Is EMS driver there? */ + if (! jems_available()) + return FALSE; + + /* Get status, make sure EMS is OK */ + ctx.ax = 0x4000; + jems_calldriver((EMScontext far *) & ctx); + if (HIBYTE(ctx.ax) != 0) + return FALSE; + + /* Get version, must be >= 4.0 */ + ctx.ax = 0x4600; + jems_calldriver((EMScontext far *) & ctx); + if (HIBYTE(ctx.ax) != 0 || LOBYTE(ctx.ax) < 0x40) + return FALSE; + + /* Try to allocate requested space */ + ctx.ax = 0x4300; + ctx.bx = (unsigned short) ((total_bytes_needed + EMSPAGESIZE-1L) / EMSPAGESIZE); + jems_calldriver((EMScontext far *) & ctx); + if (HIBYTE(ctx.ax) != 0) + return FALSE; + + /* Succeeded, save the handle and away we go */ + info->handle.ems_handle = ctx.dx; + info->read_backing_store = read_ems_store; + info->write_backing_store = write_ems_store; + info->close_backing_store = close_ems_store; + TRACEMS1(cinfo, 1, JTRC_EMS_OPEN, ctx.dx); + return TRUE; /* succeeded */ +} + +#endif /* EMS_SUPPORTED */ + + +/* + * Initial opening of a backing-store object. + */ + +GLOBAL(void) +jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info, + long total_bytes_needed) +{ + /* Try extended memory, then expanded memory, then regular file. */ +#if XMS_SUPPORTED + if (open_xms_store(cinfo, info, total_bytes_needed)) + return; +#endif +#if EMS_SUPPORTED + if (open_ems_store(cinfo, info, total_bytes_needed)) + return; +#endif + if (open_file_store(cinfo, info, total_bytes_needed)) + return; + ERREXITS(cinfo, JERR_TFILE_CREATE, ""); +} + + +/* + * These routines take care of any system-dependent initialization and + * cleanup required. + */ + +GLOBAL(long) +jpeg_mem_init (j_common_ptr cinfo) +{ + next_file_num = 0; /* initialize temp file name generator */ + return DEFAULT_MAX_MEM; /* default for max_memory_to_use */ +} + +GLOBAL(void) +jpeg_mem_term (j_common_ptr cinfo) +{ + /* Microsoft C, at least in v6.00A, will not successfully reclaim freed + * blocks of size > 32Kbytes unless we give it a kick in the rear, like so: + */ +#ifdef NEED_FHEAPMIN + _fheapmin(); +#endif +} diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jmemdosa.asm b/lc-continuity/mk4/modimage/jpeg-6b/jmemdosa.asm new file mode 100644 index 0000000000000000000000000000000000000000..ecd43729fe5e286396b3d1cc4be28d27cca48867 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jmemdosa.asm @@ -0,0 +1,379 @@ +; +; jmemdosa.asm +; +; Copyright (C) 1992, Thomas G. Lane. +; This file is part of the Independent JPEG Group's software. +; For conditions of distribution and use, see the accompanying README file. +; +; This file contains low-level interface routines to support the MS-DOS +; backing store manager (jmemdos.c). Routines are provided to access disk +; files through direct DOS calls, and to access XMS and EMS drivers. +; +; This file should assemble with Microsoft's MASM or any compatible +; assembler (including Borland's Turbo Assembler). If you haven't got +; a compatible assembler, better fall back to jmemansi.c or jmemname.c. +; +; To minimize dependence on the C compiler's register usage conventions, +; we save and restore all 8086 registers, even though most compilers only +; require SI,DI,DS to be preserved. Also, we use only 16-bit-wide return +; values, which everybody returns in AX. +; +; Based on code contributed by Ge' Weijers. +; + +JMEMDOSA_TXT segment byte public 'CODE' + + assume cs:JMEMDOSA_TXT + + public _jdos_open + public _jdos_close + public _jdos_seek + public _jdos_read + public _jdos_write + public _jxms_getdriver + public _jxms_calldriver + public _jems_available + public _jems_calldriver + +; +; short far jdos_open (short far * handle, char far * filename) +; +; Create and open a temporary file +; +_jdos_open proc far + push bp ; linkage + mov bp,sp + push si ; save all registers for safety + push di + push bx + push cx + push dx + push es + push ds + mov cx,0 ; normal file attributes + lds dx,dword ptr [bp+10] ; get filename pointer + mov ah,3ch ; create file + int 21h + jc open_err ; if failed, return error code + lds bx,dword ptr [bp+6] ; get handle pointer + mov word ptr [bx],ax ; save the handle + xor ax,ax ; return zero for OK +open_err: pop ds ; restore registers and exit + pop es + pop dx + pop cx + pop bx + pop di + pop si + pop bp + ret +_jdos_open endp + + +; +; short far jdos_close (short handle) +; +; Close the file handle +; +_jdos_close proc far + push bp ; linkage + mov bp,sp + push si ; save all registers for safety + push di + push bx + push cx + push dx + push es + push ds + mov bx,word ptr [bp+6] ; file handle + mov ah,3eh ; close file + int 21h + jc close_err ; if failed, return error code + xor ax,ax ; return zero for OK +close_err: pop ds ; restore registers and exit + pop es + pop dx + pop cx + pop bx + pop di + pop si + pop bp + ret +_jdos_close endp + + +; +; short far jdos_seek (short handle, long offset) +; +; Set file position +; +_jdos_seek proc far + push bp ; linkage + mov bp,sp + push si ; save all registers for safety + push di + push bx + push cx + push dx + push es + push ds + mov bx,word ptr [bp+6] ; file handle + mov dx,word ptr [bp+8] ; LS offset + mov cx,word ptr [bp+10] ; MS offset + mov ax,4200h ; absolute seek + int 21h + jc seek_err ; if failed, return error code + xor ax,ax ; return zero for OK +seek_err: pop ds ; restore registers and exit + pop es + pop dx + pop cx + pop bx + pop di + pop si + pop bp + ret +_jdos_seek endp + + +; +; short far jdos_read (short handle, void far * buffer, unsigned short count) +; +; Read from file +; +_jdos_read proc far + push bp ; linkage + mov bp,sp + push si ; save all registers for safety + push di + push bx + push cx + push dx + push es + push ds + mov bx,word ptr [bp+6] ; file handle + lds dx,dword ptr [bp+8] ; buffer address + mov cx,word ptr [bp+12] ; number of bytes + mov ah,3fh ; read file + int 21h + jc read_err ; if failed, return error code + cmp ax,word ptr [bp+12] ; make sure all bytes were read + je read_ok + mov ax,1 ; else return 1 for not OK + jmp short read_err +read_ok: xor ax,ax ; return zero for OK +read_err: pop ds ; restore registers and exit + pop es + pop dx + pop cx + pop bx + pop di + pop si + pop bp + ret +_jdos_read endp + + +; +; short far jdos_write (short handle, void far * buffer, unsigned short count) +; +; Write to file +; +_jdos_write proc far + push bp ; linkage + mov bp,sp + push si ; save all registers for safety + push di + push bx + push cx + push dx + push es + push ds + mov bx,word ptr [bp+6] ; file handle + lds dx,dword ptr [bp+8] ; buffer address + mov cx,word ptr [bp+12] ; number of bytes + mov ah,40h ; write file + int 21h + jc write_err ; if failed, return error code + cmp ax,word ptr [bp+12] ; make sure all bytes written + je write_ok + mov ax,1 ; else return 1 for not OK + jmp short write_err +write_ok: xor ax,ax ; return zero for OK +write_err: pop ds ; restore registers and exit + pop es + pop dx + pop cx + pop bx + pop di + pop si + pop bp + ret +_jdos_write endp + + +; +; void far jxms_getdriver (XMSDRIVER far *) +; +; Get the address of the XMS driver, or NULL if not available +; +_jxms_getdriver proc far + push bp ; linkage + mov bp,sp + push si ; save all registers for safety + push di + push bx + push cx + push dx + push es + push ds + mov ax,4300h ; call multiplex interrupt with + int 2fh ; a magic cookie, hex 4300 + cmp al,80h ; AL should contain hex 80 + je xmsavail + xor dx,dx ; no XMS driver available + xor ax,ax ; return a nil pointer + jmp short xmsavail_done +xmsavail: mov ax,4310h ; fetch driver address with + int 2fh ; another magic cookie + mov dx,es ; copy address to dx:ax + mov ax,bx +xmsavail_done: les bx,dword ptr [bp+6] ; get pointer to return value + mov word ptr es:[bx],ax + mov word ptr es:[bx+2],dx + pop ds ; restore registers and exit + pop es + pop dx + pop cx + pop bx + pop di + pop si + pop bp + ret +_jxms_getdriver endp + + +; +; void far jxms_calldriver (XMSDRIVER, XMScontext far *) +; +; The XMScontext structure contains values for the AX,DX,BX,SI,DS registers. +; These are loaded, the XMS call is performed, and the new values of the +; AX,DX,BX registers are written back to the context structure. +; +_jxms_calldriver proc far + push bp ; linkage + mov bp,sp + push si ; save all registers for safety + push di + push bx + push cx + push dx + push es + push ds + les bx,dword ptr [bp+10] ; get XMScontext pointer + mov ax,word ptr es:[bx] ; load registers + mov dx,word ptr es:[bx+2] + mov si,word ptr es:[bx+6] + mov ds,word ptr es:[bx+8] + mov bx,word ptr es:[bx+4] + call dword ptr [bp+6] ; call the driver + mov cx,bx ; save returned BX for a sec + les bx,dword ptr [bp+10] ; get XMScontext pointer + mov word ptr es:[bx],ax ; put back ax,dx,bx + mov word ptr es:[bx+2],dx + mov word ptr es:[bx+4],cx + pop ds ; restore registers and exit + pop es + pop dx + pop cx + pop bx + pop di + pop si + pop bp + ret +_jxms_calldriver endp + + +; +; short far jems_available (void) +; +; Have we got an EMS driver? (this comes straight from the EMS 4.0 specs) +; +_jems_available proc far + push si ; save all registers for safety + push di + push bx + push cx + push dx + push es + push ds + mov ax,3567h ; get interrupt vector 67h + int 21h + push cs + pop ds + mov di,000ah ; check offs 10 in returned seg + lea si,ASCII_device_name ; against literal string + mov cx,8 + cld + repe cmpsb + jne no_ems + mov ax,1 ; match, it's there + jmp short avail_done +no_ems: xor ax,ax ; it's not there +avail_done: pop ds ; restore registers and exit + pop es + pop dx + pop cx + pop bx + pop di + pop si + ret + +ASCII_device_name db "EMMXXXX0" + +_jems_available endp + + +; +; void far jems_calldriver (EMScontext far *) +; +; The EMScontext structure contains values for the AX,DX,BX,SI,DS registers. +; These are loaded, the EMS trap is performed, and the new values of the +; AX,DX,BX registers are written back to the context structure. +; +_jems_calldriver proc far + push bp ; linkage + mov bp,sp + push si ; save all registers for safety + push di + push bx + push cx + push dx + push es + push ds + les bx,dword ptr [bp+6] ; get EMScontext pointer + mov ax,word ptr es:[bx] ; load registers + mov dx,word ptr es:[bx+2] + mov si,word ptr es:[bx+6] + mov ds,word ptr es:[bx+8] + mov bx,word ptr es:[bx+4] + int 67h ; call the EMS driver + mov cx,bx ; save returned BX for a sec + les bx,dword ptr [bp+6] ; get EMScontext pointer + mov word ptr es:[bx],ax ; put back ax,dx,bx + mov word ptr es:[bx+2],dx + mov word ptr es:[bx+4],cx + pop ds ; restore registers and exit + pop es + pop dx + pop cx + pop bx + pop di + pop si + pop bp + ret +_jems_calldriver endp + +JMEMDOSA_TXT ends + + end diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jmemmac.c b/lc-continuity/mk4/modimage/jpeg-6b/jmemmac.c new file mode 100644 index 0000000000000000000000000000000000000000..106f9bea05d00219cff829ecf916d1005d546769 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jmemmac.c @@ -0,0 +1,289 @@ +/* + * jmemmac.c + * + * Copyright (C) 1992-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * jmemmac.c provides an Apple Macintosh implementation of the system- + * dependent portion of the JPEG memory manager. + * + * If you use jmemmac.c, then you must define USE_MAC_MEMMGR in the + * JPEG_INTERNALS part of jconfig.h. + * + * jmemmac.c uses the Macintosh toolbox routines NewPtr and DisposePtr + * instead of malloc and free. It accurately determines the amount of + * memory available by using CompactMem. Notice that if left to its + * own devices, this code can chew up all available space in the + * application's zone, with the exception of the rather small "slop" + * factor computed in jpeg_mem_available(). The application can ensure + * that more space is left over by reducing max_memory_to_use. + * + * Large images are swapped to disk using temporary files and System 7.0+'s + * temporary folder functionality. + * + * Note that jmemmac.c depends on two features of MacOS that were first + * introduced in System 7: FindFolder and the FSSpec-based calls. + * If your application uses jmemmac.c and is run under System 6 or earlier, + * and the jpeg library decides it needs a temporary file, it will abort, + * printing error messages about requiring System 7. (If no temporary files + * are created, it will run fine.) + * + * If you want to use jmemmac.c in an application that might be used with + * System 6 or earlier, then you should remove dependencies on FindFolder + * and the FSSpec calls. You will need to replace FindFolder with some + * other mechanism for finding a place to put temporary files, and you + * should replace the FSSpec calls with their HFS equivalents: + * + * FSpDelete -> HDelete + * FSpGetFInfo -> HGetFInfo + * FSpCreate -> HCreate + * FSpOpenDF -> HOpen *** Note: not HOpenDF *** + * FSMakeFSSpec -> (fill in spec by hand.) + * + * (Use HOpen instead of HOpenDF. HOpen is just a glue-interface to PBHOpen, + * which is on all HFS macs. HOpenDF is a System 7 addition which avoids the + * ages-old problem of names starting with a period.) + * + * Contributed by Sam Bushell (jsam@iagu.on.net) and + * Dan Gildor (gyld@in-touch.com). + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jmemsys.h" /* import the system-dependent declarations */ + +#ifndef USE_MAC_MEMMGR /* make sure user got configuration right */ + You forgot to define USE_MAC_MEMMGR in jconfig.h. /* deliberate syntax error */ +#endif + +#include /* we use the MacOS memory manager */ +#include /* we use the MacOS File stuff */ +#include /* we use the MacOS HFS stuff */ +#include /* for smSystemScript */ +#include /* we use Gestalt to test for specific functionality */ + +#ifndef TEMP_FILE_NAME /* can override from jconfig.h or Makefile */ +#define TEMP_FILE_NAME "JPG%03d.TMP" +#endif + +static int next_file_num; /* to distinguish among several temp files */ + + +/* + * Memory allocation and freeing are controlled by the MacOS library + * routines NewPtr() and DisposePtr(), which allocate fixed-address + * storage. Unfortunately, the IJG library isn't smart enough to cope + * with relocatable storage. + */ + +GLOBAL(void *) +jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject) +{ + return (void *) NewPtr(sizeofobject); +} + +GLOBAL(void) +jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject) +{ + DisposePtr((Ptr) object); +} + + +/* + * "Large" objects are treated the same as "small" ones. + * NB: we include FAR keywords in the routine declarations simply for + * consistency with the rest of the IJG code; FAR should expand to empty + * on rational architectures like the Mac. + */ + +GLOBAL(void FAR *) +jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject) +{ + return (void FAR *) NewPtr(sizeofobject); +} + +GLOBAL(void) +jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject) +{ + DisposePtr((Ptr) object); +} + + +/* + * This routine computes the total memory space available for allocation. + */ + +GLOBAL(long) +jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed, + long max_bytes_needed, long already_allocated) +{ + long limit = cinfo->mem->max_memory_to_use - already_allocated; + long slop, mem; + + /* Don't ask for more than what application has told us we may use */ + if (max_bytes_needed > limit && limit > 0) + max_bytes_needed = limit; + /* Find whether there's a big enough free block in the heap. + * CompactMem tries to create a contiguous block of the requested size, + * and then returns the size of the largest free block (which could be + * much more or much less than we asked for). + * We add some slop to ensure we don't use up all available memory. + */ + slop = max_bytes_needed / 16 + 32768L; + mem = CompactMem(max_bytes_needed + slop) - slop; + if (mem < 0) + mem = 0; /* sigh, couldn't even get the slop */ + /* Don't take more than the application says we can have */ + if (mem > limit && limit > 0) + mem = limit; + return mem; +} + + +/* + * Backing store (temporary file) management. + * Backing store objects are only used when the value returned by + * jpeg_mem_available is less than the total space needed. You can dispense + * with these routines if you have plenty of virtual memory; see jmemnobs.c. + */ + + +METHODDEF(void) +read_backing_store (j_common_ptr cinfo, backing_store_ptr info, + void FAR * buffer_address, + long file_offset, long byte_count) +{ + long bytes = byte_count; + long retVal; + + if ( SetFPos ( info->temp_file, fsFromStart, file_offset ) != noErr ) + ERREXIT(cinfo, JERR_TFILE_SEEK); + + retVal = FSRead ( info->temp_file, &bytes, + (unsigned char *) buffer_address ); + if ( retVal != noErr || bytes != byte_count ) + ERREXIT(cinfo, JERR_TFILE_READ); +} + + +METHODDEF(void) +write_backing_store (j_common_ptr cinfo, backing_store_ptr info, + void FAR * buffer_address, + long file_offset, long byte_count) +{ + long bytes = byte_count; + long retVal; + + if ( SetFPos ( info->temp_file, fsFromStart, file_offset ) != noErr ) + ERREXIT(cinfo, JERR_TFILE_SEEK); + + retVal = FSWrite ( info->temp_file, &bytes, + (unsigned char *) buffer_address ); + if ( retVal != noErr || bytes != byte_count ) + ERREXIT(cinfo, JERR_TFILE_WRITE); +} + + +METHODDEF(void) +close_backing_store (j_common_ptr cinfo, backing_store_ptr info) +{ + FSClose ( info->temp_file ); + FSpDelete ( &(info->tempSpec) ); +} + + +/* + * Initial opening of a backing-store object. + * + * This version uses FindFolder to find the Temporary Items folder, + * and puts the temporary file in there. + */ + +GLOBAL(void) +jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info, + long total_bytes_needed) +{ + short tmpRef, vRefNum; + long dirID; + FInfo finderInfo; + FSSpec theSpec; + Str255 fName; + OSErr osErr; + long gestaltResponse = 0; + + /* Check that FSSpec calls are available. */ + osErr = Gestalt( gestaltFSAttr, &gestaltResponse ); + if ( ( osErr != noErr ) + || !( gestaltResponse & (1<temp_name, TEMP_FILE_NAME, next_file_num); + strcpy ( (Ptr)fName+1, info->temp_name ); + *fName = strlen (info->temp_name); + osErr = FSMakeFSSpec ( vRefNum, dirID, fName, &theSpec ); + + if ( (osErr = FSpGetFInfo ( &theSpec, &finderInfo ) ) != noErr ) + break; + } + + osErr = FSpCreate ( &theSpec, '????', '????', smSystemScript ); + if ( osErr != noErr ) + ERREXITS(cinfo, JERR_TFILE_CREATE, info->temp_name); + + osErr = FSpOpenDF ( &theSpec, fsRdWrPerm, &(info->temp_file) ); + if ( osErr != noErr ) + ERREXITS(cinfo, JERR_TFILE_CREATE, info->temp_name); + + info->tempSpec = theSpec; + + info->read_backing_store = read_backing_store; + info->write_backing_store = write_backing_store; + info->close_backing_store = close_backing_store; + TRACEMSS(cinfo, 1, JTRC_TFILE_OPEN, info->temp_name); +} + + +/* + * These routines take care of any system-dependent initialization and + * cleanup required. + */ + +GLOBAL(long) +jpeg_mem_init (j_common_ptr cinfo) +{ + next_file_num = 0; + + /* max_memory_to_use will be initialized to FreeMem()'s result; + * the calling application might later reduce it, for example + * to leave room to invoke multiple JPEG objects. + * Note that FreeMem returns the total number of free bytes; + * it may not be possible to allocate a single block of this size. + */ + return FreeMem(); +} + +GLOBAL(void) +jpeg_mem_term (j_common_ptr cinfo) +{ + /* no work */ +} diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jmemmgr.c b/lc-continuity/mk4/modimage/jpeg-6b/jmemmgr.c new file mode 100644 index 0000000000000000000000000000000000000000..d801b322da05e0cd033159ba973676e4305101ef --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jmemmgr.c @@ -0,0 +1,1118 @@ +/* + * jmemmgr.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the JPEG system-independent memory management + * routines. This code is usable across a wide variety of machines; most + * of the system dependencies have been isolated in a separate file. + * The major functions provided here are: + * * pool-based allocation and freeing of memory; + * * policy decisions about how to divide available memory among the + * virtual arrays; + * * control logic for swapping virtual arrays between main memory and + * backing storage. + * The separate system-dependent file provides the actual backing-storage + * access code, and it contains the policy decision about how much total + * main memory to use. + * This file is system-dependent in the sense that some of its functions + * are unnecessary in some systems. For example, if there is enough virtual + * memory so that backing storage will never be used, much of the virtual + * array control logic could be removed. (Of course, if you have that much + * memory then you shouldn't care about a little bit of unused code...) + */ + +#define JPEG_INTERNALS +#define AM_MEMORY_MANAGER /* we define jvirt_Xarray_control structs */ +#include "jinclude.h" +#include "jpeglib.h" +#include "jmemsys.h" /* import the system-dependent declarations */ + +#ifndef NO_GETENV +#ifndef HAVE_STDLIB_H /* should declare getenv() */ +extern char * getenv JPP((const char * name)); +#endif +#endif + + +/* + * Some important notes: + * The allocation routines provided here must never return NULL. + * They should exit to error_exit if unsuccessful. + * + * It's not a good idea to try to merge the sarray and barray routines, + * even though they are textually almost the same, because samples are + * usually stored as bytes while coefficients are shorts or ints. Thus, + * in machines where byte pointers have a different representation from + * word pointers, the resulting machine code could not be the same. + */ + + +/* + * Many machines require storage alignment: longs must start on 4-byte + * boundaries, doubles on 8-byte boundaries, etc. On such machines, malloc() + * always returns pointers that are multiples of the worst-case alignment + * requirement, and we had better do so too. + * There isn't any really portable way to determine the worst-case alignment + * requirement. This module assumes that the alignment requirement is + * multiples of sizeof(ALIGN_TYPE). + * By default, we define ALIGN_TYPE as double. This is necessary on some + * workstations (where doubles really do need 8-byte alignment) and will work + * fine on nearly everything. If your machine has lesser alignment needs, + * you can save a few bytes by making ALIGN_TYPE smaller. + * The only place I know of where this will NOT work is certain Macintosh + * 680x0 compilers that define double as a 10-byte IEEE extended float. + * Doing 10-byte alignment is counterproductive because longwords won't be + * aligned well. Put "#define ALIGN_TYPE long" in jconfig.h if you have + * such a compiler. + */ + +#ifndef ALIGN_TYPE /* so can override from jconfig.h */ +#define ALIGN_TYPE double +#endif + + +/* + * We allocate objects from "pools", where each pool is gotten with a single + * request to jpeg_get_small() or jpeg_get_large(). There is no per-object + * overhead within a pool, except for alignment padding. Each pool has a + * header with a link to the next pool of the same class. + * Small and large pool headers are identical except that the latter's + * link pointer must be FAR on 80x86 machines. + * Notice that the "real" header fields are union'ed with a dummy ALIGN_TYPE + * field. This forces the compiler to make SIZEOF(small_pool_hdr) a multiple + * of the alignment requirement of ALIGN_TYPE. + */ + +typedef union small_pool_struct * small_pool_ptr; + +typedef union small_pool_struct { + struct { + small_pool_ptr next; /* next in list of pools */ + size_t bytes_used; /* how many bytes already used within pool */ + size_t bytes_left; /* bytes still available in this pool */ + } hdr; + ALIGN_TYPE dummy; /* included in union to ensure alignment */ +} small_pool_hdr; + +typedef union large_pool_struct FAR * large_pool_ptr; + +typedef union large_pool_struct { + struct { + large_pool_ptr next; /* next in list of pools */ + size_t bytes_used; /* how many bytes already used within pool */ + size_t bytes_left; /* bytes still available in this pool */ + } hdr; + ALIGN_TYPE dummy; /* included in union to ensure alignment */ +} large_pool_hdr; + + +/* + * Here is the full definition of a memory manager object. + */ + +typedef struct { + struct jpeg_memory_mgr pub; /* public fields */ + + /* Each pool identifier (lifetime class) names a linked list of pools. */ + small_pool_ptr small_list[JPOOL_NUMPOOLS]; + large_pool_ptr large_list[JPOOL_NUMPOOLS]; + + /* Since we only have one lifetime class of virtual arrays, only one + * linked list is necessary (for each datatype). Note that the virtual + * array control blocks being linked together are actually stored somewhere + * in the small-pool list. + */ + jvirt_sarray_ptr virt_sarray_list; + jvirt_barray_ptr virt_barray_list; + + /* This counts total space obtained from jpeg_get_small/large */ + long total_space_allocated; + + /* alloc_sarray and alloc_barray set this value for use by virtual + * array routines. + */ + JDIMENSION last_rowsperchunk; /* from most recent alloc_sarray/barray */ +} my_memory_mgr; + +typedef my_memory_mgr * my_mem_ptr; + + +/* + * The control blocks for virtual arrays. + * Note that these blocks are allocated in the "small" pool area. + * System-dependent info for the associated backing store (if any) is hidden + * inside the backing_store_info struct. + */ + +struct jvirt_sarray_control { + JSAMPARRAY mem_buffer; /* => the in-memory buffer */ + JDIMENSION rows_in_array; /* total virtual array height */ + JDIMENSION samplesperrow; /* width of array (and of memory buffer) */ + JDIMENSION maxaccess; /* max rows accessed by access_virt_sarray */ + JDIMENSION rows_in_mem; /* height of memory buffer */ + JDIMENSION rowsperchunk; /* allocation chunk size in mem_buffer */ + JDIMENSION cur_start_row; /* first logical row # in the buffer */ + JDIMENSION first_undef_row; /* row # of first uninitialized row */ + boolean pre_zero; /* pre-zero mode requested? */ + boolean dirty; /* do current buffer contents need written? */ + boolean b_s_open; /* is backing-store data valid? */ + jvirt_sarray_ptr next; /* link to next virtual sarray control block */ + backing_store_info b_s_info; /* System-dependent control info */ +}; + +struct jvirt_barray_control { + JBLOCKARRAY mem_buffer; /* => the in-memory buffer */ + JDIMENSION rows_in_array; /* total virtual array height */ + JDIMENSION blocksperrow; /* width of array (and of memory buffer) */ + JDIMENSION maxaccess; /* max rows accessed by access_virt_barray */ + JDIMENSION rows_in_mem; /* height of memory buffer */ + JDIMENSION rowsperchunk; /* allocation chunk size in mem_buffer */ + JDIMENSION cur_start_row; /* first logical row # in the buffer */ + JDIMENSION first_undef_row; /* row # of first uninitialized row */ + boolean pre_zero; /* pre-zero mode requested? */ + boolean dirty; /* do current buffer contents need written? */ + boolean b_s_open; /* is backing-store data valid? */ + jvirt_barray_ptr next; /* link to next virtual barray control block */ + backing_store_info b_s_info; /* System-dependent control info */ +}; + + +#ifdef MEM_STATS /* optional extra stuff for statistics */ + +LOCAL(void) +print_mem_stats (j_common_ptr cinfo, int pool_id) +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + small_pool_ptr shdr_ptr; + large_pool_ptr lhdr_ptr; + + /* Since this is only a debugging stub, we can cheat a little by using + * fprintf directly rather than going through the trace message code. + * This is helpful because message parm array can't handle longs. + */ + fprintf(stderr, "Freeing pool %d, total space = %ld\n", + pool_id, mem->total_space_allocated); + + for (lhdr_ptr = mem->large_list[pool_id]; lhdr_ptr != NULL; + lhdr_ptr = lhdr_ptr->hdr.next) { + fprintf(stderr, " Large chunk used %ld\n", + (long) lhdr_ptr->hdr.bytes_used); + } + + for (shdr_ptr = mem->small_list[pool_id]; shdr_ptr != NULL; + shdr_ptr = shdr_ptr->hdr.next) { + fprintf(stderr, " Small chunk used %ld free %ld\n", + (long) shdr_ptr->hdr.bytes_used, + (long) shdr_ptr->hdr.bytes_left); + } +} + +#endif /* MEM_STATS */ + + +LOCAL(void) +out_of_memory (j_common_ptr cinfo, int which) +/* Report an out-of-memory error and stop execution */ +/* If we compiled MEM_STATS support, report alloc requests before dying */ +{ +#ifdef MEM_STATS + cinfo->err->trace_level = 2; /* force self_destruct to report stats */ +#endif + ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, which); +} + + +/* + * Allocation of "small" objects. + * + * For these, we use pooled storage. When a new pool must be created, + * we try to get enough space for the current request plus a "slop" factor, + * where the slop will be the amount of leftover space in the new pool. + * The speed vs. space tradeoff is largely determined by the slop values. + * A different slop value is provided for each pool class (lifetime), + * and we also distinguish the first pool of a class from later ones. + * NOTE: the values given work fairly well on both 16- and 32-bit-int + * machines, but may be too small if longs are 64 bits or more. + */ + +static const size_t first_pool_slop[JPOOL_NUMPOOLS] = +{ + 1600, /* first PERMANENT pool */ + 16000 /* first IMAGE pool */ +}; + +static const size_t extra_pool_slop[JPOOL_NUMPOOLS] = +{ + 0, /* additional PERMANENT pools */ + 5000 /* additional IMAGE pools */ +}; + +#define MIN_SLOP 50 /* greater than 0 to avoid futile looping */ + + +METHODDEF(void *) +alloc_small (j_common_ptr cinfo, int pool_id, size_t sizeofobject) +/* Allocate a "small" object */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + small_pool_ptr hdr_ptr, prev_hdr_ptr; + char * data_ptr; + size_t odd_bytes, min_request, slop; + + /* Check for unsatisfiable request (do now to ensure no overflow below) */ + if (sizeofobject > (size_t) (MAX_ALLOC_CHUNK-SIZEOF(small_pool_hdr))) + out_of_memory(cinfo, 1); /* request exceeds malloc's ability */ + + /* Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) */ + odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE); + if (odd_bytes > 0) + sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes; + + /* See if space is available in any existing pool */ + if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ + prev_hdr_ptr = NULL; + hdr_ptr = mem->small_list[pool_id]; + while (hdr_ptr != NULL) { + if (hdr_ptr->hdr.bytes_left >= sizeofobject) + break; /* found pool with enough space */ + prev_hdr_ptr = hdr_ptr; + hdr_ptr = hdr_ptr->hdr.next; + } + + /* Time to make a new pool? */ + if (hdr_ptr == NULL) { + /* min_request is what we need now, slop is what will be leftover */ + min_request = sizeofobject + SIZEOF(small_pool_hdr); + if (prev_hdr_ptr == NULL) /* first pool in class? */ + slop = first_pool_slop[pool_id]; + else + slop = extra_pool_slop[pool_id]; + /* Don't ask for more than MAX_ALLOC_CHUNK */ + if (slop > (size_t) (MAX_ALLOC_CHUNK-min_request)) + slop = (size_t) (MAX_ALLOC_CHUNK-min_request); + /* Try to get space, if fail reduce slop and try again */ + for (;;) { + hdr_ptr = (small_pool_ptr) jpeg_get_small(cinfo, min_request + slop); + if (hdr_ptr != NULL) + break; + slop /= 2; + if (slop < MIN_SLOP) /* give up when it gets real small */ + out_of_memory(cinfo, 2); /* jpeg_get_small failed */ + } + mem->total_space_allocated += min_request + slop; + /* Success, initialize the new pool header and add to end of list */ + hdr_ptr->hdr.next = NULL; + hdr_ptr->hdr.bytes_used = 0; + hdr_ptr->hdr.bytes_left = sizeofobject + slop; + if (prev_hdr_ptr == NULL) /* first pool in class? */ + mem->small_list[pool_id] = hdr_ptr; + else + prev_hdr_ptr->hdr.next = hdr_ptr; + } + + /* OK, allocate the object from the current pool */ + data_ptr = (char *) (hdr_ptr + 1); /* point to first data byte in pool */ + data_ptr += hdr_ptr->hdr.bytes_used; /* point to place for object */ + hdr_ptr->hdr.bytes_used += sizeofobject; + hdr_ptr->hdr.bytes_left -= sizeofobject; + + return (void *) data_ptr; +} + + +/* + * Allocation of "large" objects. + * + * The external semantics of these are the same as "small" objects, + * except that FAR pointers are used on 80x86. However the pool + * management heuristics are quite different. We assume that each + * request is large enough that it may as well be passed directly to + * jpeg_get_large; the pool management just links everything together + * so that we can free it all on demand. + * Note: the major use of "large" objects is in JSAMPARRAY and JBLOCKARRAY + * structures. The routines that create these structures (see below) + * deliberately bunch rows together to ensure a large request size. + */ + +METHODDEF(void FAR *) +alloc_large (j_common_ptr cinfo, int pool_id, size_t sizeofobject) +/* Allocate a "large" object */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + large_pool_ptr hdr_ptr; + size_t odd_bytes; + + /* Check for unsatisfiable request (do now to ensure no overflow below) */ + if (sizeofobject > (size_t) (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr))) + out_of_memory(cinfo, 3); /* request exceeds malloc's ability */ + + /* Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) */ + odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE); + if (odd_bytes > 0) + sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes; + + /* Always make a new pool */ + if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ + + hdr_ptr = (large_pool_ptr) jpeg_get_large(cinfo, sizeofobject + + SIZEOF(large_pool_hdr)); + if (hdr_ptr == NULL) + out_of_memory(cinfo, 4); /* jpeg_get_large failed */ + mem->total_space_allocated += sizeofobject + SIZEOF(large_pool_hdr); + + /* Success, initialize the new pool header and add to list */ + hdr_ptr->hdr.next = mem->large_list[pool_id]; + /* We maintain space counts in each pool header for statistical purposes, + * even though they are not needed for allocation. + */ + hdr_ptr->hdr.bytes_used = sizeofobject; + hdr_ptr->hdr.bytes_left = 0; + mem->large_list[pool_id] = hdr_ptr; + + return (void FAR *) (hdr_ptr + 1); /* point to first data byte in pool */ +} + + +/* + * Creation of 2-D sample arrays. + * The pointers are in near heap, the samples themselves in FAR heap. + * + * To minimize allocation overhead and to allow I/O of large contiguous + * blocks, we allocate the sample rows in groups of as many rows as possible + * without exceeding MAX_ALLOC_CHUNK total bytes per allocation request. + * NB: the virtual array control routines, later in this file, know about + * this chunking of rows. The rowsperchunk value is left in the mem manager + * object so that it can be saved away if this sarray is the workspace for + * a virtual array. + */ + +METHODDEF(JSAMPARRAY) +alloc_sarray (j_common_ptr cinfo, int pool_id, + JDIMENSION samplesperrow, JDIMENSION numrows) +/* Allocate a 2-D sample array */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + JSAMPARRAY result; + JSAMPROW workspace; + JDIMENSION rowsperchunk, currow, i; + long ltemp; + + /* Calculate max # of rows allowed in one allocation chunk */ + ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) / + ((long) samplesperrow * SIZEOF(JSAMPLE)); + if (ltemp <= 0) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + if (ltemp < (long) numrows) + rowsperchunk = (JDIMENSION) ltemp; + else + rowsperchunk = numrows; + mem->last_rowsperchunk = rowsperchunk; + + /* Get space for row pointers (small object) */ + result = (JSAMPARRAY) alloc_small(cinfo, pool_id, + (size_t) (numrows * SIZEOF(JSAMPROW))); + + /* Get the rows themselves (large objects) */ + currow = 0; + while (currow < numrows) { + rowsperchunk = MIN(rowsperchunk, numrows - currow); + workspace = (JSAMPROW) alloc_large(cinfo, pool_id, + (size_t) ((size_t) rowsperchunk * (size_t) samplesperrow + * SIZEOF(JSAMPLE))); + for (i = rowsperchunk; i > 0; i--) { + result[currow++] = workspace; + workspace += samplesperrow; + } + } + + return result; +} + + +/* + * Creation of 2-D coefficient-block arrays. + * This is essentially the same as the code for sample arrays, above. + */ + +METHODDEF(JBLOCKARRAY) +alloc_barray (j_common_ptr cinfo, int pool_id, + JDIMENSION blocksperrow, JDIMENSION numrows) +/* Allocate a 2-D coefficient-block array */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + JBLOCKARRAY result; + JBLOCKROW workspace; + JDIMENSION rowsperchunk, currow, i; + long ltemp; + + /* Calculate max # of rows allowed in one allocation chunk */ + ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) / + ((long) blocksperrow * SIZEOF(JBLOCK)); + if (ltemp <= 0) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + if (ltemp < (long) numrows) + rowsperchunk = (JDIMENSION) ltemp; + else + rowsperchunk = numrows; + mem->last_rowsperchunk = rowsperchunk; + + /* Get space for row pointers (small object) */ + result = (JBLOCKARRAY) alloc_small(cinfo, pool_id, + (size_t) (numrows * SIZEOF(JBLOCKROW))); + + /* Get the rows themselves (large objects) */ + currow = 0; + while (currow < numrows) { + rowsperchunk = MIN(rowsperchunk, numrows - currow); + workspace = (JBLOCKROW) alloc_large(cinfo, pool_id, + (size_t) ((size_t) rowsperchunk * (size_t) blocksperrow + * SIZEOF(JBLOCK))); + for (i = rowsperchunk; i > 0; i--) { + result[currow++] = workspace; + workspace += blocksperrow; + } + } + + return result; +} + + +/* + * About virtual array management: + * + * The above "normal" array routines are only used to allocate strip buffers + * (as wide as the image, but just a few rows high). Full-image-sized buffers + * are handled as "virtual" arrays. The array is still accessed a strip at a + * time, but the memory manager must save the whole array for repeated + * accesses. The intended implementation is that there is a strip buffer in + * memory (as high as is possible given the desired memory limit), plus a + * backing file that holds the rest of the array. + * + * The request_virt_array routines are told the total size of the image and + * the maximum number of rows that will be accessed at once. The in-memory + * buffer must be at least as large as the maxaccess value. + * + * The request routines create control blocks but not the in-memory buffers. + * That is postponed until realize_virt_arrays is called. At that time the + * total amount of space needed is known (approximately, anyway), so free + * memory can be divided up fairly. + * + * The access_virt_array routines are responsible for making a specific strip + * area accessible (after reading or writing the backing file, if necessary). + * Note that the access routines are told whether the caller intends to modify + * the accessed strip; during a read-only pass this saves having to rewrite + * data to disk. The access routines are also responsible for pre-zeroing + * any newly accessed rows, if pre-zeroing was requested. + * + * In current usage, the access requests are usually for nonoverlapping + * strips; that is, successive access start_row numbers differ by exactly + * num_rows = maxaccess. This means we can get good performance with simple + * buffer dump/reload logic, by making the in-memory buffer be a multiple + * of the access height; then there will never be accesses across bufferload + * boundaries. The code will still work with overlapping access requests, + * but it doesn't handle bufferload overlaps very efficiently. + */ + + +METHODDEF(jvirt_sarray_ptr) +request_virt_sarray (j_common_ptr cinfo, int pool_id, boolean pre_zero, + JDIMENSION samplesperrow, JDIMENSION numrows, + JDIMENSION maxaccess) +/* Request a virtual 2-D sample array */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + jvirt_sarray_ptr result; + + /* Only IMAGE-lifetime virtual arrays are currently supported */ + if (pool_id != JPOOL_IMAGE) + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ + + /* get control block */ + result = (jvirt_sarray_ptr) alloc_small(cinfo, pool_id, + SIZEOF(struct jvirt_sarray_control)); + + result->mem_buffer = NULL; /* marks array not yet realized */ + result->rows_in_array = numrows; + result->samplesperrow = samplesperrow; + result->maxaccess = maxaccess; + result->pre_zero = pre_zero; + result->b_s_open = FALSE; /* no associated backing-store object */ + result->next = mem->virt_sarray_list; /* add to list of virtual arrays */ + mem->virt_sarray_list = result; + + return result; +} + + +METHODDEF(jvirt_barray_ptr) +request_virt_barray (j_common_ptr cinfo, int pool_id, boolean pre_zero, + JDIMENSION blocksperrow, JDIMENSION numrows, + JDIMENSION maxaccess) +/* Request a virtual 2-D coefficient-block array */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + jvirt_barray_ptr result; + + /* Only IMAGE-lifetime virtual arrays are currently supported */ + if (pool_id != JPOOL_IMAGE) + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ + + /* get control block */ + result = (jvirt_barray_ptr) alloc_small(cinfo, pool_id, + SIZEOF(struct jvirt_barray_control)); + + result->mem_buffer = NULL; /* marks array not yet realized */ + result->rows_in_array = numrows; + result->blocksperrow = blocksperrow; + result->maxaccess = maxaccess; + result->pre_zero = pre_zero; + result->b_s_open = FALSE; /* no associated backing-store object */ + result->next = mem->virt_barray_list; /* add to list of virtual arrays */ + mem->virt_barray_list = result; + + return result; +} + + +METHODDEF(void) +realize_virt_arrays (j_common_ptr cinfo) +/* Allocate the in-memory buffers for any unrealized virtual arrays */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + long space_per_minheight, maximum_space, avail_mem; + long minheights, max_minheights; + jvirt_sarray_ptr sptr; + jvirt_barray_ptr bptr; + + /* Compute the minimum space needed (maxaccess rows in each buffer) + * and the maximum space needed (full image height in each buffer). + * These may be of use to the system-dependent jpeg_mem_available routine. + */ + space_per_minheight = 0; + maximum_space = 0; + for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { + if (sptr->mem_buffer == NULL) { /* if not realized yet */ + space_per_minheight += (long) sptr->maxaccess * + (long) sptr->samplesperrow * SIZEOF(JSAMPLE); + maximum_space += (long) sptr->rows_in_array * + (long) sptr->samplesperrow * SIZEOF(JSAMPLE); + } + } + for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { + if (bptr->mem_buffer == NULL) { /* if not realized yet */ + space_per_minheight += (long) bptr->maxaccess * + (long) bptr->blocksperrow * SIZEOF(JBLOCK); + maximum_space += (long) bptr->rows_in_array * + (long) bptr->blocksperrow * SIZEOF(JBLOCK); + } + } + + if (space_per_minheight <= 0) + return; /* no unrealized arrays, no work */ + + /* Determine amount of memory to actually use; this is system-dependent. */ + avail_mem = jpeg_mem_available(cinfo, space_per_minheight, maximum_space, + mem->total_space_allocated); + + /* If the maximum space needed is available, make all the buffers full + * height; otherwise parcel it out with the same number of minheights + * in each buffer. + */ + if (avail_mem >= maximum_space) + max_minheights = 1000000000L; + else { + max_minheights = avail_mem / space_per_minheight; + /* If there doesn't seem to be enough space, try to get the minimum + * anyway. This allows a "stub" implementation of jpeg_mem_available(). + */ + if (max_minheights <= 0) + max_minheights = 1; + } + + /* Allocate the in-memory buffers and initialize backing store as needed. */ + + for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { + if (sptr->mem_buffer == NULL) { /* if not realized yet */ + minheights = ((long) sptr->rows_in_array - 1L) / sptr->maxaccess + 1L; + if (minheights <= max_minheights) { + /* This buffer fits in memory */ + sptr->rows_in_mem = sptr->rows_in_array; + } else { + /* It doesn't fit in memory, create backing store. */ + sptr->rows_in_mem = (JDIMENSION) (max_minheights * sptr->maxaccess); + jpeg_open_backing_store(cinfo, & sptr->b_s_info, + (long) sptr->rows_in_array * + (long) sptr->samplesperrow * + (long) SIZEOF(JSAMPLE)); + sptr->b_s_open = TRUE; + } + sptr->mem_buffer = alloc_sarray(cinfo, JPOOL_IMAGE, + sptr->samplesperrow, sptr->rows_in_mem); + sptr->rowsperchunk = mem->last_rowsperchunk; + sptr->cur_start_row = 0; + sptr->first_undef_row = 0; + sptr->dirty = FALSE; + } + } + + for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { + if (bptr->mem_buffer == NULL) { /* if not realized yet */ + minheights = ((long) bptr->rows_in_array - 1L) / bptr->maxaccess + 1L; + if (minheights <= max_minheights) { + /* This buffer fits in memory */ + bptr->rows_in_mem = bptr->rows_in_array; + } else { + /* It doesn't fit in memory, create backing store. */ + bptr->rows_in_mem = (JDIMENSION) (max_minheights * bptr->maxaccess); + jpeg_open_backing_store(cinfo, & bptr->b_s_info, + (long) bptr->rows_in_array * + (long) bptr->blocksperrow * + (long) SIZEOF(JBLOCK)); + bptr->b_s_open = TRUE; + } + bptr->mem_buffer = alloc_barray(cinfo, JPOOL_IMAGE, + bptr->blocksperrow, bptr->rows_in_mem); + bptr->rowsperchunk = mem->last_rowsperchunk; + bptr->cur_start_row = 0; + bptr->first_undef_row = 0; + bptr->dirty = FALSE; + } + } +} + + +LOCAL(void) +do_sarray_io (j_common_ptr cinfo, jvirt_sarray_ptr ptr, boolean writing) +/* Do backing store read or write of a virtual sample array */ +{ + long bytesperrow, file_offset, byte_count, rows, thisrow, i; + + bytesperrow = (long) ptr->samplesperrow * SIZEOF(JSAMPLE); + file_offset = ptr->cur_start_row * bytesperrow; + /* Loop to read or write each allocation chunk in mem_buffer */ + for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) { + /* One chunk, but check for short chunk at end of buffer */ + rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i); + /* Transfer no more than is currently defined */ + thisrow = (long) ptr->cur_start_row + i; + rows = MIN(rows, (long) ptr->first_undef_row - thisrow); + /* Transfer no more than fits in file */ + rows = MIN(rows, (long) ptr->rows_in_array - thisrow); + if (rows <= 0) /* this chunk might be past end of file! */ + break; + byte_count = rows * bytesperrow; + if (writing) + (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info, + (void FAR *) ptr->mem_buffer[i], + file_offset, byte_count); + else + (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info, + (void FAR *) ptr->mem_buffer[i], + file_offset, byte_count); + file_offset += byte_count; + } +} + + +LOCAL(void) +do_barray_io (j_common_ptr cinfo, jvirt_barray_ptr ptr, boolean writing) +/* Do backing store read or write of a virtual coefficient-block array */ +{ + long bytesperrow, file_offset, byte_count, rows, thisrow, i; + + bytesperrow = (long) ptr->blocksperrow * SIZEOF(JBLOCK); + file_offset = ptr->cur_start_row * bytesperrow; + /* Loop to read or write each allocation chunk in mem_buffer */ + for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) { + /* One chunk, but check for short chunk at end of buffer */ + rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i); + /* Transfer no more than is currently defined */ + thisrow = (long) ptr->cur_start_row + i; + rows = MIN(rows, (long) ptr->first_undef_row - thisrow); + /* Transfer no more than fits in file */ + rows = MIN(rows, (long) ptr->rows_in_array - thisrow); + if (rows <= 0) /* this chunk might be past end of file! */ + break; + byte_count = rows * bytesperrow; + if (writing) + (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info, + (void FAR *) ptr->mem_buffer[i], + file_offset, byte_count); + else + (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info, + (void FAR *) ptr->mem_buffer[i], + file_offset, byte_count); + file_offset += byte_count; + } +} + + +METHODDEF(JSAMPARRAY) +access_virt_sarray (j_common_ptr cinfo, jvirt_sarray_ptr ptr, + JDIMENSION start_row, JDIMENSION num_rows, + boolean writable) +/* Access the part of a virtual sample array starting at start_row */ +/* and extending for num_rows rows. writable is true if */ +/* caller intends to modify the accessed area. */ +{ + JDIMENSION end_row = start_row + num_rows; + JDIMENSION undef_row; + + /* debugging check */ + if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess || + ptr->mem_buffer == NULL) + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + + /* Make the desired part of the virtual array accessible */ + if (start_row < ptr->cur_start_row || + end_row > ptr->cur_start_row+ptr->rows_in_mem) { + if (! ptr->b_s_open) + ERREXIT(cinfo, JERR_VIRTUAL_BUG); + /* Flush old buffer contents if necessary */ + if (ptr->dirty) { + do_sarray_io(cinfo, ptr, TRUE); + ptr->dirty = FALSE; + } + /* Decide what part of virtual array to access. + * Algorithm: if target address > current window, assume forward scan, + * load starting at target address. If target address < current window, + * assume backward scan, load so that target area is top of window. + * Note that when switching from forward write to forward read, will have + * start_row = 0, so the limiting case applies and we load from 0 anyway. + */ + if (start_row > ptr->cur_start_row) { + ptr->cur_start_row = start_row; + } else { + /* use long arithmetic here to avoid overflow & unsigned problems */ + long ltemp; + + ltemp = (long) end_row - (long) ptr->rows_in_mem; + if (ltemp < 0) + ltemp = 0; /* don't fall off front end of file */ + ptr->cur_start_row = (JDIMENSION) ltemp; + } + /* Read in the selected part of the array. + * During the initial write pass, we will do no actual read + * because the selected part is all undefined. + */ + do_sarray_io(cinfo, ptr, FALSE); + } + /* Ensure the accessed part of the array is defined; prezero if needed. + * To improve locality of access, we only prezero the part of the array + * that the caller is about to access, not the entire in-memory array. + */ + if (ptr->first_undef_row < end_row) { + if (ptr->first_undef_row < start_row) { + if (writable) /* writer skipped over a section of array */ + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + undef_row = start_row; /* but reader is allowed to read ahead */ + } else { + undef_row = ptr->first_undef_row; + } + if (writable) + ptr->first_undef_row = end_row; + if (ptr->pre_zero) { + size_t bytesperrow = (size_t) ptr->samplesperrow * SIZEOF(JSAMPLE); + undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */ + end_row -= ptr->cur_start_row; + while (undef_row < end_row) { + jzero_far((void FAR *) ptr->mem_buffer[undef_row], bytesperrow); + undef_row++; + } + } else { + if (! writable) /* reader looking at undefined data */ + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + } + } + /* Flag the buffer dirty if caller will write in it */ + if (writable) + ptr->dirty = TRUE; + /* Return address of proper part of the buffer */ + return ptr->mem_buffer + (start_row - ptr->cur_start_row); +} + + +METHODDEF(JBLOCKARRAY) +access_virt_barray (j_common_ptr cinfo, jvirt_barray_ptr ptr, + JDIMENSION start_row, JDIMENSION num_rows, + boolean writable) +/* Access the part of a virtual block array starting at start_row */ +/* and extending for num_rows rows. writable is true if */ +/* caller intends to modify the accessed area. */ +{ + JDIMENSION end_row = start_row + num_rows; + JDIMENSION undef_row; + + /* debugging check */ + if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess || + ptr->mem_buffer == NULL) + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + + /* Make the desired part of the virtual array accessible */ + if (start_row < ptr->cur_start_row || + end_row > ptr->cur_start_row+ptr->rows_in_mem) { + if (! ptr->b_s_open) + ERREXIT(cinfo, JERR_VIRTUAL_BUG); + /* Flush old buffer contents if necessary */ + if (ptr->dirty) { + do_barray_io(cinfo, ptr, TRUE); + ptr->dirty = FALSE; + } + /* Decide what part of virtual array to access. + * Algorithm: if target address > current window, assume forward scan, + * load starting at target address. If target address < current window, + * assume backward scan, load so that target area is top of window. + * Note that when switching from forward write to forward read, will have + * start_row = 0, so the limiting case applies and we load from 0 anyway. + */ + if (start_row > ptr->cur_start_row) { + ptr->cur_start_row = start_row; + } else { + /* use long arithmetic here to avoid overflow & unsigned problems */ + long ltemp; + + ltemp = (long) end_row - (long) ptr->rows_in_mem; + if (ltemp < 0) + ltemp = 0; /* don't fall off front end of file */ + ptr->cur_start_row = (JDIMENSION) ltemp; + } + /* Read in the selected part of the array. + * During the initial write pass, we will do no actual read + * because the selected part is all undefined. + */ + do_barray_io(cinfo, ptr, FALSE); + } + /* Ensure the accessed part of the array is defined; prezero if needed. + * To improve locality of access, we only prezero the part of the array + * that the caller is about to access, not the entire in-memory array. + */ + if (ptr->first_undef_row < end_row) { + if (ptr->first_undef_row < start_row) { + if (writable) /* writer skipped over a section of array */ + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + undef_row = start_row; /* but reader is allowed to read ahead */ + } else { + undef_row = ptr->first_undef_row; + } + if (writable) + ptr->first_undef_row = end_row; + if (ptr->pre_zero) { + size_t bytesperrow = (size_t) ptr->blocksperrow * SIZEOF(JBLOCK); + undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */ + end_row -= ptr->cur_start_row; + while (undef_row < end_row) { + jzero_far((void FAR *) ptr->mem_buffer[undef_row], bytesperrow); + undef_row++; + } + } else { + if (! writable) /* reader looking at undefined data */ + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + } + } + /* Flag the buffer dirty if caller will write in it */ + if (writable) + ptr->dirty = TRUE; + /* Return address of proper part of the buffer */ + return ptr->mem_buffer + (start_row - ptr->cur_start_row); +} + + +/* + * Release all objects belonging to a specified pool. + */ + +METHODDEF(void) +free_pool (j_common_ptr cinfo, int pool_id) +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + small_pool_ptr shdr_ptr; + large_pool_ptr lhdr_ptr; + size_t space_freed; + + if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ + +#ifdef MEM_STATS + if (cinfo->err->trace_level > 1) + print_mem_stats(cinfo, pool_id); /* print pool's memory usage statistics */ +#endif + + /* If freeing IMAGE pool, close any virtual arrays first */ + if (pool_id == JPOOL_IMAGE) { + jvirt_sarray_ptr sptr; + jvirt_barray_ptr bptr; + + for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { + if (sptr->b_s_open) { /* there may be no backing store */ + sptr->b_s_open = FALSE; /* prevent recursive close if error */ + (*sptr->b_s_info.close_backing_store) (cinfo, & sptr->b_s_info); + } + } + mem->virt_sarray_list = NULL; + for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { + if (bptr->b_s_open) { /* there may be no backing store */ + bptr->b_s_open = FALSE; /* prevent recursive close if error */ + (*bptr->b_s_info.close_backing_store) (cinfo, & bptr->b_s_info); + } + } + mem->virt_barray_list = NULL; + } + + /* Release large objects */ + lhdr_ptr = mem->large_list[pool_id]; + mem->large_list[pool_id] = NULL; + + while (lhdr_ptr != NULL) { + large_pool_ptr next_lhdr_ptr = lhdr_ptr->hdr.next; + space_freed = lhdr_ptr->hdr.bytes_used + + lhdr_ptr->hdr.bytes_left + + SIZEOF(large_pool_hdr); + jpeg_free_large(cinfo, (void FAR *) lhdr_ptr, space_freed); + mem->total_space_allocated -= space_freed; + lhdr_ptr = next_lhdr_ptr; + } + + /* Release small objects */ + shdr_ptr = mem->small_list[pool_id]; + mem->small_list[pool_id] = NULL; + + while (shdr_ptr != NULL) { + small_pool_ptr next_shdr_ptr = shdr_ptr->hdr.next; + space_freed = shdr_ptr->hdr.bytes_used + + shdr_ptr->hdr.bytes_left + + SIZEOF(small_pool_hdr); + jpeg_free_small(cinfo, (void *) shdr_ptr, space_freed); + mem->total_space_allocated -= space_freed; + shdr_ptr = next_shdr_ptr; + } +} + + +/* + * Close up shop entirely. + * Note that this cannot be called unless cinfo->mem is non-NULL. + */ + +METHODDEF(void) +self_destruct (j_common_ptr cinfo) +{ + int pool; + + /* Close all backing store, release all memory. + * Releasing pools in reverse order might help avoid fragmentation + * with some (brain-damaged) malloc libraries. + */ + for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) { + free_pool(cinfo, pool); + } + + /* Release the memory manager control block too. */ + jpeg_free_small(cinfo, (void *) cinfo->mem, SIZEOF(my_memory_mgr)); + cinfo->mem = NULL; /* ensures I will be called only once */ + + jpeg_mem_term(cinfo); /* system-dependent cleanup */ +} + + +/* + * Memory manager initialization. + * When this is called, only the error manager pointer is valid in cinfo! + */ + +GLOBAL(void) +jinit_memory_mgr (j_common_ptr cinfo) +{ + my_mem_ptr mem; + long max_to_use; + int pool; + size_t test_mac; + + cinfo->mem = NULL; /* for safety if init fails */ + + /* Check for configuration errors. + * SIZEOF(ALIGN_TYPE) should be a power of 2; otherwise, it probably + * doesn't reflect any real hardware alignment requirement. + * The test is a little tricky: for X>0, X and X-1 have no one-bits + * in common if and only if X is a power of 2, ie has only one one-bit. + * Some compilers may give an "unreachable code" warning here; ignore it. + */ + if ((SIZEOF(ALIGN_TYPE) & (SIZEOF(ALIGN_TYPE)-1)) != 0) + ERREXIT(cinfo, JERR_BAD_ALIGN_TYPE); + /* MAX_ALLOC_CHUNK must be representable as type size_t, and must be + * a multiple of SIZEOF(ALIGN_TYPE). + * Again, an "unreachable code" warning may be ignored here. + * But a "constant too large" warning means you need to fix MAX_ALLOC_CHUNK. + */ + test_mac = (size_t) MAX_ALLOC_CHUNK; + if ((long) test_mac != MAX_ALLOC_CHUNK || + (MAX_ALLOC_CHUNK % SIZEOF(ALIGN_TYPE)) != 0) + ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK); + + max_to_use = jpeg_mem_init(cinfo); /* system-dependent initialization */ + + /* Attempt to allocate memory manager's control block */ + mem = (my_mem_ptr) jpeg_get_small(cinfo, SIZEOF(my_memory_mgr)); + + if (mem == NULL) { + jpeg_mem_term(cinfo); /* system-dependent cleanup */ + ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 0); + } + + /* OK, fill in the method pointers */ + mem->pub.alloc_small = alloc_small; + mem->pub.alloc_large = alloc_large; + mem->pub.alloc_sarray = alloc_sarray; + mem->pub.alloc_barray = alloc_barray; + mem->pub.request_virt_sarray = request_virt_sarray; + mem->pub.request_virt_barray = request_virt_barray; + mem->pub.realize_virt_arrays = realize_virt_arrays; + mem->pub.access_virt_sarray = access_virt_sarray; + mem->pub.access_virt_barray = access_virt_barray; + mem->pub.free_pool = free_pool; + mem->pub.self_destruct = self_destruct; + + /* Make MAX_ALLOC_CHUNK accessible to other modules */ + mem->pub.max_alloc_chunk = MAX_ALLOC_CHUNK; + + /* Initialize working state */ + mem->pub.max_memory_to_use = max_to_use; + + for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) { + mem->small_list[pool] = NULL; + mem->large_list[pool] = NULL; + } + mem->virt_sarray_list = NULL; + mem->virt_barray_list = NULL; + + mem->total_space_allocated = SIZEOF(my_memory_mgr); + + /* Declare ourselves open for business */ + cinfo->mem = & mem->pub; + + /* Check for an environment variable JPEGMEM; if found, override the + * default max_memory setting from jpeg_mem_init. Note that the + * surrounding application may again override this value. + * If your system doesn't support getenv(), define NO_GETENV to disable + * this feature. + */ +#ifndef NO_GETENV + { char * memenv; + + if ((memenv = getenv("JPEGMEM")) != NULL) { + char ch = 'x'; + + if (sscanf(memenv, "%ld%c", &max_to_use, &ch) > 0) { + if (ch == 'm' || ch == 'M') + max_to_use *= 1000L; + mem->pub.max_memory_to_use = max_to_use * 1000L; + } + } + } +#endif + +} diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jmemname.c b/lc-continuity/mk4/modimage/jpeg-6b/jmemname.c new file mode 100644 index 0000000000000000000000000000000000000000..ed96dee1bc8d3b72c1d3853527d6efd86aa25485 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jmemname.c @@ -0,0 +1,276 @@ +/* + * jmemname.c + * + * Copyright (C) 1992-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file provides a generic implementation of the system-dependent + * portion of the JPEG memory manager. This implementation assumes that + * you must explicitly construct a name for each temp file. + * Also, the problem of determining the amount of memory available + * is shoved onto the user. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jmemsys.h" /* import the system-dependent declarations */ + +#ifndef HAVE_STDLIB_H /* should declare malloc(),free() */ +extern void * malloc JPP((size_t size)); +extern void free JPP((void *ptr)); +#endif + +#ifndef SEEK_SET /* pre-ANSI systems may not define this; */ +#define SEEK_SET 0 /* if not, assume 0 is correct */ +#endif + +#ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */ +#define READ_BINARY "r" +#define RW_BINARY "w+" +#else +#ifdef VMS /* VMS is very nonstandard */ +#define READ_BINARY "rb", "ctx=stm" +#define RW_BINARY "w+b", "ctx=stm" +#else /* standard ANSI-compliant case */ +#define READ_BINARY "rb" +#define RW_BINARY "w+b" +#endif +#endif + + +/* + * Selection of a file name for a temporary file. + * This is system-dependent! + * + * The code as given is suitable for most Unix systems, and it is easily + * modified for most non-Unix systems. Some notes: + * 1. The temp file is created in the directory named by TEMP_DIRECTORY. + * The default value is /usr/tmp, which is the conventional place for + * creating large temp files on Unix. On other systems you'll probably + * want to change the file location. You can do this by editing the + * #define, or (preferred) by defining TEMP_DIRECTORY in jconfig.h. + * + * 2. If you need to change the file name as well as its location, + * you can override the TEMP_FILE_NAME macro. (Note that this is + * actually a printf format string; it must contain %s and %d.) + * Few people should need to do this. + * + * 3. mktemp() is used to ensure that multiple processes running + * simultaneously won't select the same file names. If your system + * doesn't have mktemp(), define NO_MKTEMP to do it the hard way. + * (If you don't have , also define NO_ERRNO_H.) + * + * 4. You probably want to define NEED_SIGNAL_CATCHER so that cjpeg.c/djpeg.c + * will cause the temp files to be removed if you stop the program early. + */ + +#ifndef TEMP_DIRECTORY /* can override from jconfig.h or Makefile */ +#define TEMP_DIRECTORY "/usr/tmp/" /* recommended setting for Unix */ +#endif + +static int next_file_num; /* to distinguish among several temp files */ + +#ifdef NO_MKTEMP + +#ifndef TEMP_FILE_NAME /* can override from jconfig.h or Makefile */ +#define TEMP_FILE_NAME "%sJPG%03d.TMP" +#endif + +#ifndef NO_ERRNO_H +#include /* to define ENOENT */ +#endif + +/* ANSI C specifies that errno is a macro, but on older systems it's more + * likely to be a plain int variable. And not all versions of errno.h + * bother to declare it, so we have to in order to be most portable. Thus: + */ +#ifndef errno +extern int errno; +#endif + + +LOCAL(void) +select_file_name (char * fname) +{ + FILE * tfile; + + /* Keep generating file names till we find one that's not in use */ + for (;;) { + next_file_num++; /* advance counter */ + sprintf(fname, TEMP_FILE_NAME, TEMP_DIRECTORY, next_file_num); + if ((tfile = fopen(fname, READ_BINARY)) == NULL) { + /* fopen could have failed for a reason other than the file not + * being there; for example, file there but unreadable. + * If isn't available, then we cannot test the cause. + */ +#ifdef ENOENT + if (errno != ENOENT) + continue; +#endif + break; + } + fclose(tfile); /* oops, it's there; close tfile & try again */ + } +} + +#else /* ! NO_MKTEMP */ + +/* Note that mktemp() requires the initial filename to end in six X's */ +#ifndef TEMP_FILE_NAME /* can override from jconfig.h or Makefile */ +#define TEMP_FILE_NAME "%sJPG%dXXXXXX" +#endif + +LOCAL(void) +select_file_name (char * fname) +{ + next_file_num++; /* advance counter */ + sprintf(fname, TEMP_FILE_NAME, TEMP_DIRECTORY, next_file_num); + mktemp(fname); /* make sure file name is unique */ + /* mktemp replaces the trailing XXXXXX with a unique string of characters */ +} + +#endif /* NO_MKTEMP */ + + +/* + * Memory allocation and freeing are controlled by the regular library + * routines malloc() and free(). + */ + +GLOBAL(void *) +jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject) +{ + return (void *) malloc(sizeofobject); +} + +GLOBAL(void) +jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject) +{ + free(object); +} + + +/* + * "Large" objects are treated the same as "small" ones. + * NB: although we include FAR keywords in the routine declarations, + * this file won't actually work in 80x86 small/medium model; at least, + * you probably won't be able to process useful-size images in only 64KB. + */ + +GLOBAL(void FAR *) +jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject) +{ + return (void FAR *) malloc(sizeofobject); +} + +GLOBAL(void) +jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject) +{ + free(object); +} + + +/* + * This routine computes the total memory space available for allocation. + * It's impossible to do this in a portable way; our current solution is + * to make the user tell us (with a default value set at compile time). + * If you can actually get the available space, it's a good idea to subtract + * a slop factor of 5% or so. + */ + +#ifndef DEFAULT_MAX_MEM /* so can override from makefile */ +#define DEFAULT_MAX_MEM 1000000L /* default: one megabyte */ +#endif + +GLOBAL(long) +jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed, + long max_bytes_needed, long already_allocated) +{ + return cinfo->mem->max_memory_to_use - already_allocated; +} + + +/* + * Backing store (temporary file) management. + * Backing store objects are only used when the value returned by + * jpeg_mem_available is less than the total space needed. You can dispense + * with these routines if you have plenty of virtual memory; see jmemnobs.c. + */ + + +METHODDEF(void) +read_backing_store (j_common_ptr cinfo, backing_store_ptr info, + void FAR * buffer_address, + long file_offset, long byte_count) +{ + if (fseek(info->temp_file, file_offset, SEEK_SET)) + ERREXIT(cinfo, JERR_TFILE_SEEK); + if (JFREAD(info->temp_file, buffer_address, byte_count) + != (size_t) byte_count) + ERREXIT(cinfo, JERR_TFILE_READ); +} + + +METHODDEF(void) +write_backing_store (j_common_ptr cinfo, backing_store_ptr info, + void FAR * buffer_address, + long file_offset, long byte_count) +{ + if (fseek(info->temp_file, file_offset, SEEK_SET)) + ERREXIT(cinfo, JERR_TFILE_SEEK); + if (JFWRITE(info->temp_file, buffer_address, byte_count) + != (size_t) byte_count) + ERREXIT(cinfo, JERR_TFILE_WRITE); +} + + +METHODDEF(void) +close_backing_store (j_common_ptr cinfo, backing_store_ptr info) +{ + fclose(info->temp_file); /* close the file */ + unlink(info->temp_name); /* delete the file */ +/* If your system doesn't have unlink(), use remove() instead. + * remove() is the ANSI-standard name for this function, but if + * your system was ANSI you'd be using jmemansi.c, right? + */ + TRACEMSS(cinfo, 1, JTRC_TFILE_CLOSE, info->temp_name); +} + + +/* + * Initial opening of a backing-store object. + */ + +GLOBAL(void) +jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info, + long total_bytes_needed) +{ + select_file_name(info->temp_name); + if ((info->temp_file = fopen(info->temp_name, RW_BINARY)) == NULL) + ERREXITS(cinfo, JERR_TFILE_CREATE, info->temp_name); + info->read_backing_store = read_backing_store; + info->write_backing_store = write_backing_store; + info->close_backing_store = close_backing_store; + TRACEMSS(cinfo, 1, JTRC_TFILE_OPEN, info->temp_name); +} + + +/* + * These routines take care of any system-dependent initialization and + * cleanup required. + */ + +GLOBAL(long) +jpeg_mem_init (j_common_ptr cinfo) +{ + next_file_num = 0; /* initialize temp file name generator */ + return DEFAULT_MAX_MEM; /* default for max_memory_to_use */ +} + +GLOBAL(void) +jpeg_mem_term (j_common_ptr cinfo) +{ + /* no work */ +} diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jmemnobs.c b/lc-continuity/mk4/modimage/jpeg-6b/jmemnobs.c new file mode 100644 index 0000000000000000000000000000000000000000..eb8c337725fd85f289b04eebbea8549d90d53c77 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jmemnobs.c @@ -0,0 +1,109 @@ +/* + * jmemnobs.c + * + * Copyright (C) 1992-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file provides a really simple implementation of the system- + * dependent portion of the JPEG memory manager. This implementation + * assumes that no backing-store files are needed: all required space + * can be obtained from malloc(). + * This is very portable in the sense that it'll compile on almost anything, + * but you'd better have lots of main memory (or virtual memory) if you want + * to process big images. + * Note that the max_memory_to_use option is ignored by this implementation. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jmemsys.h" /* import the system-dependent declarations */ + +#ifndef HAVE_STDLIB_H /* should declare malloc(),free() */ +extern void * malloc JPP((size_t size)); +extern void free JPP((void *ptr)); +#endif + + +/* + * Memory allocation and freeing are controlled by the regular library + * routines malloc() and free(). + */ + +GLOBAL(void *) +jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject) +{ + return (void *) malloc(sizeofobject); +} + +GLOBAL(void) +jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject) +{ + free(object); +} + + +/* + * "Large" objects are treated the same as "small" ones. + * NB: although we include FAR keywords in the routine declarations, + * this file won't actually work in 80x86 small/medium model; at least, + * you probably won't be able to process useful-size images in only 64KB. + */ + +GLOBAL(void FAR *) +jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject) +{ + return (void FAR *) malloc(sizeofobject); +} + +GLOBAL(void) +jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject) +{ + free(object); +} + + +/* + * This routine computes the total memory space available for allocation. + * Here we always say, "we got all you want bud!" + */ + +GLOBAL(long) +jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed, + long max_bytes_needed, long already_allocated) +{ + return max_bytes_needed; +} + + +/* + * Backing store (temporary file) management. + * Since jpeg_mem_available always promised the moon, + * this should never be called and we can just error out. + */ + +GLOBAL(void) +jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info, + long total_bytes_needed) +{ + ERREXIT(cinfo, JERR_NO_BACKING_STORE); +} + + +/* + * These routines take care of any system-dependent initialization and + * cleanup required. Here, there isn't any. + */ + +GLOBAL(long) +jpeg_mem_init (j_common_ptr cinfo) +{ + return 0; /* just set max_memory_to_use to 0 */ +} + +GLOBAL(void) +jpeg_mem_term (j_common_ptr cinfo) +{ + /* no work */ +} diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jmemsys.h b/lc-continuity/mk4/modimage/jpeg-6b/jmemsys.h new file mode 100644 index 0000000000000000000000000000000000000000..6c3c6d348f2cf68149087f1906196a470136237e --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jmemsys.h @@ -0,0 +1,198 @@ +/* + * jmemsys.h + * + * Copyright (C) 1992-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This include file defines the interface between the system-independent + * and system-dependent portions of the JPEG memory manager. No other + * modules need include it. (The system-independent portion is jmemmgr.c; + * there are several different versions of the system-dependent portion.) + * + * This file works as-is for the system-dependent memory managers supplied + * in the IJG distribution. You may need to modify it if you write a + * custom memory manager. If system-dependent changes are needed in + * this file, the best method is to #ifdef them based on a configuration + * symbol supplied in jconfig.h, as we have done with USE_MSDOS_MEMMGR + * and USE_MAC_MEMMGR. + */ + + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_get_small jGetSmall +#define jpeg_free_small jFreeSmall +#define jpeg_get_large jGetLarge +#define jpeg_free_large jFreeLarge +#define jpeg_mem_available jMemAvail +#define jpeg_open_backing_store jOpenBackStore +#define jpeg_mem_init jMemInit +#define jpeg_mem_term jMemTerm +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* + * These two functions are used to allocate and release small chunks of + * memory. (Typically the total amount requested through jpeg_get_small is + * no more than 20K or so; this will be requested in chunks of a few K each.) + * Behavior should be the same as for the standard library functions malloc + * and free; in particular, jpeg_get_small must return NULL on failure. + * On most systems, these ARE malloc and free. jpeg_free_small is passed the + * size of the object being freed, just in case it's needed. + * On an 80x86 machine using small-data memory model, these manage near heap. + */ + +EXTERN(void *) jpeg_get_small JPP((j_common_ptr cinfo, size_t sizeofobject)); +EXTERN(void) jpeg_free_small JPP((j_common_ptr cinfo, void * object, + size_t sizeofobject)); + +/* + * These two functions are used to allocate and release large chunks of + * memory (up to the total free space designated by jpeg_mem_available). + * The interface is the same as above, except that on an 80x86 machine, + * far pointers are used. On most other machines these are identical to + * the jpeg_get/free_small routines; but we keep them separate anyway, + * in case a different allocation strategy is desirable for large chunks. + */ + +EXTERN(void FAR *) jpeg_get_large JPP((j_common_ptr cinfo, + size_t sizeofobject)); +EXTERN(void) jpeg_free_large JPP((j_common_ptr cinfo, void FAR * object, + size_t sizeofobject)); + +/* + * The macro MAX_ALLOC_CHUNK designates the maximum number of bytes that may + * be requested in a single call to jpeg_get_large (and jpeg_get_small for that + * matter, but that case should never come into play). This macro is needed + * to model the 64Kb-segment-size limit of far addressing on 80x86 machines. + * On those machines, we expect that jconfig.h will provide a proper value. + * On machines with 32-bit flat address spaces, any large constant may be used. + * + * NB: jmemmgr.c expects that MAX_ALLOC_CHUNK will be representable as type + * size_t and will be a multiple of sizeof(align_type). + */ + +#ifndef MAX_ALLOC_CHUNK /* may be overridden in jconfig.h */ +#define MAX_ALLOC_CHUNK 1000000000L +#endif + +/* + * This routine computes the total space still available for allocation by + * jpeg_get_large. If more space than this is needed, backing store will be + * used. NOTE: any memory already allocated must not be counted. + * + * There is a minimum space requirement, corresponding to the minimum + * feasible buffer sizes; jmemmgr.c will request that much space even if + * jpeg_mem_available returns zero. The maximum space needed, enough to hold + * all working storage in memory, is also passed in case it is useful. + * Finally, the total space already allocated is passed. If no better + * method is available, cinfo->mem->max_memory_to_use - already_allocated + * is often a suitable calculation. + * + * It is OK for jpeg_mem_available to underestimate the space available + * (that'll just lead to more backing-store access than is really necessary). + * However, an overestimate will lead to failure. Hence it's wise to subtract + * a slop factor from the true available space. 5% should be enough. + * + * On machines with lots of virtual memory, any large constant may be returned. + * Conversely, zero may be returned to always use the minimum amount of memory. + */ + +EXTERN(long) jpeg_mem_available JPP((j_common_ptr cinfo, + long min_bytes_needed, + long max_bytes_needed, + long already_allocated)); + + +/* + * This structure holds whatever state is needed to access a single + * backing-store object. The read/write/close method pointers are called + * by jmemmgr.c to manipulate the backing-store object; all other fields + * are private to the system-dependent backing store routines. + */ + +#define TEMP_NAME_LENGTH 64 /* max length of a temporary file's name */ + + +#ifdef USE_MSDOS_MEMMGR /* DOS-specific junk */ + +typedef unsigned short XMSH; /* type of extended-memory handles */ +typedef unsigned short EMSH; /* type of expanded-memory handles */ + +typedef union { + short file_handle; /* DOS file handle if it's a temp file */ + XMSH xms_handle; /* handle if it's a chunk of XMS */ + EMSH ems_handle; /* handle if it's a chunk of EMS */ +} handle_union; + +#endif /* USE_MSDOS_MEMMGR */ + +#ifdef USE_MAC_MEMMGR /* Mac-specific junk */ +#include +#endif /* USE_MAC_MEMMGR */ + + +typedef struct backing_store_struct * backing_store_ptr; + +typedef struct backing_store_struct { + /* Methods for reading/writing/closing this backing-store object */ + JMETHOD(void, read_backing_store, (j_common_ptr cinfo, + backing_store_ptr info, + void FAR * buffer_address, + long file_offset, long byte_count)); + JMETHOD(void, write_backing_store, (j_common_ptr cinfo, + backing_store_ptr info, + void FAR * buffer_address, + long file_offset, long byte_count)); + JMETHOD(void, close_backing_store, (j_common_ptr cinfo, + backing_store_ptr info)); + + /* Private fields for system-dependent backing-store management */ +#ifdef USE_MSDOS_MEMMGR + /* For the MS-DOS manager (jmemdos.c), we need: */ + handle_union handle; /* reference to backing-store storage object */ + char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */ +#else +#ifdef USE_MAC_MEMMGR + /* For the Mac manager (jmemmac.c), we need: */ + short temp_file; /* file reference number to temp file */ + FSSpec tempSpec; /* the FSSpec for the temp file */ + char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */ +#else + /* For a typical implementation with temp files, we need: */ + FILE * temp_file; /* stdio reference to temp file */ + char temp_name[TEMP_NAME_LENGTH]; /* name of temp file */ +#endif +#endif +} backing_store_info; + + +/* + * Initial opening of a backing-store object. This must fill in the + * read/write/close pointers in the object. The read/write routines + * may take an error exit if the specified maximum file size is exceeded. + * (If jpeg_mem_available always returns a large value, this routine can + * just take an error exit.) + */ + +EXTERN(void) jpeg_open_backing_store JPP((j_common_ptr cinfo, + backing_store_ptr info, + long total_bytes_needed)); + + +/* + * These routines take care of any system-dependent initialization and + * cleanup required. jpeg_mem_init will be called before anything is + * allocated (and, therefore, nothing in cinfo is of use except the error + * manager pointer). It should return a suitable default value for + * max_memory_to_use; this may subsequently be overridden by the surrounding + * application. (Note that max_memory_to_use is only important if + * jpeg_mem_available chooses to consult it ... no one else will.) + * jpeg_mem_term may assume that all requested memory has been freed and that + * all opened backing-store objects have been closed. + */ + +EXTERN(long) jpeg_mem_init JPP((j_common_ptr cinfo)); +EXTERN(void) jpeg_mem_term JPP((j_common_ptr cinfo)); diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jmorecfg.h b/lc-continuity/mk4/modimage/jpeg-6b/jmorecfg.h new file mode 100644 index 0000000000000000000000000000000000000000..54a7d1c447e4ed862caf5a905b0275efcf3629ef --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jmorecfg.h @@ -0,0 +1,363 @@ +/* + * jmorecfg.h + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains additional configuration options that customize the + * JPEG software for special applications or support machine-dependent + * optimizations. Most users will not need to touch this file. + */ + + +/* + * Define BITS_IN_JSAMPLE as either + * 8 for 8-bit sample values (the usual setting) + * 12 for 12-bit sample values + * Only 8 and 12 are legal data precisions for lossy JPEG according to the + * JPEG standard, and the IJG code does not support anything else! + * We do not support run-time selection of data precision, sorry. + */ + +#define BITS_IN_JSAMPLE 8 /* use 8 or 12 */ + + +/* + * Maximum number of components (color channels) allowed in JPEG image. + * To meet the letter of the JPEG spec, set this to 255. However, darn + * few applications need more than 4 channels (maybe 5 for CMYK + alpha + * mask). We recommend 10 as a reasonable compromise; use 4 if you are + * really short on memory. (Each allowed component costs a hundred or so + * bytes of storage, whether actually used in an image or not.) + */ + +#define MAX_COMPONENTS 10 /* maximum number of image components */ + + +/* + * Basic data types. + * You may need to change these if you have a machine with unusual data + * type sizes; for example, "char" not 8 bits, "short" not 16 bits, + * or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits, + * but it had better be at least 16. + */ + +/* Representation of a single sample (pixel element value). + * We frequently allocate large arrays of these, so it's important to keep + * them small. But if you have memory to burn and access to char or short + * arrays is very slow on your hardware, you might want to change these. + */ + +#if BITS_IN_JSAMPLE == 8 +/* JSAMPLE should be the smallest type that will hold the values 0..255. + * You can use a signed char by having GETJSAMPLE mask it with 0xFF. + */ + +#ifdef HAVE_UNSIGNED_CHAR + +typedef unsigned char JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#else /* not HAVE_UNSIGNED_CHAR */ + +typedef char JSAMPLE; +#ifdef CHAR_IS_UNSIGNED +#define GETJSAMPLE(value) ((int) (value)) +#else +#define GETJSAMPLE(value) ((int) (value) & 0xFF) +#endif /* CHAR_IS_UNSIGNED */ + +#endif /* HAVE_UNSIGNED_CHAR */ + +#define MAXJSAMPLE 255 +#define CENTERJSAMPLE 128 + +#endif /* BITS_IN_JSAMPLE == 8 */ + + +#if BITS_IN_JSAMPLE == 12 +/* JSAMPLE should be the smallest type that will hold the values 0..4095. + * On nearly all machines "short" will do nicely. + */ + +typedef short JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#define MAXJSAMPLE 4095 +#define CENTERJSAMPLE 2048 + +#endif /* BITS_IN_JSAMPLE == 12 */ + + +/* Representation of a DCT frequency coefficient. + * This should be a signed value of at least 16 bits; "short" is usually OK. + * Again, we allocate large arrays of these, but you can change to int + * if you have memory to burn and "short" is really slow. + */ + +typedef short JCOEF; + + +/* Compressed datastreams are represented as arrays of JOCTET. + * These must be EXACTLY 8 bits wide, at least once they are written to + * external storage. Note that when using the stdio data source/destination + * managers, this is also the data type passed to fread/fwrite. + */ + +#ifdef HAVE_UNSIGNED_CHAR + +typedef unsigned char JOCTET; +#define GETJOCTET(value) (value) + +#else /* not HAVE_UNSIGNED_CHAR */ + +typedef char JOCTET; +#ifdef CHAR_IS_UNSIGNED +#define GETJOCTET(value) (value) +#else +#define GETJOCTET(value) ((value) & 0xFF) +#endif /* CHAR_IS_UNSIGNED */ + +#endif /* HAVE_UNSIGNED_CHAR */ + + +/* These typedefs are used for various table entries and so forth. + * They must be at least as wide as specified; but making them too big + * won't cost a huge amount of memory, so we don't provide special + * extraction code like we did for JSAMPLE. (In other words, these + * typedefs live at a different point on the speed/space tradeoff curve.) + */ + +/* UINT8 must hold at least the values 0..255. */ + +#ifdef HAVE_UNSIGNED_CHAR +typedef unsigned char UINT8; +#else /* not HAVE_UNSIGNED_CHAR */ +#ifdef CHAR_IS_UNSIGNED +typedef char UINT8; +#else /* not CHAR_IS_UNSIGNED */ +typedef short UINT8; +#endif /* CHAR_IS_UNSIGNED */ +#endif /* HAVE_UNSIGNED_CHAR */ + +/* UINT16 must hold at least the values 0..65535. */ + +#ifdef HAVE_UNSIGNED_SHORT +typedef unsigned short UINT16; +#else /* not HAVE_UNSIGNED_SHORT */ +typedef unsigned int UINT16; +#endif /* HAVE_UNSIGNED_SHORT */ + +/* INT16 must hold at least the values -32768..32767. */ + +#ifndef XMD_H /* X11/xmd.h correctly defines INT16 */ +typedef short INT16; +#endif + +/* INT32 must hold at least signed 32-bit values. */ + +#ifndef XMD_H /* X11/xmd.h correctly defines INT32 */ +typedef long INT32; +#endif + +/* Datatype used for image dimensions. The JPEG standard only supports + * images up to 64K*64K due to 16-bit fields in SOF markers. Therefore + * "unsigned int" is sufficient on all machines. However, if you need to + * handle larger images and you don't mind deviating from the spec, you + * can change this datatype. + */ + +typedef unsigned int JDIMENSION; + +#define JPEG_MAX_DIMENSION 65500L /* a tad under 64K to prevent overflows */ + + +/* These macros are used in all function definitions and extern declarations. + * You could modify them if you need to change function linkage conventions; + * in particular, you'll need to do that to make the library a Windows DLL. + * Another application is to make all functions global for use with debuggers + * or code profilers that require it. + */ + +/* a function called through method pointers: */ +#define METHODDEF(type) static type +/* a function used only in its module: */ +#define LOCAL(type) static type +/* a function referenced thru EXTERNs: */ +#define GLOBAL(type) type +/* a reference to a GLOBAL function: */ +#define EXTERN(type) extern type + + +/* This macro is used to declare a "method", that is, a function pointer. + * We want to supply prototype parameters if the compiler can cope. + * Note that the arglist parameter must be parenthesized! + * Again, you can customize this if you need special linkage keywords. + */ + +#ifdef HAVE_PROTOTYPES +#define JMETHOD(type,methodname,arglist) type (*methodname) arglist +#else +#define JMETHOD(type,methodname,arglist) type (*methodname) () +#endif + + +/* Here is the pseudo-keyword for declaring pointers that must be "far" + * on 80x86 machines. Most of the specialized coding for 80x86 is handled + * by just saying "FAR *" where such a pointer is needed. In a few places + * explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol. + */ + +#ifdef NEED_FAR_POINTERS +#define FAR far +#else +#define FAR +#endif + + +/* + * On a few systems, type boolean and/or its values FALSE, TRUE may appear + * in standard header files. Or you may have conflicts with application- + * specific header files that you want to include together with these files. + * Defining HAVE_BOOLEAN before including jpeglib.h should make it work. + */ + +#ifndef HAVE_BOOLEAN +typedef int boolean; +#endif +#ifndef FALSE /* in case these macros already exist */ +#define FALSE 0 /* values of boolean */ +#endif +#ifndef TRUE +#define TRUE 1 +#endif + + +/* + * The remaining options affect code selection within the JPEG library, + * but they don't need to be visible to most applications using the library. + * To minimize application namespace pollution, the symbols won't be + * defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined. + */ + +#ifdef JPEG_INTERNALS +#define JPEG_INTERNAL_OPTIONS +#endif + +#ifdef JPEG_INTERNAL_OPTIONS + + +/* + * These defines indicate whether to include various optional functions. + * Undefining some of these symbols will produce a smaller but less capable + * library. Note that you can leave certain source files out of the + * compilation/linking process if you've #undef'd the corresponding symbols. + * (You may HAVE to do that if your compiler doesn't like null source files.) + */ + +/* Arithmetic coding is unsupported for legal reasons. Complaints to IBM. */ + +/* Capability options common to encoder and decoder: */ + +#define DCT_ISLOW_SUPPORTED /* slow but accurate integer algorithm */ +#define DCT_IFAST_SUPPORTED /* faster, less accurate integer method */ +#define DCT_FLOAT_SUPPORTED /* floating-point: accurate, fast on fast HW */ + +/* Encoder capability options: */ + +#undef C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ +#define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ +#define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ +#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */ +/* Note: if you selected 12-bit data precision, it is dangerous to turn off + * ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit + * precision, so jchuff.c normally uses entropy optimization to compute + * usable tables for higher precision. If you don't want to do optimization, + * you'll have to supply different default Huffman tables. + * The exact same statements apply for progressive JPEG: the default tables + * don't work for progressive mode. (This may get fixed, however.) + */ +#define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */ + +/* Decoder capability options: */ + +#undef D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ +#define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ +#define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ +#define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */ +#define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */ +#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? */ +#undef UPSAMPLE_SCALING_SUPPORTED /* Output rescaling at upsample stage? */ +#define UPSAMPLE_MERGING_SUPPORTED /* Fast path for sloppy upsampling? */ +#define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */ +#define QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */ + +/* more capability options later, no doubt */ + + +/* + * Ordering of RGB data in scanlines passed to or from the application. + * If your application wants to deal with data in the order B,G,R, just + * change these macros. You can also deal with formats such as R,G,B,X + * (one extra byte per pixel) by changing RGB_PIXELSIZE. Note that changing + * the offsets will also change the order in which colormap data is organized. + * RESTRICTIONS: + * 1. The sample applications cjpeg,djpeg do NOT support modified RGB formats. + * 2. These macros only affect RGB<=>YCbCr color conversion, so they are not + * useful if you are using JPEG color spaces other than YCbCr or grayscale. + * 3. The color quantizer modules will not behave desirably if RGB_PIXELSIZE + * is not 3 (they don't understand about dummy color components!). So you + * can't use color quantization if you change that value. + */ + +#define RGB_RED 0 /* Offset of Red in an RGB scanline element */ +#define RGB_GREEN 1 /* Offset of Green */ +#define RGB_BLUE 2 /* Offset of Blue */ +#define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */ + + +/* Definitions for speed-related optimizations. */ + + +/* If your compiler supports inline functions, define INLINE + * as the inline keyword; otherwise define it as empty. + */ + +#ifndef INLINE +#ifdef __GNUC__ /* for instance, GNU C knows about inline */ +#define INLINE __inline__ +#endif +#ifndef INLINE +#define INLINE /* default is to define it as empty */ +#endif +#endif + + +/* On some machines (notably 68000 series) "int" is 32 bits, but multiplying + * two 16-bit shorts is faster than multiplying two ints. Define MULTIPLIER + * as short on such a machine. MULTIPLIER must be at least 16 bits wide. + */ + +#ifndef MULTIPLIER +#define MULTIPLIER int /* type for fastest integer multiply */ +#endif + + +/* FAST_FLOAT should be either float or double, whichever is done faster + * by your compiler. (Note that this type is only used in the floating point + * DCT routines, so it only matters if you've defined DCT_FLOAT_SUPPORTED.) + * Typically, float is faster in ANSI C compilers, while double is faster in + * pre-ANSI compilers (because they insist on converting to double anyway). + * The code below therefore chooses float if we have ANSI-style prototypes. + */ + +#ifndef FAST_FLOAT +#ifdef HAVE_PROTOTYPES +#define FAST_FLOAT float +#else +#define FAST_FLOAT double +#endif +#endif + +#endif /* JPEG_INTERNAL_OPTIONS */ diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jpegint.h b/lc-continuity/mk4/modimage/jpeg-6b/jpegint.h new file mode 100644 index 0000000000000000000000000000000000000000..95b00d405caeca1dc971b37a94bbadc566f3074b --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jpegint.h @@ -0,0 +1,392 @@ +/* + * jpegint.h + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file provides common declarations for the various JPEG modules. + * These declarations are considered internal to the JPEG library; most + * applications using the library shouldn't need to include this file. + */ + + +/* Declarations for both compression & decompression */ + +typedef enum { /* Operating modes for buffer controllers */ + JBUF_PASS_THRU, /* Plain stripwise operation */ + /* Remaining modes require a full-image buffer to have been created */ + JBUF_SAVE_SOURCE, /* Run source subobject only, save output */ + JBUF_CRANK_DEST, /* Run dest subobject only, using saved data */ + JBUF_SAVE_AND_PASS /* Run both subobjects, save output */ +} J_BUF_MODE; + +/* Values of global_state field (jdapi.c has some dependencies on ordering!) */ +#define CSTATE_START 100 /* after create_compress */ +#define CSTATE_SCANNING 101 /* start_compress done, write_scanlines OK */ +#define CSTATE_RAW_OK 102 /* start_compress done, write_raw_data OK */ +#define CSTATE_WRCOEFS 103 /* jpeg_write_coefficients done */ +#define DSTATE_START 200 /* after create_decompress */ +#define DSTATE_INHEADER 201 /* reading header markers, no SOS yet */ +#define DSTATE_READY 202 /* found SOS, ready for start_decompress */ +#define DSTATE_PRELOAD 203 /* reading multiscan file in start_decompress*/ +#define DSTATE_PRESCAN 204 /* performing dummy pass for 2-pass quant */ +#define DSTATE_SCANNING 205 /* start_decompress done, read_scanlines OK */ +#define DSTATE_RAW_OK 206 /* start_decompress done, read_raw_data OK */ +#define DSTATE_BUFIMAGE 207 /* expecting jpeg_start_output */ +#define DSTATE_BUFPOST 208 /* looking for SOS/EOI in jpeg_finish_output */ +#define DSTATE_RDCOEFS 209 /* reading file in jpeg_read_coefficients */ +#define DSTATE_STOPPING 210 /* looking for EOI in jpeg_finish_decompress */ + + +/* Declarations for compression modules */ + +/* Master control module */ +struct jpeg_comp_master { + JMETHOD(void, prepare_for_pass, (j_compress_ptr cinfo)); + JMETHOD(void, pass_startup, (j_compress_ptr cinfo)); + JMETHOD(void, finish_pass, (j_compress_ptr cinfo)); + + /* State variables made visible to other modules */ + boolean call_pass_startup; /* True if pass_startup must be called */ + boolean is_last_pass; /* True during last pass */ +}; + +/* Main buffer control (downsampled-data buffer) */ +struct jpeg_c_main_controller { + JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(void, process_data, (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail)); +}; + +/* Compression preprocessing (downsampling input buffer control) */ +struct jpeg_c_prep_controller { + JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(void, pre_process_data, (j_compress_ptr cinfo, + JSAMPARRAY input_buf, + JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail, + JSAMPIMAGE output_buf, + JDIMENSION *out_row_group_ctr, + JDIMENSION out_row_groups_avail)); +}; + +/* Coefficient buffer control */ +struct jpeg_c_coef_controller { + JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(boolean, compress_data, (j_compress_ptr cinfo, + JSAMPIMAGE input_buf)); +}; + +/* Colorspace conversion */ +struct jpeg_color_converter { + JMETHOD(void, start_pass, (j_compress_ptr cinfo)); + JMETHOD(void, color_convert, (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows)); +}; + +/* Downsampling */ +struct jpeg_downsampler { + JMETHOD(void, start_pass, (j_compress_ptr cinfo)); + JMETHOD(void, downsample, (j_compress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION in_row_index, + JSAMPIMAGE output_buf, + JDIMENSION out_row_group_index)); + + boolean need_context_rows; /* TRUE if need rows above & below */ +}; + +/* Forward DCT (also controls coefficient quantization) */ +struct jpeg_forward_dct { + JMETHOD(void, start_pass, (j_compress_ptr cinfo)); + /* perhaps this should be an array??? */ + JMETHOD(void, forward_DCT, (j_compress_ptr cinfo, + jpeg_component_info * compptr, + JSAMPARRAY sample_data, JBLOCKROW coef_blocks, + JDIMENSION start_row, JDIMENSION start_col, + JDIMENSION num_blocks)); +}; + +/* Entropy encoding */ +struct jpeg_entropy_encoder { + JMETHOD(void, start_pass, (j_compress_ptr cinfo, boolean gather_statistics)); + JMETHOD(boolean, encode_mcu, (j_compress_ptr cinfo, JBLOCKROW *MCU_data)); + JMETHOD(void, finish_pass, (j_compress_ptr cinfo)); +}; + +/* Marker writing */ +struct jpeg_marker_writer { + JMETHOD(void, write_file_header, (j_compress_ptr cinfo)); + JMETHOD(void, write_frame_header, (j_compress_ptr cinfo)); + JMETHOD(void, write_scan_header, (j_compress_ptr cinfo)); + JMETHOD(void, write_file_trailer, (j_compress_ptr cinfo)); + JMETHOD(void, write_tables_only, (j_compress_ptr cinfo)); + /* These routines are exported to allow insertion of extra markers */ + /* Probably only COM and APPn markers should be written this way */ + JMETHOD(void, write_marker_header, (j_compress_ptr cinfo, int marker, + unsigned int datalen)); + JMETHOD(void, write_marker_byte, (j_compress_ptr cinfo, int val)); +}; + + +/* Declarations for decompression modules */ + +/* Master control module */ +struct jpeg_decomp_master { + JMETHOD(void, prepare_for_output_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, finish_output_pass, (j_decompress_ptr cinfo)); + + /* State variables made visible to other modules */ + boolean is_dummy_pass; /* True during 1st pass for 2-pass quant */ +}; + +/* Input control module */ +struct jpeg_input_controller { + JMETHOD(int, consume_input, (j_decompress_ptr cinfo)); + JMETHOD(void, reset_input_controller, (j_decompress_ptr cinfo)); + JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, finish_input_pass, (j_decompress_ptr cinfo)); + + /* State variables made visible to other modules */ + boolean has_multiple_scans; /* True if file has multiple scans */ + boolean eoi_reached; /* True when EOI has been consumed */ +}; + +/* Main buffer control (downsampled-data buffer) */ +struct jpeg_d_main_controller { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(void, process_data, (j_decompress_ptr cinfo, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); +}; + +/* Coefficient buffer control */ +struct jpeg_d_coef_controller { + JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo)); + JMETHOD(int, consume_data, (j_decompress_ptr cinfo)); + JMETHOD(void, start_output_pass, (j_decompress_ptr cinfo)); + JMETHOD(int, decompress_data, (j_decompress_ptr cinfo, + JSAMPIMAGE output_buf)); + /* Pointer to array of coefficient virtual arrays, or NULL if none */ + jvirt_barray_ptr *coef_arrays; +}; + +/* Decompression postprocessing (color quantization buffer control) */ +struct jpeg_d_post_controller { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(void, post_process_data, (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, + JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); +}; + +/* Marker reading & parsing */ +struct jpeg_marker_reader { + JMETHOD(void, reset_marker_reader, (j_decompress_ptr cinfo)); + /* Read markers until SOS or EOI. + * Returns same codes as are defined for jpeg_consume_input: + * JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. + */ + JMETHOD(int, read_markers, (j_decompress_ptr cinfo)); + /* Read a restart marker --- exported for use by entropy decoder only */ + jpeg_marker_parser_method read_restart_marker; + + /* State of marker reader --- nominally internal, but applications + * supplying COM or APPn handlers might like to know the state. + */ + boolean saw_SOI; /* found SOI? */ + boolean saw_SOF; /* found SOF? */ + int next_restart_num; /* next restart number expected (0-7) */ + unsigned int discarded_bytes; /* # of bytes skipped looking for a marker */ +}; + +/* Entropy decoding */ +struct jpeg_entropy_decoder { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); + JMETHOD(boolean, decode_mcu, (j_decompress_ptr cinfo, + JBLOCKROW *MCU_data)); + + /* This is here to share code between baseline and progressive decoders; */ + /* other modules probably should not use it */ + boolean insufficient_data; /* set TRUE after emitting warning */ +}; + +/* Inverse DCT (also performs dequantization) */ +typedef JMETHOD(void, inverse_DCT_method_ptr, + (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col)); + +struct jpeg_inverse_dct { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); + /* It is useful to allow each component to have a separate IDCT method. */ + inverse_DCT_method_ptr inverse_DCT[MAX_COMPONENTS]; +}; + +/* Upsampling (note that upsampler must also call color converter) */ +struct jpeg_upsampler { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, upsample, (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, + JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); + + boolean need_context_rows; /* TRUE if need rows above & below */ +}; + +/* Colorspace conversion */ +struct jpeg_color_deconverter { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, color_convert, (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows)); +}; + +/* Color quantization or color precision reduction */ +struct jpeg_color_quantizer { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo, boolean is_pre_scan)); + JMETHOD(void, color_quantize, (j_decompress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPARRAY output_buf, + int num_rows)); + JMETHOD(void, finish_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, new_color_map, (j_decompress_ptr cinfo)); +}; + + +/* Miscellaneous useful macros */ + +#undef MAX +#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#undef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) + + +/* We assume that right shift corresponds to signed division by 2 with + * rounding towards minus infinity. This is correct for typical "arithmetic + * shift" instructions that shift in copies of the sign bit. But some + * C compilers implement >> with an unsigned shift. For these machines you + * must define RIGHT_SHIFT_IS_UNSIGNED. + * RIGHT_SHIFT provides a proper signed right shift of an INT32 quantity. + * It is only applied with constant shift counts. SHIFT_TEMPS must be + * included in the variables of any routine using RIGHT_SHIFT. + */ + +#ifdef RIGHT_SHIFT_IS_UNSIGNED +#define SHIFT_TEMPS INT32 shift_temp; +#define RIGHT_SHIFT(x,shft) \ + ((shift_temp = (x)) < 0 ? \ + (shift_temp >> (shft)) | ((~((INT32) 0)) << (32-(shft))) : \ + (shift_temp >> (shft))) +#else +#define SHIFT_TEMPS +#define RIGHT_SHIFT(x,shft) ((x) >> (shft)) +#endif + + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jinit_compress_master jICompress +#define jinit_c_master_control jICMaster +#define jinit_c_main_controller jICMainC +#define jinit_c_prep_controller jICPrepC +#define jinit_c_coef_controller jICCoefC +#define jinit_color_converter jICColor +#define jinit_downsampler jIDownsampler +#define jinit_forward_dct jIFDCT +#define jinit_huff_encoder jIHEncoder +#define jinit_phuff_encoder jIPHEncoder +#define jinit_marker_writer jIMWriter +#define jinit_master_decompress jIDMaster +#define jinit_d_main_controller jIDMainC +#define jinit_d_coef_controller jIDCoefC +#define jinit_d_post_controller jIDPostC +#define jinit_input_controller jIInCtlr +#define jinit_marker_reader jIMReader +#define jinit_huff_decoder jIHDecoder +#define jinit_phuff_decoder jIPHDecoder +#define jinit_inverse_dct jIIDCT +#define jinit_upsampler jIUpsampler +#define jinit_color_deconverter jIDColor +#define jinit_1pass_quantizer jI1Quant +#define jinit_2pass_quantizer jI2Quant +#define jinit_merged_upsampler jIMUpsampler +#define jinit_memory_mgr jIMemMgr +#define jdiv_round_up jDivRound +#define jround_up jRound +#define jcopy_sample_rows jCopySamples +#define jcopy_block_row jCopyBlocks +#define jzero_far jZeroFar +#define jpeg_zigzag_order jZIGTable +#define jpeg_natural_order jZAGTable +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* Compression module initialization routines */ +EXTERN(void) jinit_compress_master JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_c_master_control JPP((j_compress_ptr cinfo, + boolean transcode_only)); +EXTERN(void) jinit_c_main_controller JPP((j_compress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_c_prep_controller JPP((j_compress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_c_coef_controller JPP((j_compress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_color_converter JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_downsampler JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_forward_dct JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_huff_encoder JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_phuff_encoder JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_marker_writer JPP((j_compress_ptr cinfo)); +/* Decompression module initialization routines */ +EXTERN(void) jinit_master_decompress JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_d_main_controller JPP((j_decompress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_d_coef_controller JPP((j_decompress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_d_post_controller JPP((j_decompress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_input_controller JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_marker_reader JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_huff_decoder JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_phuff_decoder JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_inverse_dct JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_upsampler JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_color_deconverter JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_1pass_quantizer JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_2pass_quantizer JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_merged_upsampler JPP((j_decompress_ptr cinfo)); +/* Memory manager initialization */ +EXTERN(void) jinit_memory_mgr JPP((j_common_ptr cinfo)); + +/* Utility routines in jutils.c */ +EXTERN(long) jdiv_round_up JPP((long a, long b)); +EXTERN(long) jround_up JPP((long a, long b)); +EXTERN(void) jcopy_sample_rows JPP((JSAMPARRAY input_array, int source_row, + JSAMPARRAY output_array, int dest_row, + int num_rows, JDIMENSION num_cols)); +EXTERN(void) jcopy_block_row JPP((JBLOCKROW input_row, JBLOCKROW output_row, + JDIMENSION num_blocks)); +EXTERN(void) jzero_far JPP((void FAR * target, size_t bytestozero)); +/* Constant tables in jutils.c */ +#if 0 /* This table is not actually needed in v6a */ +extern const int jpeg_zigzag_order[]; /* natural coef order to zigzag order */ +#endif +extern const int jpeg_natural_order[]; /* zigzag coef order to natural order */ + +/* Suppress undefined-structure complaints if necessary. */ + +#ifdef INCOMPLETE_TYPES_BROKEN +#ifndef AM_MEMORY_MANAGER /* only jmemmgr.c defines these */ +struct jvirt_sarray_control { long dummy; }; +struct jvirt_barray_control { long dummy; }; +#endif +#endif /* INCOMPLETE_TYPES_BROKEN */ diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jpeglib.h b/lc-continuity/mk4/modimage/jpeg-6b/jpeglib.h new file mode 100644 index 0000000000000000000000000000000000000000..d1be8ddeff1bfee59f56d3ea04379f4b6f4d1c0e --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jpeglib.h @@ -0,0 +1,1096 @@ +/* + * jpeglib.h + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file defines the application interface for the JPEG library. + * Most applications using the library need only include this file, + * and perhaps jerror.h if they want to know the exact error codes. + */ + +#ifndef JPEGLIB_H +#define JPEGLIB_H + +/* + * First we include the configuration files that record how this + * installation of the JPEG library is set up. jconfig.h can be + * generated automatically for many systems. jmorecfg.h contains + * manual configuration options that most people need not worry about. + */ + +#ifndef JCONFIG_INCLUDED /* in case jinclude.h already did */ +#include "jconfig.h" /* widely used configuration options */ +#endif +#include "jmorecfg.h" /* seldom changed options */ + + +/* Version ID for the JPEG library. + * Might be useful for tests like "#if JPEG_LIB_VERSION >= 60". + */ + +#define JPEG_LIB_VERSION 62 /* Version 6b */ + + +/* Various constants determining the sizes of things. + * All of these are specified by the JPEG standard, so don't change them + * if you want to be compatible. + */ + +#define DCTSIZE 8 /* The basic DCT block is 8x8 samples */ +#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */ +#define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */ +#define NUM_HUFF_TBLS 4 /* Huffman tables are numbered 0..3 */ +#define NUM_ARITH_TBLS 16 /* Arith-coding tables are numbered 0..15 */ +#define MAX_COMPS_IN_SCAN 4 /* JPEG limit on # of components in one scan */ +#define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */ +/* Unfortunately, some bozo at Adobe saw no reason to be bound by the standard; + * the PostScript DCT filter can emit files with many more than 10 blocks/MCU. + * If you happen to run across such a file, you can up D_MAX_BLOCKS_IN_MCU + * to handle it. We even let you do this from the jconfig.h file. However, + * we strongly discourage changing C_MAX_BLOCKS_IN_MCU; just because Adobe + * sometimes emits noncompliant files doesn't mean you should too. + */ +#define C_MAX_BLOCKS_IN_MCU 10 /* compressor's limit on blocks per MCU */ +#ifndef D_MAX_BLOCKS_IN_MCU +#define D_MAX_BLOCKS_IN_MCU 10 /* decompressor's limit on blocks per MCU */ +#endif + + +/* Data structures for images (arrays of samples and of DCT coefficients). + * On 80x86 machines, the image arrays are too big for near pointers, + * but the pointer arrays can fit in near memory. + */ + +typedef JSAMPLE FAR *JSAMPROW; /* ptr to one image row of pixel samples. */ +typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */ +typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D sample array: top index is color */ + +typedef JCOEF JBLOCK[DCTSIZE2]; /* one block of coefficients */ +typedef JBLOCK FAR *JBLOCKROW; /* pointer to one row of coefficient blocks */ +typedef JBLOCKROW *JBLOCKARRAY; /* a 2-D array of coefficient blocks */ +typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */ + +typedef JCOEF FAR *JCOEFPTR; /* useful in a couple of places */ + + +/* Types for JPEG compression parameters and working tables. */ + + +/* DCT coefficient quantization tables. */ + +typedef struct { + /* This array gives the coefficient quantizers in natural array order + * (not the zigzag order in which they are stored in a JPEG DQT marker). + * CAUTION: IJG versions prior to v6a kept this array in zigzag order. + */ + UINT16 quantval[DCTSIZE2]; /* quantization step for each coefficient */ + /* This field is used only during compression. It's initialized FALSE when + * the table is created, and set TRUE when it's been output to the file. + * You could suppress output of a table by setting this to TRUE. + * (See jpeg_suppress_tables for an example.) + */ + boolean sent_table; /* TRUE when table has been output */ +} JQUANT_TBL; + + +/* Huffman coding tables. */ + +typedef struct { + /* These two fields directly represent the contents of a JPEG DHT marker */ + UINT8 bits[17]; /* bits[k] = # of symbols with codes of */ + /* length k bits; bits[0] is unused */ + UINT8 huffval[256]; /* The symbols, in order of incr code length */ + /* This field is used only during compression. It's initialized FALSE when + * the table is created, and set TRUE when it's been output to the file. + * You could suppress output of a table by setting this to TRUE. + * (See jpeg_suppress_tables for an example.) + */ + boolean sent_table; /* TRUE when table has been output */ +} JHUFF_TBL; + + +/* Basic info about one component (color channel). */ + +typedef struct { + /* These values are fixed over the whole image. */ + /* For compression, they must be supplied by parameter setup; */ + /* for decompression, they are read from the SOF marker. */ + int component_id; /* identifier for this component (0..255) */ + int component_index; /* its index in SOF or cinfo->comp_info[] */ + int h_samp_factor; /* horizontal sampling factor (1..4) */ + int v_samp_factor; /* vertical sampling factor (1..4) */ + int quant_tbl_no; /* quantization table selector (0..3) */ + /* These values may vary between scans. */ + /* For compression, they must be supplied by parameter setup; */ + /* for decompression, they are read from the SOS marker. */ + /* The decompressor output side may not use these variables. */ + int dc_tbl_no; /* DC entropy table selector (0..3) */ + int ac_tbl_no; /* AC entropy table selector (0..3) */ + + /* Remaining fields should be treated as private by applications. */ + + /* These values are computed during compression or decompression startup: */ + /* Component's size in DCT blocks. + * Any dummy blocks added to complete an MCU are not counted; therefore + * these values do not depend on whether a scan is interleaved or not. + */ + JDIMENSION width_in_blocks; + JDIMENSION height_in_blocks; + /* Size of a DCT block in samples. Always DCTSIZE for compression. + * For decompression this is the size of the output from one DCT block, + * reflecting any scaling we choose to apply during the IDCT step. + * Values of 1,2,4,8 are likely to be supported. Note that different + * components may receive different IDCT scalings. + */ + int DCT_scaled_size; + /* The downsampled dimensions are the component's actual, unpadded number + * of samples at the main buffer (preprocessing/compression interface), thus + * downsampled_width = ceil(image_width * Hi/Hmax) + * and similarly for height. For decompression, IDCT scaling is included, so + * downsampled_width = ceil(image_width * Hi/Hmax * DCT_scaled_size/DCTSIZE) + */ + JDIMENSION downsampled_width; /* actual width in samples */ + JDIMENSION downsampled_height; /* actual height in samples */ + /* This flag is used only for decompression. In cases where some of the + * components will be ignored (eg grayscale output from YCbCr image), + * we can skip most computations for the unused components. + */ + boolean component_needed; /* do we need the value of this component? */ + + /* These values are computed before starting a scan of the component. */ + /* The decompressor output side may not use these variables. */ + int MCU_width; /* number of blocks per MCU, horizontally */ + int MCU_height; /* number of blocks per MCU, vertically */ + int MCU_blocks; /* MCU_width * MCU_height */ + int MCU_sample_width; /* MCU width in samples, MCU_width*DCT_scaled_size */ + int last_col_width; /* # of non-dummy blocks across in last MCU */ + int last_row_height; /* # of non-dummy blocks down in last MCU */ + + /* Saved quantization table for component; NULL if none yet saved. + * See jdinput.c comments about the need for this information. + * This field is currently used only for decompression. + */ + JQUANT_TBL * quant_table; + + /* Private per-component storage for DCT or IDCT subsystem. */ + void * dct_table; +} jpeg_component_info; + + +/* The script for encoding a multiple-scan file is an array of these: */ + +typedef struct { + int comps_in_scan; /* number of components encoded in this scan */ + int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */ + int Ss, Se; /* progressive JPEG spectral selection parms */ + int Ah, Al; /* progressive JPEG successive approx. parms */ +} jpeg_scan_info; + +/* The decompressor can save APPn and COM markers in a list of these: */ + +typedef struct jpeg_marker_struct FAR * jpeg_saved_marker_ptr; + +struct jpeg_marker_struct { + jpeg_saved_marker_ptr next; /* next in list, or NULL */ + UINT8 marker; /* marker code: JPEG_COM, or JPEG_APP0+n */ + unsigned int original_length; /* # bytes of data in the file */ + unsigned int data_length; /* # bytes of data saved at data[] */ + JOCTET FAR * data; /* the data contained in the marker */ + /* the marker length word is not counted in data_length or original_length */ +}; + +/* Known color spaces. */ + +typedef enum { + JCS_UNKNOWN, /* error/unspecified */ + JCS_GRAYSCALE, /* monochrome */ + JCS_RGB, /* red/green/blue */ + JCS_YCbCr, /* Y/Cb/Cr (also known as YUV) */ + JCS_CMYK, /* C/M/Y/K */ + JCS_YCCK /* Y/Cb/Cr/K */ +} J_COLOR_SPACE; + +/* DCT/IDCT algorithm options. */ + +typedef enum { + JDCT_ISLOW, /* slow but accurate integer algorithm */ + JDCT_IFAST, /* faster, less accurate integer method */ + JDCT_FLOAT /* floating-point: accurate, fast on fast HW */ +} J_DCT_METHOD; + +#ifndef JDCT_DEFAULT /* may be overridden in jconfig.h */ +#define JDCT_DEFAULT JDCT_ISLOW +#endif +#ifndef JDCT_FASTEST /* may be overridden in jconfig.h */ +#define JDCT_FASTEST JDCT_IFAST +#endif + +/* Dithering options for decompression. */ + +typedef enum { + JDITHER_NONE, /* no dithering */ + JDITHER_ORDERED, /* simple ordered dither */ + JDITHER_FS /* Floyd-Steinberg error diffusion dither */ +} J_DITHER_MODE; + + +/* Common fields between JPEG compression and decompression master structs. */ + +#define jpeg_common_fields \ + struct jpeg_error_mgr * err; /* Error handler module */\ + struct jpeg_memory_mgr * mem; /* Memory manager module */\ + struct jpeg_progress_mgr * progress; /* Progress monitor, or NULL if none */\ + void * client_data; /* Available for use by application */\ + boolean is_decompressor; /* So common code can tell which is which */\ + int global_state /* For checking call sequence validity */ + +/* Routines that are to be used by both halves of the library are declared + * to receive a pointer to this structure. There are no actual instances of + * jpeg_common_struct, only of jpeg_compress_struct and jpeg_decompress_struct. + */ +struct jpeg_common_struct { + jpeg_common_fields; /* Fields common to both master struct types */ + /* Additional fields follow in an actual jpeg_compress_struct or + * jpeg_decompress_struct. All three structs must agree on these + * initial fields! (This would be a lot cleaner in C++.) + */ +}; + +typedef struct jpeg_common_struct * j_common_ptr; +typedef struct jpeg_compress_struct * j_compress_ptr; +typedef struct jpeg_decompress_struct * j_decompress_ptr; + + +/* Master record for a compression instance */ + +struct jpeg_compress_struct { + jpeg_common_fields; /* Fields shared with jpeg_decompress_struct */ + + /* Destination for compressed data */ + struct jpeg_destination_mgr * dest; + + /* Description of source image --- these fields must be filled in by + * outer application before starting compression. in_color_space must + * be correct before you can even call jpeg_set_defaults(). + */ + + JDIMENSION image_width; /* input image width */ + JDIMENSION image_height; /* input image height */ + int input_components; /* # of color components in input image */ + J_COLOR_SPACE in_color_space; /* colorspace of input image */ + + double input_gamma; /* image gamma of input image */ + + /* Compression parameters --- these fields must be set before calling + * jpeg_start_compress(). We recommend calling jpeg_set_defaults() to + * initialize everything to reasonable defaults, then changing anything + * the application specifically wants to change. That way you won't get + * burnt when new parameters are added. Also note that there are several + * helper routines to simplify changing parameters. + */ + + int data_precision; /* bits of precision in image data */ + + int num_components; /* # of color components in JPEG image */ + J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ + + jpeg_component_info * comp_info; + /* comp_info[i] describes component that appears i'th in SOF */ + + JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; + /* ptrs to coefficient quantization tables, or NULL if not defined */ + + JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; + JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; + /* ptrs to Huffman coding tables, or NULL if not defined */ + + UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ + UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ + UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ + + int num_scans; /* # of entries in scan_info array */ + const jpeg_scan_info * scan_info; /* script for multi-scan file, or NULL */ + /* The default value of scan_info is NULL, which causes a single-scan + * sequential JPEG file to be emitted. To create a multi-scan file, + * set num_scans and scan_info to point to an array of scan definitions. + */ + + boolean raw_data_in; /* TRUE=caller supplies downsampled data */ + boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ + boolean optimize_coding; /* TRUE=optimize entropy encoding parms */ + boolean CCIR601_sampling; /* TRUE=first samples are cosited */ + int smoothing_factor; /* 1..100, or 0 for no input smoothing */ + J_DCT_METHOD dct_method; /* DCT algorithm selector */ + + /* The restart interval can be specified in absolute MCUs by setting + * restart_interval, or in MCU rows by setting restart_in_rows + * (in which case the correct restart_interval will be figured + * for each scan). + */ + unsigned int restart_interval; /* MCUs per restart, or 0 for no restart */ + int restart_in_rows; /* if > 0, MCU rows per restart interval */ + + /* Parameters controlling emission of special markers. */ + + boolean write_JFIF_header; /* should a JFIF marker be written? */ + UINT8 JFIF_major_version; /* What to write for the JFIF version number */ + UINT8 JFIF_minor_version; + /* These three values are not used by the JPEG code, merely copied */ + /* into the JFIF APP0 marker. density_unit can be 0 for unknown, */ + /* 1 for dots/inch, or 2 for dots/cm. Note that the pixel aspect */ + /* ratio is defined by X_density/Y_density even when density_unit=0. */ + UINT8 density_unit; /* JFIF code for pixel size units */ + UINT16 X_density; /* Horizontal pixel density */ + UINT16 Y_density; /* Vertical pixel density */ + boolean write_Adobe_marker; /* should an Adobe marker be written? */ + + /* State variable: index of next scanline to be written to + * jpeg_write_scanlines(). Application may use this to control its + * processing loop, e.g., "while (next_scanline < image_height)". + */ + + JDIMENSION next_scanline; /* 0 .. image_height-1 */ + + /* Remaining fields are known throughout compressor, but generally + * should not be touched by a surrounding application. + */ + + /* + * These fields are computed during compression startup + */ + boolean progressive_mode; /* TRUE if scan script uses progressive mode */ + int max_h_samp_factor; /* largest h_samp_factor */ + int max_v_samp_factor; /* largest v_samp_factor */ + + JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to coef ctlr */ + /* The coefficient controller receives data in units of MCU rows as defined + * for fully interleaved scans (whether the JPEG file is interleaved or not). + * There are v_samp_factor * DCTSIZE sample rows of each component in an + * "iMCU" (interleaved MCU) row. + */ + + /* + * These fields are valid during any one scan. + * They describe the components and MCUs actually appearing in the scan. + */ + int comps_in_scan; /* # of JPEG components in this scan */ + jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; + /* *cur_comp_info[i] describes component that appears i'th in SOS */ + + JDIMENSION MCUs_per_row; /* # of MCUs across the image */ + JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ + + int blocks_in_MCU; /* # of DCT blocks per MCU */ + int MCU_membership[C_MAX_BLOCKS_IN_MCU]; + /* MCU_membership[i] is index in cur_comp_info of component owning */ + /* i'th block in an MCU */ + + int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ + + /* + * Links to compression subobjects (methods and private variables of modules) + */ + struct jpeg_comp_master * master; + struct jpeg_c_main_controller * main; + struct jpeg_c_prep_controller * prep; + struct jpeg_c_coef_controller * coef; + struct jpeg_marker_writer * marker; + struct jpeg_color_converter * cconvert; + struct jpeg_downsampler * downsample; + struct jpeg_forward_dct * fdct; + struct jpeg_entropy_encoder * entropy; + jpeg_scan_info * script_space; /* workspace for jpeg_simple_progression */ + int script_space_size; +}; + + +/* Master record for a decompression instance */ + +struct jpeg_decompress_struct { + jpeg_common_fields; /* Fields shared with jpeg_compress_struct */ + + /* Source of compressed data */ + struct jpeg_source_mgr * src; + + /* Basic description of image --- filled in by jpeg_read_header(). */ + /* Application may inspect these values to decide how to process image. */ + + JDIMENSION image_width; /* nominal image width (from SOF marker) */ + JDIMENSION image_height; /* nominal image height */ + int num_components; /* # of color components in JPEG image */ + J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ + + /* Decompression processing parameters --- these fields must be set before + * calling jpeg_start_decompress(). Note that jpeg_read_header() initializes + * them to default values. + */ + + J_COLOR_SPACE out_color_space; /* colorspace for output */ + + unsigned int scale_num, scale_denom; /* fraction by which to scale image */ + + double output_gamma; /* image gamma wanted in output */ + + boolean buffered_image; /* TRUE=multiple output passes */ + boolean raw_data_out; /* TRUE=downsampled data wanted */ + + J_DCT_METHOD dct_method; /* IDCT algorithm selector */ + boolean do_fancy_upsampling; /* TRUE=apply fancy upsampling */ + boolean do_block_smoothing; /* TRUE=apply interblock smoothing */ + + boolean quantize_colors; /* TRUE=colormapped output wanted */ + /* the following are ignored if not quantize_colors: */ + J_DITHER_MODE dither_mode; /* type of color dithering to use */ + boolean two_pass_quantize; /* TRUE=use two-pass color quantization */ + int desired_number_of_colors; /* max # colors to use in created colormap */ + /* these are significant only in buffered-image mode: */ + boolean enable_1pass_quant; /* enable future use of 1-pass quantizer */ + boolean enable_external_quant;/* enable future use of external colormap */ + boolean enable_2pass_quant; /* enable future use of 2-pass quantizer */ + + /* Description of actual output image that will be returned to application. + * These fields are computed by jpeg_start_decompress(). + * You can also use jpeg_calc_output_dimensions() to determine these values + * in advance of calling jpeg_start_decompress(). + */ + + JDIMENSION output_width; /* scaled image width */ + JDIMENSION output_height; /* scaled image height */ + int out_color_components; /* # of color components in out_color_space */ + int output_components; /* # of color components returned */ + /* output_components is 1 (a colormap index) when quantizing colors; + * otherwise it equals out_color_components. + */ + int rec_outbuf_height; /* min recommended height of scanline buffer */ + /* If the buffer passed to jpeg_read_scanlines() is less than this many rows + * high, space and time will be wasted due to unnecessary data copying. + * Usually rec_outbuf_height will be 1 or 2, at most 4. + */ + + /* When quantizing colors, the output colormap is described by these fields. + * The application can supply a colormap by setting colormap non-NULL before + * calling jpeg_start_decompress; otherwise a colormap is created during + * jpeg_start_decompress or jpeg_start_output. + * The map has out_color_components rows and actual_number_of_colors columns. + */ + int actual_number_of_colors; /* number of entries in use */ + JSAMPARRAY colormap; /* The color map as a 2-D pixel array */ + + /* State variables: these variables indicate the progress of decompression. + * The application may examine these but must not modify them. + */ + + /* Row index of next scanline to be read from jpeg_read_scanlines(). + * Application may use this to control its processing loop, e.g., + * "while (output_scanline < output_height)". + */ + JDIMENSION output_scanline; /* 0 .. output_height-1 */ + + /* Current input scan number and number of iMCU rows completed in scan. + * These indicate the progress of the decompressor input side. + */ + int input_scan_number; /* Number of SOS markers seen so far */ + JDIMENSION input_iMCU_row; /* Number of iMCU rows completed */ + + /* The "output scan number" is the notional scan being displayed by the + * output side. The decompressor will not allow output scan/row number + * to get ahead of input scan/row, but it can fall arbitrarily far behind. + */ + int output_scan_number; /* Nominal scan number being displayed */ + JDIMENSION output_iMCU_row; /* Number of iMCU rows read */ + + /* Current progression status. coef_bits[c][i] indicates the precision + * with which component c's DCT coefficient i (in zigzag order) is known. + * It is -1 when no data has yet been received, otherwise it is the point + * transform (shift) value for the most recent scan of the coefficient + * (thus, 0 at completion of the progression). + * This pointer is NULL when reading a non-progressive file. + */ + int (*coef_bits)[DCTSIZE2]; /* -1 or current Al value for each coef */ + + /* Internal JPEG parameters --- the application usually need not look at + * these fields. Note that the decompressor output side may not use + * any parameters that can change between scans. + */ + + /* Quantization and Huffman tables are carried forward across input + * datastreams when processing abbreviated JPEG datastreams. + */ + + JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; + /* ptrs to coefficient quantization tables, or NULL if not defined */ + + JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; + JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; + /* ptrs to Huffman coding tables, or NULL if not defined */ + + /* These parameters are never carried across datastreams, since they + * are given in SOF/SOS markers or defined to be reset by SOI. + */ + + int data_precision; /* bits of precision in image data */ + + jpeg_component_info * comp_info; + /* comp_info[i] describes component that appears i'th in SOF */ + + boolean progressive_mode; /* TRUE if SOFn specifies progressive mode */ + boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ + + UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ + UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ + UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ + + unsigned int restart_interval; /* MCUs per restart interval, or 0 for no restart */ + + /* These fields record data obtained from optional markers recognized by + * the JPEG library. + */ + boolean saw_JFIF_marker; /* TRUE iff a JFIF APP0 marker was found */ + /* Data copied from JFIF marker; only valid if saw_JFIF_marker is TRUE: */ + UINT8 JFIF_major_version; /* JFIF version number */ + UINT8 JFIF_minor_version; + UINT8 density_unit; /* JFIF code for pixel size units */ + UINT16 X_density; /* Horizontal pixel density */ + UINT16 Y_density; /* Vertical pixel density */ + boolean saw_Adobe_marker; /* TRUE iff an Adobe APP14 marker was found */ + UINT8 Adobe_transform; /* Color transform code from Adobe marker */ + + boolean CCIR601_sampling; /* TRUE=first samples are cosited */ + + /* Aside from the specific data retained from APPn markers known to the + * library, the uninterpreted contents of any or all APPn and COM markers + * can be saved in a list for examination by the application. + */ + jpeg_saved_marker_ptr marker_list; /* Head of list of saved markers */ + + /* Remaining fields are known throughout decompressor, but generally + * should not be touched by a surrounding application. + */ + + /* + * These fields are computed during decompression startup + */ + int max_h_samp_factor; /* largest h_samp_factor */ + int max_v_samp_factor; /* largest v_samp_factor */ + + int min_DCT_scaled_size; /* smallest DCT_scaled_size of any component */ + + JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */ + /* The coefficient controller's input and output progress is measured in + * units of "iMCU" (interleaved MCU) rows. These are the same as MCU rows + * in fully interleaved JPEG scans, but are used whether the scan is + * interleaved or not. We define an iMCU row as v_samp_factor DCT block + * rows of each component. Therefore, the IDCT output contains + * v_samp_factor*DCT_scaled_size sample rows of a component per iMCU row. + */ + + JSAMPLE * sample_range_limit; /* table for fast range-limiting */ + + /* + * These fields are valid during any one scan. + * They describe the components and MCUs actually appearing in the scan. + * Note that the decompressor output side must not use these fields. + */ + int comps_in_scan; /* # of JPEG components in this scan */ + jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; + /* *cur_comp_info[i] describes component that appears i'th in SOS */ + + JDIMENSION MCUs_per_row; /* # of MCUs across the image */ + JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ + + int blocks_in_MCU; /* # of DCT blocks per MCU */ + int MCU_membership[D_MAX_BLOCKS_IN_MCU]; + /* MCU_membership[i] is index in cur_comp_info of component owning */ + /* i'th block in an MCU */ + + int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ + + /* This field is shared between entropy decoder and marker parser. + * It is either zero or the code of a JPEG marker that has been + * read from the data source, but has not yet been processed. + */ + int unread_marker; + + /* + * Links to decompression subobjects (methods, private variables of modules) + */ + struct jpeg_decomp_master * master; + struct jpeg_d_main_controller * main; + struct jpeg_d_coef_controller * coef; + struct jpeg_d_post_controller * post; + struct jpeg_input_controller * inputctl; + struct jpeg_marker_reader * marker; + struct jpeg_entropy_decoder * entropy; + struct jpeg_inverse_dct * idct; + struct jpeg_upsampler * upsample; + struct jpeg_color_deconverter * cconvert; + struct jpeg_color_quantizer * cquantize; +}; + + +/* "Object" declarations for JPEG modules that may be supplied or called + * directly by the surrounding application. + * As with all objects in the JPEG library, these structs only define the + * publicly visible methods and state variables of a module. Additional + * private fields may exist after the public ones. + */ + + +/* Error handler object */ + +struct jpeg_error_mgr { + /* Error exit handler: does not return to caller */ + JMETHOD(void, error_exit, (j_common_ptr cinfo)); + /* Conditionally emit a trace or warning message */ + JMETHOD(void, emit_message, (j_common_ptr cinfo, int msg_level)); + /* Routine that actually outputs a trace or error message */ + JMETHOD(void, output_message, (j_common_ptr cinfo)); + /* Format a message string for the most recent JPEG error or message */ + JMETHOD(void, format_message, (j_common_ptr cinfo, char * buffer)); +#define JMSG_LENGTH_MAX 200 /* recommended size of format_message buffer */ + /* Reset error state variables at start of a new image */ + JMETHOD(void, reset_error_mgr, (j_common_ptr cinfo)); + + /* The message ID code and any parameters are saved here. + * A message can have one string parameter or up to 8 int parameters. + */ + int msg_code; +#define JMSG_STR_PARM_MAX 80 + union { + int i[8]; + char s[JMSG_STR_PARM_MAX]; + } msg_parm; + + /* Standard state variables for error facility */ + + int trace_level; /* max msg_level that will be displayed */ + + /* For recoverable corrupt-data errors, we emit a warning message, + * but keep going unless emit_message chooses to abort. emit_message + * should count warnings in num_warnings. The surrounding application + * can check for bad data by seeing if num_warnings is nonzero at the + * end of processing. + */ + long num_warnings; /* number of corrupt-data warnings */ + + /* These fields point to the table(s) of error message strings. + * An application can change the table pointer to switch to a different + * message list (typically, to change the language in which errors are + * reported). Some applications may wish to add additional error codes + * that will be handled by the JPEG library error mechanism; the second + * table pointer is used for this purpose. + * + * First table includes all errors generated by JPEG library itself. + * Error code 0 is reserved for a "no such error string" message. + */ + const char * const * jpeg_message_table; /* Library errors */ + int last_jpeg_message; /* Table contains strings 0..last_jpeg_message */ + /* Second table can be added by application (see cjpeg/djpeg for example). + * It contains strings numbered first_addon_message..last_addon_message. + */ + const char * const * addon_message_table; /* Non-library errors */ + int first_addon_message; /* code for first string in addon table */ + int last_addon_message; /* code for last string in addon table */ +}; + + +/* Progress monitor object */ + +struct jpeg_progress_mgr { + JMETHOD(void, progress_monitor, (j_common_ptr cinfo)); + + long pass_counter; /* work units completed in this pass */ + long pass_limit; /* total number of work units in this pass */ + int completed_passes; /* passes completed so far */ + int total_passes; /* total number of passes expected */ +}; + + +/* Data destination object for compression */ + +struct jpeg_destination_mgr { + JOCTET * next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + + JMETHOD(void, init_destination, (j_compress_ptr cinfo)); + JMETHOD(boolean, empty_output_buffer, (j_compress_ptr cinfo)); + JMETHOD(void, term_destination, (j_compress_ptr cinfo)); +}; + + +/* Data source object for decompression */ + +struct jpeg_source_mgr { + const JOCTET * next_input_byte; /* => next byte to read from buffer */ + size_t bytes_in_buffer; /* # of bytes remaining in buffer */ + + JMETHOD(void, init_source, (j_decompress_ptr cinfo)); + JMETHOD(boolean, fill_input_buffer, (j_decompress_ptr cinfo)); + JMETHOD(void, skip_input_data, (j_decompress_ptr cinfo, long num_bytes)); + JMETHOD(boolean, resync_to_restart, (j_decompress_ptr cinfo, int desired)); + JMETHOD(void, term_source, (j_decompress_ptr cinfo)); +}; + + +/* Memory manager object. + * Allocates "small" objects (a few K total), "large" objects (tens of K), + * and "really big" objects (virtual arrays with backing store if needed). + * The memory manager does not allow individual objects to be freed; rather, + * each created object is assigned to a pool, and whole pools can be freed + * at once. This is faster and more convenient than remembering exactly what + * to free, especially where malloc()/free() are not too speedy. + * NB: alloc routines never return NULL. They exit to error_exit if not + * successful. + */ + +#define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */ +#define JPOOL_IMAGE 1 /* lasts until done with image/datastream */ +#define JPOOL_NUMPOOLS 2 + +typedef struct jvirt_sarray_control * jvirt_sarray_ptr; +typedef struct jvirt_barray_control * jvirt_barray_ptr; + + +struct jpeg_memory_mgr { + /* Method pointers */ + JMETHOD(void *, alloc_small, (j_common_ptr cinfo, int pool_id, + size_t sizeofobject)); + JMETHOD(void FAR *, alloc_large, (j_common_ptr cinfo, int pool_id, + size_t sizeofobject)); + JMETHOD(JSAMPARRAY, alloc_sarray, (j_common_ptr cinfo, int pool_id, + JDIMENSION samplesperrow, + JDIMENSION numrows)); + JMETHOD(JBLOCKARRAY, alloc_barray, (j_common_ptr cinfo, int pool_id, + JDIMENSION blocksperrow, + JDIMENSION numrows)); + JMETHOD(jvirt_sarray_ptr, request_virt_sarray, (j_common_ptr cinfo, + int pool_id, + boolean pre_zero, + JDIMENSION samplesperrow, + JDIMENSION numrows, + JDIMENSION maxaccess)); + JMETHOD(jvirt_barray_ptr, request_virt_barray, (j_common_ptr cinfo, + int pool_id, + boolean pre_zero, + JDIMENSION blocksperrow, + JDIMENSION numrows, + JDIMENSION maxaccess)); + JMETHOD(void, realize_virt_arrays, (j_common_ptr cinfo)); + JMETHOD(JSAMPARRAY, access_virt_sarray, (j_common_ptr cinfo, + jvirt_sarray_ptr ptr, + JDIMENSION start_row, + JDIMENSION num_rows, + boolean writable)); + JMETHOD(JBLOCKARRAY, access_virt_barray, (j_common_ptr cinfo, + jvirt_barray_ptr ptr, + JDIMENSION start_row, + JDIMENSION num_rows, + boolean writable)); + JMETHOD(void, free_pool, (j_common_ptr cinfo, int pool_id)); + JMETHOD(void, self_destruct, (j_common_ptr cinfo)); + + /* Limit on memory allocation for this JPEG object. (Note that this is + * merely advisory, not a guaranteed maximum; it only affects the space + * used for virtual-array buffers.) May be changed by outer application + * after creating the JPEG object. + */ + long max_memory_to_use; + + /* Maximum allocation request accepted by alloc_large. */ + long max_alloc_chunk; +}; + + +/* Routine signature for application-supplied marker processing methods. + * Need not pass marker code since it is stored in cinfo->unread_marker. + */ +typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo)); + + +/* Declarations for routines called by application. + * The JPP macro hides prototype parameters from compilers that can't cope. + * Note JPP requires double parentheses. + */ + +#ifdef HAVE_PROTOTYPES +#define JPP(arglist) arglist +#else +#define JPP(arglist) () +#endif + + +/* Short forms of external names for systems with brain-damaged linkers. + * We shorten external names to be unique in the first six letters, which + * is good enough for all known systems. + * (If your compiler itself needs names to be unique in less than 15 + * characters, you are out of luck. Get a better compiler.) + */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_std_error jStdError +#define jpeg_CreateCompress jCreaCompress +#define jpeg_CreateDecompress jCreaDecompress +#define jpeg_destroy_compress jDestCompress +#define jpeg_destroy_decompress jDestDecompress +#define jpeg_stdio_dest jStdDest +#define jpeg_stdio_src jStdSrc +#define jpeg_set_defaults jSetDefaults +#define jpeg_set_colorspace jSetColorspace +#define jpeg_default_colorspace jDefColorspace +#define jpeg_set_quality jSetQuality +#define jpeg_set_linear_quality jSetLQuality +#define jpeg_add_quant_table jAddQuantTable +#define jpeg_quality_scaling jQualityScaling +#define jpeg_simple_progression jSimProgress +#define jpeg_suppress_tables jSuppressTables +#define jpeg_alloc_quant_table jAlcQTable +#define jpeg_alloc_huff_table jAlcHTable +#define jpeg_start_compress jStrtCompress +#define jpeg_write_scanlines jWrtScanlines +#define jpeg_finish_compress jFinCompress +#define jpeg_write_raw_data jWrtRawData +#define jpeg_write_marker jWrtMarker +#define jpeg_write_m_header jWrtMHeader +#define jpeg_write_m_byte jWrtMByte +#define jpeg_write_tables jWrtTables +#define jpeg_read_header jReadHeader +#define jpeg_start_decompress jStrtDecompress +#define jpeg_read_scanlines jReadScanlines +#define jpeg_finish_decompress jFinDecompress +#define jpeg_read_raw_data jReadRawData +#define jpeg_has_multiple_scans jHasMultScn +#define jpeg_start_output jStrtOutput +#define jpeg_finish_output jFinOutput +#define jpeg_input_complete jInComplete +#define jpeg_new_colormap jNewCMap +#define jpeg_consume_input jConsumeInput +#define jpeg_calc_output_dimensions jCalcDimensions +#define jpeg_save_markers jSaveMarkers +#define jpeg_set_marker_processor jSetMarker +#define jpeg_read_coefficients jReadCoefs +#define jpeg_write_coefficients jWrtCoefs +#define jpeg_copy_critical_parameters jCopyCrit +#define jpeg_abort_compress jAbrtCompress +#define jpeg_abort_decompress jAbrtDecompress +#define jpeg_abort jAbort +#define jpeg_destroy jDestroy +#define jpeg_resync_to_restart jResyncRestart +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* Default error-management setup */ +EXTERN(struct jpeg_error_mgr *) jpeg_std_error + JPP((struct jpeg_error_mgr * err)); + +/* Initialization of JPEG compression objects. + * jpeg_create_compress() and jpeg_create_decompress() are the exported + * names that applications should call. These expand to calls on + * jpeg_CreateCompress and jpeg_CreateDecompress with additional information + * passed for version mismatch checking. + * NB: you must set up the error-manager BEFORE calling jpeg_create_xxx. + */ +#define jpeg_create_compress(cinfo) \ + jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \ + (size_t) sizeof(struct jpeg_compress_struct)) +#define jpeg_create_decompress(cinfo) \ + jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \ + (size_t) sizeof(struct jpeg_decompress_struct)) +EXTERN(void) jpeg_CreateCompress JPP((j_compress_ptr cinfo, + int version, size_t structsize)); +EXTERN(void) jpeg_CreateDecompress JPP((j_decompress_ptr cinfo, + int version, size_t structsize)); +/* Destruction of JPEG compression objects */ +EXTERN(void) jpeg_destroy_compress JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_destroy_decompress JPP((j_decompress_ptr cinfo)); + +/* Standard data source and destination managers: stdio streams. */ +/* Caller is responsible for opening the file before and closing after. */ +EXTERN(void) jpeg_stdio_dest JPP((j_compress_ptr cinfo, FILE * outfile)); +EXTERN(void) jpeg_stdio_src JPP((j_decompress_ptr cinfo, FILE * infile)); + +/* Default parameter setup for compression */ +EXTERN(void) jpeg_set_defaults JPP((j_compress_ptr cinfo)); +/* Compression parameter setup aids */ +EXTERN(void) jpeg_set_colorspace JPP((j_compress_ptr cinfo, + J_COLOR_SPACE colorspace)); +EXTERN(void) jpeg_default_colorspace JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_set_quality JPP((j_compress_ptr cinfo, int quality, + boolean force_baseline)); +EXTERN(void) jpeg_set_linear_quality JPP((j_compress_ptr cinfo, + int scale_factor, + boolean force_baseline)); +EXTERN(void) jpeg_add_quant_table JPP((j_compress_ptr cinfo, int which_tbl, + const unsigned int *basic_table, + int scale_factor, + boolean force_baseline)); +EXTERN(int) jpeg_quality_scaling JPP((int quality)); +EXTERN(void) jpeg_simple_progression JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_suppress_tables JPP((j_compress_ptr cinfo, + boolean suppress)); +EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table JPP((j_common_ptr cinfo)); +EXTERN(JHUFF_TBL *) jpeg_alloc_huff_table JPP((j_common_ptr cinfo)); + +/* Main entry points for compression */ +EXTERN(void) jpeg_start_compress JPP((j_compress_ptr cinfo, + boolean write_all_tables)); +EXTERN(JDIMENSION) jpeg_write_scanlines JPP((j_compress_ptr cinfo, + JSAMPARRAY scanlines, + JDIMENSION num_lines)); +EXTERN(void) jpeg_finish_compress JPP((j_compress_ptr cinfo)); + +/* Replaces jpeg_write_scanlines when writing raw downsampled data. */ +EXTERN(JDIMENSION) jpeg_write_raw_data JPP((j_compress_ptr cinfo, + JSAMPIMAGE data, + JDIMENSION num_lines)); + +/* Write a special marker. See libjpeg.doc concerning safe usage. */ +EXTERN(void) jpeg_write_marker + JPP((j_compress_ptr cinfo, int marker, + const JOCTET * dataptr, unsigned int datalen)); +/* Same, but piecemeal. */ +EXTERN(void) jpeg_write_m_header + JPP((j_compress_ptr cinfo, int marker, unsigned int datalen)); +EXTERN(void) jpeg_write_m_byte + JPP((j_compress_ptr cinfo, int val)); + +/* Alternate compression function: just write an abbreviated table file */ +EXTERN(void) jpeg_write_tables JPP((j_compress_ptr cinfo)); + +/* Decompression startup: read start of JPEG datastream to see what's there */ +EXTERN(int) jpeg_read_header JPP((j_decompress_ptr cinfo, + boolean require_image)); +/* Return value is one of: */ +#define JPEG_SUSPENDED 0 /* Suspended due to lack of input data */ +#define JPEG_HEADER_OK 1 /* Found valid image datastream */ +#define JPEG_HEADER_TABLES_ONLY 2 /* Found valid table-specs-only datastream */ +/* If you pass require_image = TRUE (normal case), you need not check for + * a TABLES_ONLY return code; an abbreviated file will cause an error exit. + * JPEG_SUSPENDED is only possible if you use a data source module that can + * give a suspension return (the stdio source module doesn't). + */ + +/* Main entry points for decompression */ +EXTERN(boolean) jpeg_start_decompress JPP((j_decompress_ptr cinfo)); +EXTERN(JDIMENSION) jpeg_read_scanlines JPP((j_decompress_ptr cinfo, + JSAMPARRAY scanlines, + JDIMENSION max_lines)); +EXTERN(boolean) jpeg_finish_decompress JPP((j_decompress_ptr cinfo)); + +/* Replaces jpeg_read_scanlines when reading raw downsampled data. */ +EXTERN(JDIMENSION) jpeg_read_raw_data JPP((j_decompress_ptr cinfo, + JSAMPIMAGE data, + JDIMENSION max_lines)); + +/* Additional entry points for buffered-image mode. */ +EXTERN(boolean) jpeg_has_multiple_scans JPP((j_decompress_ptr cinfo)); +EXTERN(boolean) jpeg_start_output JPP((j_decompress_ptr cinfo, + int scan_number)); +EXTERN(boolean) jpeg_finish_output JPP((j_decompress_ptr cinfo)); +EXTERN(boolean) jpeg_input_complete JPP((j_decompress_ptr cinfo)); +EXTERN(void) jpeg_new_colormap JPP((j_decompress_ptr cinfo)); +EXTERN(int) jpeg_consume_input JPP((j_decompress_ptr cinfo)); +/* Return value is one of: */ +/* #define JPEG_SUSPENDED 0 Suspended due to lack of input data */ +#define JPEG_REACHED_SOS 1 /* Reached start of new scan */ +#define JPEG_REACHED_EOI 2 /* Reached end of image */ +#define JPEG_ROW_COMPLETED 3 /* Completed one iMCU row */ +#define JPEG_SCAN_COMPLETED 4 /* Completed last iMCU row of a scan */ + +/* Precalculate output dimensions for current decompression parameters. */ +EXTERN(void) jpeg_calc_output_dimensions JPP((j_decompress_ptr cinfo)); + +/* Control saving of COM and APPn markers into marker_list. */ +EXTERN(void) jpeg_save_markers + JPP((j_decompress_ptr cinfo, int marker_code, + unsigned int length_limit)); + +/* Install a special processing method for COM or APPn markers. */ +EXTERN(void) jpeg_set_marker_processor + JPP((j_decompress_ptr cinfo, int marker_code, + jpeg_marker_parser_method routine)); + +/* Read or write raw DCT coefficients --- useful for lossless transcoding. */ +EXTERN(jvirt_barray_ptr *) jpeg_read_coefficients JPP((j_decompress_ptr cinfo)); +EXTERN(void) jpeg_write_coefficients JPP((j_compress_ptr cinfo, + jvirt_barray_ptr * coef_arrays)); +EXTERN(void) jpeg_copy_critical_parameters JPP((j_decompress_ptr srcinfo, + j_compress_ptr dstinfo)); + +/* If you choose to abort compression or decompression before completing + * jpeg_finish_(de)compress, then you need to clean up to release memory, + * temporary files, etc. You can just call jpeg_destroy_(de)compress + * if you're done with the JPEG object, but if you want to clean it up and + * reuse it, call this: + */ +EXTERN(void) jpeg_abort_compress JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_abort_decompress JPP((j_decompress_ptr cinfo)); + +/* Generic versions of jpeg_abort and jpeg_destroy that work on either + * flavor of JPEG object. These may be more convenient in some places. + */ +EXTERN(void) jpeg_abort JPP((j_common_ptr cinfo)); +EXTERN(void) jpeg_destroy JPP((j_common_ptr cinfo)); + +/* Default restart-marker-resync procedure for use by data source modules */ +EXTERN(boolean) jpeg_resync_to_restart JPP((j_decompress_ptr cinfo, + int desired)); + + +/* These marker codes are exported since applications and data source modules + * are likely to want to use them. + */ + +#define JPEG_RST0 0xD0 /* RST0 marker code */ +#define JPEG_EOI 0xD9 /* EOI marker code */ +#define JPEG_APP0 0xE0 /* APP0 marker code */ +#define JPEG_COM 0xFE /* COM marker code */ + + +/* If we have a brain-damaged compiler that emits warnings (or worse, errors) + * for structure definitions that are never filled in, keep it quiet by + * supplying dummy definitions for the various substructures. + */ + +#ifdef INCOMPLETE_TYPES_BROKEN +#ifndef JPEG_INTERNALS /* will be defined in jpegint.h */ +struct jvirt_sarray_control { long dummy; }; +struct jvirt_barray_control { long dummy; }; +struct jpeg_comp_master { long dummy; }; +struct jpeg_c_main_controller { long dummy; }; +struct jpeg_c_prep_controller { long dummy; }; +struct jpeg_c_coef_controller { long dummy; }; +struct jpeg_marker_writer { long dummy; }; +struct jpeg_color_converter { long dummy; }; +struct jpeg_downsampler { long dummy; }; +struct jpeg_forward_dct { long dummy; }; +struct jpeg_entropy_encoder { long dummy; }; +struct jpeg_decomp_master { long dummy; }; +struct jpeg_d_main_controller { long dummy; }; +struct jpeg_d_coef_controller { long dummy; }; +struct jpeg_d_post_controller { long dummy; }; +struct jpeg_input_controller { long dummy; }; +struct jpeg_marker_reader { long dummy; }; +struct jpeg_entropy_decoder { long dummy; }; +struct jpeg_inverse_dct { long dummy; }; +struct jpeg_upsampler { long dummy; }; +struct jpeg_color_deconverter { long dummy; }; +struct jpeg_color_quantizer { long dummy; }; +#endif /* JPEG_INTERNALS */ +#endif /* INCOMPLETE_TYPES_BROKEN */ + + +/* + * The JPEG library modules define JPEG_INTERNALS before including this file. + * The internal structure declarations are read only when that is true. + * Applications using the library should not include jpegint.h, but may wish + * to include jerror.h. + */ + +#ifdef JPEG_INTERNALS +#include "jpegint.h" /* fetch private declarations */ +#include "jerror.h" /* fetch error codes too */ +#endif + +#endif /* JPEGLIB_H */ diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jpegtran.1 b/lc-continuity/mk4/modimage/jpeg-6b/jpegtran.1 new file mode 100644 index 0000000000000000000000000000000000000000..6de18e2af960b0cb346ea1d4fd38002f3817460b --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jpegtran.1 @@ -0,0 +1,238 @@ +.TH JPEGTRAN 1 "3 August 1997" +.SH NAME +jpegtran \- lossless transformation of JPEG files +.SH SYNOPSIS +.B jpegtran +[ +.I options +] +[ +.I filename +] +.LP +.SH DESCRIPTION +.LP +.B jpegtran +performs various useful transformations of JPEG files. +It can translate the coded representation from one variant of JPEG to another, +for example from baseline JPEG to progressive JPEG or vice versa. It can also +perform some rearrangements of the image data, for example turning an image +from landscape to portrait format by rotation. +.PP +.B jpegtran +works by rearranging the compressed data (DCT coefficients), without +ever fully decoding the image. Therefore, its transformations are lossless: +there is no image degradation at all, which would not be true if you used +.B djpeg +followed by +.B cjpeg +to accomplish the same conversion. But by the same token, +.B jpegtran +cannot perform lossy operations such as changing the image quality. +.PP +.B jpegtran +reads the named JPEG/JFIF file, or the standard input if no file is +named, and produces a JPEG/JFIF file on the standard output. +.SH OPTIONS +All switch names may be abbreviated; for example, +.B \-optimize +may be written +.B \-opt +or +.BR \-o . +Upper and lower case are equivalent. +British spellings are also accepted (e.g., +.BR \-optimise ), +though for brevity these are not mentioned below. +.PP +To specify the coded JPEG representation used in the output file, +.B jpegtran +accepts a subset of the switches recognized by +.BR cjpeg : +.TP +.B \-optimize +Perform optimization of entropy encoding parameters. +.TP +.B \-progressive +Create progressive JPEG file. +.TP +.BI \-restart " N" +Emit a JPEG restart marker every N MCU rows, or every N MCU blocks if "B" is +attached to the number. +.TP +.BI \-scans " file" +Use the scan script given in the specified text file. +.PP +See +.BR cjpeg (1) +for more details about these switches. +If you specify none of these switches, you get a plain baseline-JPEG output +file. The quality setting and so forth are determined by the input file. +.PP +The image can be losslessly transformed by giving one of these switches: +.TP +.B \-flip horizontal +Mirror image horizontally (left-right). +.TP +.B \-flip vertical +Mirror image vertically (top-bottom). +.TP +.B \-rotate 90 +Rotate image 90 degrees clockwise. +.TP +.B \-rotate 180 +Rotate image 180 degrees. +.TP +.B \-rotate 270 +Rotate image 270 degrees clockwise (or 90 ccw). +.TP +.B \-transpose +Transpose image (across UL-to-LR axis). +.TP +.B \-transverse +Transverse transpose (across UR-to-LL axis). +.PP +The transpose transformation has no restrictions regarding image dimensions. +The other transformations operate rather oddly if the image dimensions are not +a multiple of the iMCU size (usually 8 or 16 pixels), because they can only +transform complete blocks of DCT coefficient data in the desired way. +.PP +.BR jpegtran 's +default behavior when transforming an odd-size image is designed +to preserve exact reversibility and mathematical consistency of the +transformation set. As stated, transpose is able to flip the entire image +area. Horizontal mirroring leaves any partial iMCU column at the right edge +untouched, but is able to flip all rows of the image. Similarly, vertical +mirroring leaves any partial iMCU row at the bottom edge untouched, but is +able to flip all columns. The other transforms can be built up as sequences +of transpose and flip operations; for consistency, their actions on edge +pixels are defined to be the same as the end result of the corresponding +transpose-and-flip sequence. +.PP +For practical use, you may prefer to discard any untransformable edge pixels +rather than having a strange-looking strip along the right and/or bottom edges +of a transformed image. To do this, add the +.B \-trim +switch: +.TP +.B \-trim +Drop non-transformable edge blocks. +.PP +Obviously, a transformation with +.B \-trim +is not reversible, so strictly speaking +.B jpegtran +with this switch is not lossless. Also, the expected mathematical +equivalences between the transformations no longer hold. For example, +.B \-rot 270 -trim +trims only the bottom edge, but +.B \-rot 90 -trim +followed by +.B \-rot 180 -trim +trims both edges. +.PP +Another not-strictly-lossless transformation switch is: +.TP +.B \-grayscale +Force grayscale output. +.PP +This option discards the chrominance channels if the input image is YCbCr +(ie, a standard color JPEG), resulting in a grayscale JPEG file. The +luminance channel is preserved exactly, so this is a better method of reducing +to grayscale than decompression, conversion, and recompression. This switch +is particularly handy for fixing a monochrome picture that was mistakenly +encoded as a color JPEG. (In such a case, the space savings from getting rid +of the near-empty chroma channels won't be large; but the decoding time for +a grayscale JPEG is substantially less than that for a color JPEG.) +.PP +.B jpegtran +also recognizes these switches that control what to do with "extra" markers, +such as comment blocks: +.TP +.B \-copy none +Copy no extra markers from source file. This setting suppresses all +comments and other excess baggage present in the source file. +.TP +.B \-copy comments +Copy only comment markers. This setting copies comments from the source file, +but discards any other inessential data. +.TP +.B \-copy all +Copy all extra markers. This setting preserves miscellaneous markers +found in the source file, such as JFIF thumbnails and Photoshop settings. +In some files these extra markers can be sizable. +.PP +The default behavior is +.BR "\-copy comments" . +(Note: in IJG releases v6 and v6a, +.B jpegtran +always did the equivalent of +.BR "\-copy none" .) +.PP +Additional switches recognized by jpegtran are: +.TP +.BI \-maxmemory " N" +Set limit for amount of memory to use in processing large images. Value is +in thousands of bytes, or millions of bytes if "M" is attached to the +number. For example, +.B \-max 4m +selects 4000000 bytes. If more space is needed, temporary files will be used. +.TP +.BI \-outfile " name" +Send output image to the named file, not to standard output. +.TP +.B \-verbose +Enable debug printout. More +.BR \-v 's +give more output. Also, version information is printed at startup. +.TP +.B \-debug +Same as +.BR \-verbose . +.SH EXAMPLES +.LP +This example converts a baseline JPEG file to progressive form: +.IP +.B jpegtran \-progressive +.I foo.jpg +.B > +.I fooprog.jpg +.PP +This example rotates an image 90 degrees clockwise, discarding any +unrotatable edge pixels: +.IP +.B jpegtran \-rot 90 -trim +.I foo.jpg +.B > +.I foo90.jpg +.SH ENVIRONMENT +.TP +.B JPEGMEM +If this environment variable is set, its value is the default memory limit. +The value is specified as described for the +.B \-maxmemory +switch. +.B JPEGMEM +overrides the default value specified when the program was compiled, and +itself is overridden by an explicit +.BR \-maxmemory . +.SH SEE ALSO +.BR cjpeg (1), +.BR djpeg (1), +.BR rdjpgcom (1), +.BR wrjpgcom (1) +.br +Wallace, Gregory K. "The JPEG Still Picture Compression Standard", +Communications of the ACM, April 1991 (vol. 34, no. 4), pp. 30-44. +.SH AUTHOR +Independent JPEG Group +.SH BUGS +Arithmetic coding is not supported for legal reasons. +.PP +The transform options can't transform odd-size images perfectly. Use +.B \-trim +if you don't like the results without it. +.PP +The entire image is read into memory and then written out again, even in +cases where this isn't really necessary. Expect swapping on large images, +especially when using the more complex transform options. diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jpegtran.c b/lc-continuity/mk4/modimage/jpeg-6b/jpegtran.c new file mode 100644 index 0000000000000000000000000000000000000000..20ef111b3f563539eba0cea2f0d5327e440b7b00 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jpegtran.c @@ -0,0 +1,504 @@ +/* + * jpegtran.c + * + * Copyright (C) 1995-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a command-line user interface for JPEG transcoding. + * It is very similar to cjpeg.c, but provides lossless transcoding between + * different JPEG file formats. It also provides some lossless and sort-of- + * lossless transformations of JPEG data. + */ + +#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ +#include "transupp.h" /* Support routines for jpegtran */ +#include "jversion.h" /* for version message */ + +#ifdef USE_CCOMMAND /* command-line reader for Macintosh */ +#ifdef __MWERKS__ +#include /* Metrowerks needs this */ +#include /* ... and this */ +#endif +#ifdef THINK_C +#include /* Think declares it here */ +#endif +#endif + + +/* + * Argument-parsing code. + * The switch parser is designed to be useful with DOS-style command line + * syntax, ie, intermixed switches and file names, where only the switches + * to the left of a given file name affect processing of that file. + * The main program in this file doesn't actually use this capability... + */ + + +static const char * progname; /* program name for error messages */ +static char * outfilename; /* for -outfile switch */ +static JCOPY_OPTION copyoption; /* -copy switch */ +static jpeg_transform_info transformoption; /* image transformation options */ + + +LOCAL(void) +usage (void) +/* complain about bad command line */ +{ + fprintf(stderr, "usage: %s [switches] ", progname); +#ifdef TWO_FILE_COMMANDLINE + fprintf(stderr, "inputfile outputfile\n"); +#else + fprintf(stderr, "[inputfile]\n"); +#endif + + fprintf(stderr, "Switches (names may be abbreviated):\n"); + fprintf(stderr, " -copy none Copy no extra markers from source file\n"); + fprintf(stderr, " -copy comments Copy only comment markers (default)\n"); + fprintf(stderr, " -copy all Copy all extra markers\n"); +#ifdef ENTROPY_OPT_SUPPORTED + fprintf(stderr, " -optimize Optimize Huffman table (smaller file, but slow compression)\n"); +#endif +#ifdef C_PROGRESSIVE_SUPPORTED + fprintf(stderr, " -progressive Create progressive JPEG file\n"); +#endif +#if TRANSFORMS_SUPPORTED + fprintf(stderr, "Switches for modifying the image:\n"); + fprintf(stderr, " -grayscale Reduce to grayscale (omit color data)\n"); + fprintf(stderr, " -flip [horizontal|vertical] Mirror image (left-right or top-bottom)\n"); + fprintf(stderr, " -rotate [90|180|270] Rotate image (degrees clockwise)\n"); + fprintf(stderr, " -transpose Transpose image\n"); + fprintf(stderr, " -transverse Transverse transpose image\n"); + fprintf(stderr, " -trim Drop non-transformable edge blocks\n"); +#endif /* TRANSFORMS_SUPPORTED */ + fprintf(stderr, "Switches for advanced users:\n"); + fprintf(stderr, " -restart N Set restart interval in rows, or in blocks with B\n"); + fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n"); + fprintf(stderr, " -outfile name Specify name for output file\n"); + fprintf(stderr, " -verbose or -debug Emit debug output\n"); + fprintf(stderr, "Switches for wizards:\n"); +#ifdef C_ARITH_CODING_SUPPORTED + fprintf(stderr, " -arithmetic Use arithmetic coding\n"); +#endif +#ifdef C_MULTISCAN_FILES_SUPPORTED + fprintf(stderr, " -scans file Create multi-scan JPEG per script file\n"); +#endif + exit(EXIT_FAILURE); +} + + +LOCAL(void) +select_transform (JXFORM_CODE transform) +/* Silly little routine to detect multiple transform options, + * which we can't handle. + */ +{ +#if TRANSFORMS_SUPPORTED + if (transformoption.transform == JXFORM_NONE || + transformoption.transform == transform) { + transformoption.transform = transform; + } else { + fprintf(stderr, "%s: can only do one image transformation at a time\n", + progname); + usage(); + } +#else + fprintf(stderr, "%s: sorry, image transformation was not compiled\n", + progname); + exit(EXIT_FAILURE); +#endif +} + + +LOCAL(int) +parse_switches (j_compress_ptr cinfo, int argc, char **argv, + int last_file_arg_seen, boolean for_real) +/* Parse optional switches. + * Returns argv[] index of first file-name argument (== argc if none). + * Any file names with indexes <= last_file_arg_seen are ignored; + * they have presumably been processed in a previous iteration. + * (Pass 0 for last_file_arg_seen on the first or only iteration.) + * for_real is FALSE on the first (dummy) pass; we may skip any expensive + * processing. + */ +{ + int argn; + char * arg; + boolean simple_progressive; + char * scansarg = NULL; /* saves -scans parm if any */ + + /* Set up default JPEG parameters. */ + simple_progressive = FALSE; + outfilename = NULL; + copyoption = JCOPYOPT_DEFAULT; + transformoption.transform = JXFORM_NONE; + transformoption.trim = FALSE; + transformoption.force_grayscale = FALSE; + cinfo->err->trace_level = 0; + + /* Scan command line options, adjust parameters */ + + for (argn = 1; argn < argc; argn++) { + arg = argv[argn]; + if (*arg != '-') { + /* Not a switch, must be a file name argument */ + if (argn <= last_file_arg_seen) { + outfilename = NULL; /* -outfile applies to just one input file */ + continue; /* ignore this name if previously processed */ + } + break; /* else done parsing switches */ + } + arg++; /* advance past switch marker character */ + + if (keymatch(arg, "arithmetic", 1)) { + /* Use arithmetic coding. */ +#ifdef C_ARITH_CODING_SUPPORTED + cinfo->arith_code = TRUE; +#else + fprintf(stderr, "%s: sorry, arithmetic coding not supported\n", + progname); + exit(EXIT_FAILURE); +#endif + + } else if (keymatch(arg, "copy", 1)) { + /* Select which extra markers to copy. */ + if (++argn >= argc) /* advance to next argument */ + usage(); + if (keymatch(argv[argn], "none", 1)) { + copyoption = JCOPYOPT_NONE; + } else if (keymatch(argv[argn], "comments", 1)) { + copyoption = JCOPYOPT_COMMENTS; + } else if (keymatch(argv[argn], "all", 1)) { + copyoption = JCOPYOPT_ALL; + } else + usage(); + + } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) { + /* Enable debug printouts. */ + /* On first -d, print version identification */ + static boolean printed_version = FALSE; + + if (! printed_version) { + fprintf(stderr, "Independent JPEG Group's JPEGTRAN, version %s\n%s\n", + JVERSION, JCOPYRIGHT); + printed_version = TRUE; + } + cinfo->err->trace_level++; + + } else if (keymatch(arg, "flip", 1)) { + /* Mirror left-right or top-bottom. */ + if (++argn >= argc) /* advance to next argument */ + usage(); + if (keymatch(argv[argn], "horizontal", 1)) + select_transform(JXFORM_FLIP_H); + else if (keymatch(argv[argn], "vertical", 1)) + select_transform(JXFORM_FLIP_V); + else + usage(); + + } else if (keymatch(arg, "grayscale", 1) || keymatch(arg, "greyscale",1)) { + /* Force to grayscale. */ +#if TRANSFORMS_SUPPORTED + transformoption.force_grayscale = TRUE; +#else + select_transform(JXFORM_NONE); /* force an error */ +#endif + + } else if (keymatch(arg, "maxmemory", 3)) { + /* Maximum memory in Kb (or Mb with 'm'). */ + long lval; + char ch = 'x'; + + if (++argn >= argc) /* advance to next argument */ + usage(); + if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1) + usage(); + if (ch == 'm' || ch == 'M') + lval *= 1000L; + cinfo->mem->max_memory_to_use = lval * 1000L; + + } else if (keymatch(arg, "optimize", 1) || keymatch(arg, "optimise", 1)) { + /* Enable entropy parm optimization. */ +#ifdef ENTROPY_OPT_SUPPORTED + cinfo->optimize_coding = TRUE; +#else + fprintf(stderr, "%s: sorry, entropy optimization was not compiled\n", + progname); + exit(EXIT_FAILURE); +#endif + + } else if (keymatch(arg, "outfile", 4)) { + /* Set output file name. */ + if (++argn >= argc) /* advance to next argument */ + usage(); + outfilename = argv[argn]; /* save it away for later use */ + + } else if (keymatch(arg, "progressive", 1)) { + /* Select simple progressive mode. */ +#ifdef C_PROGRESSIVE_SUPPORTED + simple_progressive = TRUE; + /* We must postpone execution until num_components is known. */ +#else + fprintf(stderr, "%s: sorry, progressive output was not compiled\n", + progname); + exit(EXIT_FAILURE); +#endif + + } else if (keymatch(arg, "restart", 1)) { + /* Restart interval in MCU rows (or in MCUs with 'b'). */ + long lval; + char ch = 'x'; + + if (++argn >= argc) /* advance to next argument */ + usage(); + if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1) + usage(); + if (lval < 0 || lval > 65535L) + usage(); + if (ch == 'b' || ch == 'B') { + cinfo->restart_interval = (unsigned int) lval; + cinfo->restart_in_rows = 0; /* else prior '-restart n' overrides me */ + } else { + cinfo->restart_in_rows = (int) lval; + /* restart_interval will be computed during startup */ + } + + } else if (keymatch(arg, "rotate", 2)) { + /* Rotate 90, 180, or 270 degrees (measured clockwise). */ + if (++argn >= argc) /* advance to next argument */ + usage(); + if (keymatch(argv[argn], "90", 2)) + select_transform(JXFORM_ROT_90); + else if (keymatch(argv[argn], "180", 3)) + select_transform(JXFORM_ROT_180); + else if (keymatch(argv[argn], "270", 3)) + select_transform(JXFORM_ROT_270); + else + usage(); + + } else if (keymatch(arg, "scans", 1)) { + /* Set scan script. */ +#ifdef C_MULTISCAN_FILES_SUPPORTED + if (++argn >= argc) /* advance to next argument */ + usage(); + scansarg = argv[argn]; + /* We must postpone reading the file in case -progressive appears. */ +#else + fprintf(stderr, "%s: sorry, multi-scan output was not compiled\n", + progname); + exit(EXIT_FAILURE); +#endif + + } else if (keymatch(arg, "transpose", 1)) { + /* Transpose (across UL-to-LR axis). */ + select_transform(JXFORM_TRANSPOSE); + + } else if (keymatch(arg, "transverse", 6)) { + /* Transverse transpose (across UR-to-LL axis). */ + select_transform(JXFORM_TRANSVERSE); + + } else if (keymatch(arg, "trim", 3)) { + /* Trim off any partial edge MCUs that the transform can't handle. */ + transformoption.trim = TRUE; + + } else { + usage(); /* bogus switch */ + } + } + + /* Post-switch-scanning cleanup */ + + if (for_real) { + +#ifdef C_PROGRESSIVE_SUPPORTED + if (simple_progressive) /* process -progressive; -scans can override */ + jpeg_simple_progression(cinfo); +#endif + +#ifdef C_MULTISCAN_FILES_SUPPORTED + if (scansarg != NULL) /* process -scans if it was present */ + if (! read_scan_script(cinfo, scansarg)) + usage(); +#endif + } + + return argn; /* return index of next arg (file name) */ +} + + +/* + * The main program. + */ + +int +main (int argc, char **argv) +{ + struct jpeg_decompress_struct srcinfo; + struct jpeg_compress_struct dstinfo; + struct jpeg_error_mgr jsrcerr, jdsterr; +#ifdef PROGRESS_REPORT + struct cdjpeg_progress_mgr progress; +#endif + jvirt_barray_ptr * src_coef_arrays; + jvirt_barray_ptr * dst_coef_arrays; + int file_index; + FILE * input_file; + FILE * output_file; + + /* On Mac, fetch a command line. */ +#ifdef USE_CCOMMAND + argc = ccommand(&argv); +#endif + + progname = argv[0]; + if (progname == NULL || progname[0] == 0) + progname = "jpegtran"; /* in case C library doesn't provide it */ + + /* Initialize the JPEG decompression object with default error handling. */ + srcinfo.err = jpeg_std_error(&jsrcerr); + jpeg_create_decompress(&srcinfo); + /* Initialize the JPEG compression object with default error handling. */ + dstinfo.err = jpeg_std_error(&jdsterr); + jpeg_create_compress(&dstinfo); + + /* Now safe to enable signal catcher. + * Note: we assume only the decompression object will have virtual arrays. + */ +#ifdef NEED_SIGNAL_CATCHER + enable_signal_catcher((j_common_ptr) &srcinfo); +#endif + + /* Scan command line to find file names. + * It is convenient to use just one switch-parsing routine, but the switch + * values read here are mostly ignored; we will rescan the switches after + * opening the input file. Also note that most of the switches affect the + * destination JPEG object, so we parse into that and then copy over what + * needs to affects the source too. + */ + + file_index = parse_switches(&dstinfo, argc, argv, 0, FALSE); + jsrcerr.trace_level = jdsterr.trace_level; + srcinfo.mem->max_memory_to_use = dstinfo.mem->max_memory_to_use; + +#ifdef TWO_FILE_COMMANDLINE + /* Must have either -outfile switch or explicit output file name */ + if (outfilename == NULL) { + if (file_index != argc-2) { + fprintf(stderr, "%s: must name one input and one output file\n", + progname); + usage(); + } + outfilename = argv[file_index+1]; + } else { + if (file_index != argc-1) { + fprintf(stderr, "%s: must name one input and one output file\n", + progname); + usage(); + } + } +#else + /* Unix style: expect zero or one file name */ + if (file_index < argc-1) { + fprintf(stderr, "%s: only one input file\n", progname); + usage(); + } +#endif /* TWO_FILE_COMMANDLINE */ + + /* Open the input file. */ + if (file_index < argc) { + if ((input_file = fopen(argv[file_index], READ_BINARY)) == NULL) { + fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]); + exit(EXIT_FAILURE); + } + } else { + /* default input file is stdin */ + input_file = read_stdin(); + } + + /* Open the output file. */ + if (outfilename != NULL) { + if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) { + fprintf(stderr, "%s: can't open %s\n", progname, outfilename); + exit(EXIT_FAILURE); + } + } else { + /* default output file is stdout */ + output_file = write_stdout(); + } + +#ifdef PROGRESS_REPORT + start_progress_monitor((j_common_ptr) &dstinfo, &progress); +#endif + + /* Specify data source for decompression */ + jpeg_stdio_src(&srcinfo, input_file); + + /* Enable saving of extra markers that we want to copy */ + jcopy_markers_setup(&srcinfo, copyoption); + + /* Read file header */ + (void) jpeg_read_header(&srcinfo, TRUE); + + /* Any space needed by a transform option must be requested before + * jpeg_read_coefficients so that memory allocation will be done right. + */ +#if TRANSFORMS_SUPPORTED + jtransform_request_workspace(&srcinfo, &transformoption); +#endif + + /* Read source file as DCT coefficients */ + src_coef_arrays = jpeg_read_coefficients(&srcinfo); + + /* Initialize destination compression parameters from source values */ + jpeg_copy_critical_parameters(&srcinfo, &dstinfo); + + /* Adjust destination parameters if required by transform options; + * also find out which set of coefficient arrays will hold the output. + */ +#if TRANSFORMS_SUPPORTED + dst_coef_arrays = jtransform_adjust_parameters(&srcinfo, &dstinfo, + src_coef_arrays, + &transformoption); +#else + dst_coef_arrays = src_coef_arrays; +#endif + + /* Adjust default compression parameters by re-parsing the options */ + file_index = parse_switches(&dstinfo, argc, argv, 0, TRUE); + + /* Specify data destination for compression */ + jpeg_stdio_dest(&dstinfo, output_file); + + /* Start compressor (note no image data is actually written here) */ + jpeg_write_coefficients(&dstinfo, dst_coef_arrays); + + /* Copy to the output file any extra markers that we want to preserve */ + jcopy_markers_execute(&srcinfo, &dstinfo, copyoption); + + /* Execute image transformation, if any */ +#if TRANSFORMS_SUPPORTED + jtransform_execute_transformation(&srcinfo, &dstinfo, + src_coef_arrays, + &transformoption); +#endif + + /* Finish compression and release memory */ + jpeg_finish_compress(&dstinfo); + jpeg_destroy_compress(&dstinfo); + (void) jpeg_finish_decompress(&srcinfo); + jpeg_destroy_decompress(&srcinfo); + + /* Close files, if we opened them */ + if (input_file != stdin) + fclose(input_file); + if (output_file != stdout) + fclose(output_file); + +#ifdef PROGRESS_REPORT + end_progress_monitor((j_common_ptr) &dstinfo); +#endif + + /* All done. */ + exit(jsrcerr.num_warnings + jdsterr.num_warnings ?EXIT_WARNING:EXIT_SUCCESS); + return 0; /* suppress no-return-value warnings */ +} diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jquant1.c b/lc-continuity/mk4/modimage/jpeg-6b/jquant1.c new file mode 100644 index 0000000000000000000000000000000000000000..b2f96aa15d25dd722c55b955bf0e475eb3160c15 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jquant1.c @@ -0,0 +1,856 @@ +/* + * jquant1.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains 1-pass color quantization (color mapping) routines. + * These routines provide mapping to a fixed color map using equally spaced + * color values. Optional Floyd-Steinberg or ordered dithering is available. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + +#ifdef QUANT_1PASS_SUPPORTED + + +/* + * The main purpose of 1-pass quantization is to provide a fast, if not very + * high quality, colormapped output capability. A 2-pass quantizer usually + * gives better visual quality; however, for quantized grayscale output this + * quantizer is perfectly adequate. Dithering is highly recommended with this + * quantizer, though you can turn it off if you really want to. + * + * In 1-pass quantization the colormap must be chosen in advance of seeing the + * image. We use a map consisting of all combinations of Ncolors[i] color + * values for the i'th component. The Ncolors[] values are chosen so that + * their product, the total number of colors, is no more than that requested. + * (In most cases, the product will be somewhat less.) + * + * Since the colormap is orthogonal, the representative value for each color + * component can be determined without considering the other components; + * then these indexes can be combined into a colormap index by a standard + * N-dimensional-array-subscript calculation. Most of the arithmetic involved + * can be precalculated and stored in the lookup table colorindex[]. + * colorindex[i][j] maps pixel value j in component i to the nearest + * representative value (grid plane) for that component; this index is + * multiplied by the array stride for component i, so that the + * index of the colormap entry closest to a given pixel value is just + * sum( colorindex[component-number][pixel-component-value] ) + * Aside from being fast, this scheme allows for variable spacing between + * representative values with no additional lookup cost. + * + * If gamma correction has been applied in color conversion, it might be wise + * to adjust the color grid spacing so that the representative colors are + * equidistant in linear space. At this writing, gamma correction is not + * implemented by jdcolor, so nothing is done here. + */ + + +/* Declarations for ordered dithering. + * + * We use a standard 16x16 ordered dither array. The basic concept of ordered + * dithering is described in many references, for instance Dale Schumacher's + * chapter II.2 of Graphics Gems II (James Arvo, ed. Academic Press, 1991). + * In place of Schumacher's comparisons against a "threshold" value, we add a + * "dither" value to the input pixel and then round the result to the nearest + * output value. The dither value is equivalent to (0.5 - threshold) times + * the distance between output values. For ordered dithering, we assume that + * the output colors are equally spaced; if not, results will probably be + * worse, since the dither may be too much or too little at a given point. + * + * The normal calculation would be to form pixel value + dither, range-limit + * this to 0..MAXJSAMPLE, and then index into the colorindex table as usual. + * We can skip the separate range-limiting step by extending the colorindex + * table in both directions. + */ + +#define ODITHER_SIZE 16 /* dimension of dither matrix */ +/* NB: if ODITHER_SIZE is not a power of 2, ODITHER_MASK uses will break */ +#define ODITHER_CELLS (ODITHER_SIZE*ODITHER_SIZE) /* # cells in matrix */ +#define ODITHER_MASK (ODITHER_SIZE-1) /* mask for wrapping around counters */ + +typedef int ODITHER_MATRIX[ODITHER_SIZE][ODITHER_SIZE]; +typedef int (*ODITHER_MATRIX_PTR)[ODITHER_SIZE]; + +static const UINT8 base_dither_matrix[ODITHER_SIZE][ODITHER_SIZE] = { + /* Bayer's order-4 dither array. Generated by the code given in + * Stephen Hawley's article "Ordered Dithering" in Graphics Gems I. + * The values in this array must range from 0 to ODITHER_CELLS-1. + */ + { 0,192, 48,240, 12,204, 60,252, 3,195, 51,243, 15,207, 63,255 }, + { 128, 64,176,112,140, 76,188,124,131, 67,179,115,143, 79,191,127 }, + { 32,224, 16,208, 44,236, 28,220, 35,227, 19,211, 47,239, 31,223 }, + { 160, 96,144, 80,172,108,156, 92,163, 99,147, 83,175,111,159, 95 }, + { 8,200, 56,248, 4,196, 52,244, 11,203, 59,251, 7,199, 55,247 }, + { 136, 72,184,120,132, 68,180,116,139, 75,187,123,135, 71,183,119 }, + { 40,232, 24,216, 36,228, 20,212, 43,235, 27,219, 39,231, 23,215 }, + { 168,104,152, 88,164,100,148, 84,171,107,155, 91,167,103,151, 87 }, + { 2,194, 50,242, 14,206, 62,254, 1,193, 49,241, 13,205, 61,253 }, + { 130, 66,178,114,142, 78,190,126,129, 65,177,113,141, 77,189,125 }, + { 34,226, 18,210, 46,238, 30,222, 33,225, 17,209, 45,237, 29,221 }, + { 162, 98,146, 82,174,110,158, 94,161, 97,145, 81,173,109,157, 93 }, + { 10,202, 58,250, 6,198, 54,246, 9,201, 57,249, 5,197, 53,245 }, + { 138, 74,186,122,134, 70,182,118,137, 73,185,121,133, 69,181,117 }, + { 42,234, 26,218, 38,230, 22,214, 41,233, 25,217, 37,229, 21,213 }, + { 170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85 } +}; + + +/* Declarations for Floyd-Steinberg dithering. + * + * Errors are accumulated into the array fserrors[], at a resolution of + * 1/16th of a pixel count. The error at a given pixel is propagated + * to its not-yet-processed neighbors using the standard F-S fractions, + * ... (here) 7/16 + * 3/16 5/16 1/16 + * We work left-to-right on even rows, right-to-left on odd rows. + * + * We can get away with a single array (holding one row's worth of errors) + * by using it to store the current row's errors at pixel columns not yet + * processed, but the next row's errors at columns already processed. We + * need only a few extra variables to hold the errors immediately around the + * current column. (If we are lucky, those variables are in registers, but + * even if not, they're probably cheaper to access than array elements are.) + * + * The fserrors[] array is indexed [component#][position]. + * We provide (#columns + 2) entries per component; the extra entry at each + * end saves us from special-casing the first and last pixels. + * + * Note: on a wide image, we might not have enough room in a PC's near data + * segment to hold the error array; so it is allocated with alloc_large. + */ + +#if BITS_IN_JSAMPLE == 8 +typedef INT16 FSERROR; /* 16 bits should be enough */ +typedef int LOCFSERROR; /* use 'int' for calculation temps */ +#else +typedef INT32 FSERROR; /* may need more than 16 bits */ +typedef INT32 LOCFSERROR; /* be sure calculation temps are big enough */ +#endif + +typedef FSERROR FAR *FSERRPTR; /* pointer to error array (in FAR storage!) */ + + +/* Private subobject */ + +#define MAX_Q_COMPS 4 /* max components I can handle */ + +typedef struct { + struct jpeg_color_quantizer pub; /* public fields */ + + /* Initially allocated colormap is saved here */ + JSAMPARRAY sv_colormap; /* The color map as a 2-D pixel array */ + int sv_actual; /* number of entries in use */ + + JSAMPARRAY colorindex; /* Precomputed mapping for speed */ + /* colorindex[i][j] = index of color closest to pixel value j in component i, + * premultiplied as described above. Since colormap indexes must fit into + * JSAMPLEs, the entries of this array will too. + */ + boolean is_padded; /* is the colorindex padded for odither? */ + + int Ncolors[MAX_Q_COMPS]; /* # of values alloced to each component */ + + /* Variables for ordered dithering */ + int row_index; /* cur row's vertical index in dither matrix */ + ODITHER_MATRIX_PTR odither[MAX_Q_COMPS]; /* one dither array per component */ + + /* Variables for Floyd-Steinberg dithering */ + FSERRPTR fserrors[MAX_Q_COMPS]; /* accumulated errors */ + boolean on_odd_row; /* flag to remember which row we are on */ +} my_cquantizer; + +typedef my_cquantizer * my_cquantize_ptr; + + +/* + * Policy-making subroutines for create_colormap and create_colorindex. + * These routines determine the colormap to be used. The rest of the module + * only assumes that the colormap is orthogonal. + * + * * select_ncolors decides how to divvy up the available colors + * among the components. + * * output_value defines the set of representative values for a component. + * * largest_input_value defines the mapping from input values to + * representative values for a component. + * Note that the latter two routines may impose different policies for + * different components, though this is not currently done. + */ + + +LOCAL(int) +select_ncolors (j_decompress_ptr cinfo, int Ncolors[]) +/* Determine allocation of desired colors to components, */ +/* and fill in Ncolors[] array to indicate choice. */ +/* Return value is total number of colors (product of Ncolors[] values). */ +{ + int nc = cinfo->out_color_components; /* number of color components */ + int max_colors = cinfo->desired_number_of_colors; + int total_colors, iroot, i, j; + boolean changed; + long temp; + static const int RGB_order[3] = { RGB_GREEN, RGB_RED, RGB_BLUE }; + + /* We can allocate at least the nc'th root of max_colors per component. */ + /* Compute floor(nc'th root of max_colors). */ + iroot = 1; + do { + iroot++; + temp = iroot; /* set temp = iroot ** nc */ + for (i = 1; i < nc; i++) + temp *= iroot; + } while (temp <= (long) max_colors); /* repeat till iroot exceeds root */ + iroot--; /* now iroot = floor(root) */ + + /* Must have at least 2 color values per component */ + if (iroot < 2) + ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, (int) temp); + + /* Initialize to iroot color values for each component */ + total_colors = 1; + for (i = 0; i < nc; i++) { + Ncolors[i] = iroot; + total_colors *= iroot; + } + /* We may be able to increment the count for one or more components without + * exceeding max_colors, though we know not all can be incremented. + * Sometimes, the first component can be incremented more than once! + * (Example: for 16 colors, we start at 2*2*2, go to 3*2*2, then 4*2*2.) + * In RGB colorspace, try to increment G first, then R, then B. + */ + do { + changed = FALSE; + for (i = 0; i < nc; i++) { + j = (cinfo->out_color_space == JCS_RGB ? RGB_order[i] : i); + /* calculate new total_colors if Ncolors[j] is incremented */ + temp = total_colors / Ncolors[j]; + temp *= Ncolors[j]+1; /* done in long arith to avoid oflo */ + if (temp > (long) max_colors) + break; /* won't fit, done with this pass */ + Ncolors[j]++; /* OK, apply the increment */ + total_colors = (int) temp; + changed = TRUE; + } + } while (changed); + + return total_colors; +} + + +LOCAL(int) +output_value (j_decompress_ptr cinfo, int ci, int j, int maxj) +/* Return j'th output value, where j will range from 0 to maxj */ +/* The output values must fall in 0..MAXJSAMPLE in increasing order */ +{ + /* We always provide values 0 and MAXJSAMPLE for each component; + * any additional values are equally spaced between these limits. + * (Forcing the upper and lower values to the limits ensures that + * dithering can't produce a color outside the selected gamut.) + */ + return (int) (((INT32) j * MAXJSAMPLE + maxj/2) / maxj); +} + + +LOCAL(int) +largest_input_value (j_decompress_ptr cinfo, int ci, int j, int maxj) +/* Return largest input value that should map to j'th output value */ +/* Must have largest(j=0) >= 0, and largest(j=maxj) >= MAXJSAMPLE */ +{ + /* Breakpoints are halfway between values returned by output_value */ + return (int) (((INT32) (2*j + 1) * MAXJSAMPLE + maxj) / (2*maxj)); +} + + +/* + * Create the colormap. + */ + +LOCAL(void) +create_colormap (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + JSAMPARRAY colormap; /* Created colormap */ + int total_colors; /* Number of distinct output colors */ + int i,j,k, nci, blksize, blkdist, ptr, val; + + /* Select number of colors for each component */ + total_colors = select_ncolors(cinfo, cquantize->Ncolors); + + /* Report selected color counts */ + if (cinfo->out_color_components == 3) + TRACEMS4(cinfo, 1, JTRC_QUANT_3_NCOLORS, + total_colors, cquantize->Ncolors[0], + cquantize->Ncolors[1], cquantize->Ncolors[2]); + else + TRACEMS1(cinfo, 1, JTRC_QUANT_NCOLORS, total_colors); + + /* Allocate and fill in the colormap. */ + /* The colors are ordered in the map in standard row-major order, */ + /* i.e. rightmost (highest-indexed) color changes most rapidly. */ + + colormap = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) total_colors, (JDIMENSION) cinfo->out_color_components); + + /* blksize is number of adjacent repeated entries for a component */ + /* blkdist is distance between groups of identical entries for a component */ + blkdist = total_colors; + + for (i = 0; i < cinfo->out_color_components; i++) { + /* fill in colormap entries for i'th color component */ + nci = cquantize->Ncolors[i]; /* # of distinct values for this color */ + blksize = blkdist / nci; + for (j = 0; j < nci; j++) { + /* Compute j'th output value (out of nci) for component */ + val = output_value(cinfo, i, j, nci-1); + /* Fill in all colormap entries that have this value of this component */ + for (ptr = j * blksize; ptr < total_colors; ptr += blkdist) { + /* fill in blksize entries beginning at ptr */ + for (k = 0; k < blksize; k++) + colormap[i][ptr+k] = (JSAMPLE) val; + } + } + blkdist = blksize; /* blksize of this color is blkdist of next */ + } + + /* Save the colormap in private storage, + * where it will survive color quantization mode changes. + */ + cquantize->sv_colormap = colormap; + cquantize->sv_actual = total_colors; +} + + +/* + * Create the color index table. + */ + +LOCAL(void) +create_colorindex (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + JSAMPROW indexptr; + int i,j,k, nci, blksize, val, pad; + + /* For ordered dither, we pad the color index tables by MAXJSAMPLE in + * each direction (input index values can be -MAXJSAMPLE .. 2*MAXJSAMPLE). + * This is not necessary in the other dithering modes. However, we + * flag whether it was done in case user changes dithering mode. + */ + if (cinfo->dither_mode == JDITHER_ORDERED) { + pad = MAXJSAMPLE*2; + cquantize->is_padded = TRUE; + } else { + pad = 0; + cquantize->is_padded = FALSE; + } + + cquantize->colorindex = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) (MAXJSAMPLE+1 + pad), + (JDIMENSION) cinfo->out_color_components); + + /* blksize is number of adjacent repeated entries for a component */ + blksize = cquantize->sv_actual; + + for (i = 0; i < cinfo->out_color_components; i++) { + /* fill in colorindex entries for i'th color component */ + nci = cquantize->Ncolors[i]; /* # of distinct values for this color */ + blksize = blksize / nci; + + /* adjust colorindex pointers to provide padding at negative indexes. */ + if (pad) + cquantize->colorindex[i] += MAXJSAMPLE; + + /* in loop, val = index of current output value, */ + /* and k = largest j that maps to current val */ + indexptr = cquantize->colorindex[i]; + val = 0; + k = largest_input_value(cinfo, i, 0, nci-1); + for (j = 0; j <= MAXJSAMPLE; j++) { + while (j > k) /* advance val if past boundary */ + k = largest_input_value(cinfo, i, ++val, nci-1); + /* premultiply so that no multiplication needed in main processing */ + indexptr[j] = (JSAMPLE) (val * blksize); + } + /* Pad at both ends if necessary */ + if (pad) + for (j = 1; j <= MAXJSAMPLE; j++) { + indexptr[-j] = indexptr[0]; + indexptr[MAXJSAMPLE+j] = indexptr[MAXJSAMPLE]; + } + } +} + + +/* + * Create an ordered-dither array for a component having ncolors + * distinct output values. + */ + +LOCAL(ODITHER_MATRIX_PTR) +make_odither_array (j_decompress_ptr cinfo, int ncolors) +{ + ODITHER_MATRIX_PTR odither; + int j,k; + INT32 num,den; + + odither = (ODITHER_MATRIX_PTR) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(ODITHER_MATRIX)); + /* The inter-value distance for this color is MAXJSAMPLE/(ncolors-1). + * Hence the dither value for the matrix cell with fill order f + * (f=0..N-1) should be (N-1-2*f)/(2*N) * MAXJSAMPLE/(ncolors-1). + * On 16-bit-int machine, be careful to avoid overflow. + */ + den = 2 * ODITHER_CELLS * ((INT32) (ncolors - 1)); + for (j = 0; j < ODITHER_SIZE; j++) { + for (k = 0; k < ODITHER_SIZE; k++) { + num = ((INT32) (ODITHER_CELLS-1 - 2*((int)base_dither_matrix[j][k]))) + * MAXJSAMPLE; + /* Ensure round towards zero despite C's lack of consistency + * about rounding negative values in integer division... + */ + odither[j][k] = (int) (num<0 ? -((-num)/den) : num/den); + } + } + return odither; +} + + +/* + * Create the ordered-dither tables. + * Components having the same number of representative colors may + * share a dither table. + */ + +LOCAL(void) +create_odither_tables (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + ODITHER_MATRIX_PTR odither; + int i, j, nci; + + for (i = 0; i < cinfo->out_color_components; i++) { + nci = cquantize->Ncolors[i]; /* # of distinct values for this color */ + odither = NULL; /* search for matching prior component */ + for (j = 0; j < i; j++) { + if (nci == cquantize->Ncolors[j]) { + odither = cquantize->odither[j]; + break; + } + } + if (odither == NULL) /* need a new table? */ + odither = make_odither_array(cinfo, nci); + cquantize->odither[i] = odither; + } +} + + +/* + * Map some rows of pixels to the output colormapped representation. + */ + +METHODDEF(void) +color_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) +/* General case, no dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + JSAMPARRAY colorindex = cquantize->colorindex; + register int pixcode, ci; + register JSAMPROW ptrin, ptrout; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + register int nc = cinfo->out_color_components; + + for (row = 0; row < num_rows; row++) { + ptrin = input_buf[row]; + ptrout = output_buf[row]; + for (col = width; col > 0; col--) { + pixcode = 0; + for (ci = 0; ci < nc; ci++) { + pixcode += GETJSAMPLE(colorindex[ci][GETJSAMPLE(*ptrin++)]); + } + *ptrout++ = (JSAMPLE) pixcode; + } + } +} + + +METHODDEF(void) +color_quantize3 (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) +/* Fast path for out_color_components==3, no dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + register int pixcode; + register JSAMPROW ptrin, ptrout; + JSAMPROW colorindex0 = cquantize->colorindex[0]; + JSAMPROW colorindex1 = cquantize->colorindex[1]; + JSAMPROW colorindex2 = cquantize->colorindex[2]; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + + for (row = 0; row < num_rows; row++) { + ptrin = input_buf[row]; + ptrout = output_buf[row]; + for (col = width; col > 0; col--) { + pixcode = GETJSAMPLE(colorindex0[GETJSAMPLE(*ptrin++)]); + pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*ptrin++)]); + pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*ptrin++)]); + *ptrout++ = (JSAMPLE) pixcode; + } + } +} + + +METHODDEF(void) +quantize_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) +/* General case, with ordered dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + register JSAMPROW input_ptr; + register JSAMPROW output_ptr; + JSAMPROW colorindex_ci; + int * dither; /* points to active row of dither matrix */ + int row_index, col_index; /* current indexes into dither matrix */ + int nc = cinfo->out_color_components; + int ci; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + + for (row = 0; row < num_rows; row++) { + /* Initialize output values to 0 so can process components separately */ + jzero_far((void FAR *) output_buf[row], + (size_t) (width * SIZEOF(JSAMPLE))); + row_index = cquantize->row_index; + for (ci = 0; ci < nc; ci++) { + input_ptr = input_buf[row] + ci; + output_ptr = output_buf[row]; + colorindex_ci = cquantize->colorindex[ci]; + dither = cquantize->odither[ci][row_index]; + col_index = 0; + + for (col = width; col > 0; col--) { + /* Form pixel value + dither, range-limit to 0..MAXJSAMPLE, + * select output value, accumulate into output code for this pixel. + * Range-limiting need not be done explicitly, as we have extended + * the colorindex table to produce the right answers for out-of-range + * inputs. The maximum dither is +- MAXJSAMPLE; this sets the + * required amount of padding. + */ + *output_ptr += colorindex_ci[GETJSAMPLE(*input_ptr)+dither[col_index]]; + input_ptr += nc; + output_ptr++; + col_index = (col_index + 1) & ODITHER_MASK; + } + } + /* Advance row index for next row */ + row_index = (row_index + 1) & ODITHER_MASK; + cquantize->row_index = row_index; + } +} + + +METHODDEF(void) +quantize3_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) +/* Fast path for out_color_components==3, with ordered dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + register int pixcode; + register JSAMPROW input_ptr; + register JSAMPROW output_ptr; + JSAMPROW colorindex0 = cquantize->colorindex[0]; + JSAMPROW colorindex1 = cquantize->colorindex[1]; + JSAMPROW colorindex2 = cquantize->colorindex[2]; + int * dither0; /* points to active row of dither matrix */ + int * dither1; + int * dither2; + int row_index, col_index; /* current indexes into dither matrix */ + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + + for (row = 0; row < num_rows; row++) { + row_index = cquantize->row_index; + input_ptr = input_buf[row]; + output_ptr = output_buf[row]; + dither0 = cquantize->odither[0][row_index]; + dither1 = cquantize->odither[1][row_index]; + dither2 = cquantize->odither[2][row_index]; + col_index = 0; + + for (col = width; col > 0; col--) { + pixcode = GETJSAMPLE(colorindex0[GETJSAMPLE(*input_ptr++) + + dither0[col_index]]); + pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*input_ptr++) + + dither1[col_index]]); + pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*input_ptr++) + + dither2[col_index]]); + *output_ptr++ = (JSAMPLE) pixcode; + col_index = (col_index + 1) & ODITHER_MASK; + } + row_index = (row_index + 1) & ODITHER_MASK; + cquantize->row_index = row_index; + } +} + + +METHODDEF(void) +quantize_fs_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) +/* General case, with Floyd-Steinberg dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + register LOCFSERROR cur; /* current error or pixel value */ + LOCFSERROR belowerr; /* error for pixel below cur */ + LOCFSERROR bpreverr; /* error for below/prev col */ + LOCFSERROR bnexterr; /* error for below/next col */ + LOCFSERROR delta; + register FSERRPTR errorptr; /* => fserrors[] at column before current */ + register JSAMPROW input_ptr; + register JSAMPROW output_ptr; + JSAMPROW colorindex_ci; + JSAMPROW colormap_ci; + int pixcode; + int nc = cinfo->out_color_components; + int dir; /* 1 for left-to-right, -1 for right-to-left */ + int dirnc; /* dir * nc */ + int ci; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + JSAMPLE *range_limit = cinfo->sample_range_limit; + SHIFT_TEMPS + + for (row = 0; row < num_rows; row++) { + /* Initialize output values to 0 so can process components separately */ + jzero_far((void FAR *) output_buf[row], + (size_t) (width * SIZEOF(JSAMPLE))); + for (ci = 0; ci < nc; ci++) { + input_ptr = input_buf[row] + ci; + output_ptr = output_buf[row]; + if (cquantize->on_odd_row) { + /* work right to left in this row */ + input_ptr += (width-1) * nc; /* so point to rightmost pixel */ + output_ptr += width-1; + dir = -1; + dirnc = -nc; + errorptr = cquantize->fserrors[ci] + (width+1); /* => entry after last column */ + } else { + /* work left to right in this row */ + dir = 1; + dirnc = nc; + errorptr = cquantize->fserrors[ci]; /* => entry before first column */ + } + colorindex_ci = cquantize->colorindex[ci]; + colormap_ci = cquantize->sv_colormap[ci]; + /* Preset error values: no error propagated to first pixel from left */ + cur = 0; + /* and no error propagated to row below yet */ + belowerr = bpreverr = 0; + + for (col = width; col > 0; col--) { + /* cur holds the error propagated from the previous pixel on the + * current line. Add the error propagated from the previous line + * to form the complete error correction term for this pixel, and + * round the error term (which is expressed * 16) to an integer. + * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct + * for either sign of the error value. + * Note: errorptr points to *previous* column's array entry. + */ + cur = RIGHT_SHIFT(cur + errorptr[dir] + 8, 4); + /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE. + * The maximum error is +- MAXJSAMPLE; this sets the required size + * of the range_limit array. + */ + cur += GETJSAMPLE(*input_ptr); + cur = GETJSAMPLE(range_limit[cur]); + /* Select output value, accumulate into output code for this pixel */ + pixcode = GETJSAMPLE(colorindex_ci[cur]); + *output_ptr += (JSAMPLE) pixcode; + /* Compute actual representation error at this pixel */ + /* Note: we can do this even though we don't have the final */ + /* pixel code, because the colormap is orthogonal. */ + cur -= GETJSAMPLE(colormap_ci[pixcode]); + /* Compute error fractions to be propagated to adjacent pixels. + * Add these into the running sums, and simultaneously shift the + * next-line error sums left by 1 column. + */ + bnexterr = cur; + delta = cur * 2; + cur += delta; /* form error * 3 */ + errorptr[0] = (FSERROR) (bpreverr + cur); + cur += delta; /* form error * 5 */ + bpreverr = belowerr + cur; + belowerr = bnexterr; + cur += delta; /* form error * 7 */ + /* At this point cur contains the 7/16 error value to be propagated + * to the next pixel on the current line, and all the errors for the + * next line have been shifted over. We are therefore ready to move on. + */ + input_ptr += dirnc; /* advance input ptr to next column */ + output_ptr += dir; /* advance output ptr to next column */ + errorptr += dir; /* advance errorptr to current column */ + } + /* Post-loop cleanup: we must unload the final error value into the + * final fserrors[] entry. Note we need not unload belowerr because + * it is for the dummy column before or after the actual array. + */ + errorptr[0] = (FSERROR) bpreverr; /* unload prev err into array */ + } + cquantize->on_odd_row = (cquantize->on_odd_row ? FALSE : TRUE); + } +} + + +/* + * Allocate workspace for Floyd-Steinberg errors. + */ + +LOCAL(void) +alloc_fs_workspace (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + size_t arraysize; + int i; + + arraysize = (size_t) ((cinfo->output_width + 2) * SIZEOF(FSERROR)); + for (i = 0; i < cinfo->out_color_components; i++) { + cquantize->fserrors[i] = (FSERRPTR) + (*cinfo->mem->alloc_large)((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize); + } +} + + +/* + * Initialize for one-pass color quantization. + */ + +METHODDEF(void) +start_pass_1_quant (j_decompress_ptr cinfo, boolean is_pre_scan) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + size_t arraysize; + int i; + + /* Install my colormap. */ + cinfo->colormap = cquantize->sv_colormap; + cinfo->actual_number_of_colors = cquantize->sv_actual; + + /* Initialize for desired dithering mode. */ + switch (cinfo->dither_mode) { + case JDITHER_NONE: + if (cinfo->out_color_components == 3) + cquantize->pub.color_quantize = color_quantize3; + else + cquantize->pub.color_quantize = color_quantize; + break; + case JDITHER_ORDERED: + if (cinfo->out_color_components == 3) + cquantize->pub.color_quantize = quantize3_ord_dither; + else + cquantize->pub.color_quantize = quantize_ord_dither; + cquantize->row_index = 0; /* initialize state for ordered dither */ + /* If user changed to ordered dither from another mode, + * we must recreate the color index table with padding. + * This will cost extra space, but probably isn't very likely. + */ + if (! cquantize->is_padded) + create_colorindex(cinfo); + /* Create ordered-dither tables if we didn't already. */ + if (cquantize->odither[0] == NULL) + create_odither_tables(cinfo); + break; + case JDITHER_FS: + cquantize->pub.color_quantize = quantize_fs_dither; + cquantize->on_odd_row = FALSE; /* initialize state for F-S dither */ + /* Allocate Floyd-Steinberg workspace if didn't already. */ + if (cquantize->fserrors[0] == NULL) + alloc_fs_workspace(cinfo); + /* Initialize the propagated errors to zero. */ + arraysize = (size_t) ((cinfo->output_width + 2) * SIZEOF(FSERROR)); + for (i = 0; i < cinfo->out_color_components; i++) + jzero_far((void FAR *) cquantize->fserrors[i], arraysize); + break; + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; + } +} + + +/* + * Finish up at the end of the pass. + */ + +METHODDEF(void) +finish_pass_1_quant (j_decompress_ptr cinfo) +{ + /* no work in 1-pass case */ +} + + +/* + * Switch to a new external colormap between output passes. + * Shouldn't get to this module! + */ + +METHODDEF(void) +new_color_map_1_quant (j_decompress_ptr cinfo) +{ + ERREXIT(cinfo, JERR_MODE_CHANGE); +} + + +/* + * Module initialization routine for 1-pass color quantization. + */ + +GLOBAL(void) +jinit_1pass_quantizer (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize; + + cquantize = (my_cquantize_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_cquantizer)); + cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize; + cquantize->pub.start_pass = start_pass_1_quant; + cquantize->pub.finish_pass = finish_pass_1_quant; + cquantize->pub.new_color_map = new_color_map_1_quant; + cquantize->fserrors[0] = NULL; /* Flag FS workspace not allocated */ + cquantize->odither[0] = NULL; /* Also flag odither arrays not allocated */ + + /* Make sure my internal arrays won't overflow */ + if (cinfo->out_color_components > MAX_Q_COMPS) + ERREXIT1(cinfo, JERR_QUANT_COMPONENTS, MAX_Q_COMPS); + /* Make sure colormap indexes can be represented by JSAMPLEs */ + if (cinfo->desired_number_of_colors > (MAXJSAMPLE+1)) + ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXJSAMPLE+1); + + /* Create the colormap and color index table. */ + create_colormap(cinfo); + create_colorindex(cinfo); + + /* Allocate Floyd-Steinberg workspace now if requested. + * We do this now since it is FAR storage and may affect the memory + * manager's space calculations. If the user changes to FS dither + * mode in a later pass, we will allocate the space then, and will + * possibly overrun the max_memory_to_use setting. + */ + if (cinfo->dither_mode == JDITHER_FS) + alloc_fs_workspace(cinfo); +} + +#endif /* QUANT_1PASS_SUPPORTED */ diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jquant2.c b/lc-continuity/mk4/modimage/jpeg-6b/jquant2.c new file mode 100644 index 0000000000000000000000000000000000000000..af601e334b244f0a356e78826463b71e0848fe57 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jquant2.c @@ -0,0 +1,1310 @@ +/* + * jquant2.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains 2-pass color quantization (color mapping) routines. + * These routines provide selection of a custom color map for an image, + * followed by mapping of the image to that color map, with optional + * Floyd-Steinberg dithering. + * It is also possible to use just the second pass to map to an arbitrary + * externally-given color map. + * + * Note: ordered dithering is not supported, since there isn't any fast + * way to compute intercolor distances; it's unclear that ordered dither's + * fundamental assumptions even hold with an irregularly spaced color map. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + +#ifdef QUANT_2PASS_SUPPORTED + + +/* + * This module implements the well-known Heckbert paradigm for color + * quantization. Most of the ideas used here can be traced back to + * Heckbert's seminal paper + * Heckbert, Paul. "Color Image Quantization for Frame Buffer Display", + * Proc. SIGGRAPH '82, Computer Graphics v.16 #3 (July 1982), pp 297-304. + * + * In the first pass over the image, we accumulate a histogram showing the + * usage count of each possible color. To keep the histogram to a reasonable + * size, we reduce the precision of the input; typical practice is to retain + * 5 or 6 bits per color, so that 8 or 4 different input values are counted + * in the same histogram cell. + * + * Next, the color-selection step begins with a box representing the whole + * color space, and repeatedly splits the "largest" remaining box until we + * have as many boxes as desired colors. Then the mean color in each + * remaining box becomes one of the possible output colors. + * + * The second pass over the image maps each input pixel to the closest output + * color (optionally after applying a Floyd-Steinberg dithering correction). + * This mapping is logically trivial, but making it go fast enough requires + * considerable care. + * + * Heckbert-style quantizers vary a good deal in their policies for choosing + * the "largest" box and deciding where to cut it. The particular policies + * used here have proved out well in experimental comparisons, but better ones + * may yet be found. + * + * In earlier versions of the IJG code, this module quantized in YCbCr color + * space, processing the raw upsampled data without a color conversion step. + * This allowed the color conversion math to be done only once per colormap + * entry, not once per pixel. However, that optimization precluded other + * useful optimizations (such as merging color conversion with upsampling) + * and it also interfered with desired capabilities such as quantizing to an + * externally-supplied colormap. We have therefore abandoned that approach. + * The present code works in the post-conversion color space, typically RGB. + * + * To improve the visual quality of the results, we actually work in scaled + * RGB space, giving G distances more weight than R, and R in turn more than + * B. To do everything in integer math, we must use integer scale factors. + * The 2/3/1 scale factors used here correspond loosely to the relative + * weights of the colors in the NTSC grayscale equation. + * If you want to use this code to quantize a non-RGB color space, you'll + * probably need to change these scale factors. + */ + +#define R_SCALE 2 /* scale R distances by this much */ +#define G_SCALE 3 /* scale G distances by this much */ +#define B_SCALE 1 /* and B by this much */ + +/* Relabel R/G/B as components 0/1/2, respecting the RGB ordering defined + * in jmorecfg.h. As the code stands, it will do the right thing for R,G,B + * and B,G,R orders. If you define some other weird order in jmorecfg.h, + * you'll get compile errors until you extend this logic. In that case + * you'll probably want to tweak the histogram sizes too. + */ + +#if RGB_RED == 0 +#define C0_SCALE R_SCALE +#endif +#if RGB_BLUE == 0 +#define C0_SCALE B_SCALE +#endif +#if RGB_GREEN == 1 +#define C1_SCALE G_SCALE +#endif +#if RGB_RED == 2 +#define C2_SCALE R_SCALE +#endif +#if RGB_BLUE == 2 +#define C2_SCALE B_SCALE +#endif + + +/* + * First we have the histogram data structure and routines for creating it. + * + * The number of bits of precision can be adjusted by changing these symbols. + * We recommend keeping 6 bits for G and 5 each for R and B. + * If you have plenty of memory and cycles, 6 bits all around gives marginally + * better results; if you are short of memory, 5 bits all around will save + * some space but degrade the results. + * To maintain a fully accurate histogram, we'd need to allocate a "long" + * (preferably unsigned long) for each cell. In practice this is overkill; + * we can get by with 16 bits per cell. Few of the cell counts will overflow, + * and clamping those that do overflow to the maximum value will give close- + * enough results. This reduces the recommended histogram size from 256Kb + * to 128Kb, which is a useful savings on PC-class machines. + * (In the second pass the histogram space is re-used for pixel mapping data; + * in that capacity, each cell must be able to store zero to the number of + * desired colors. 16 bits/cell is plenty for that too.) + * Since the JPEG code is intended to run in small memory model on 80x86 + * machines, we can't just allocate the histogram in one chunk. Instead + * of a true 3-D array, we use a row of pointers to 2-D arrays. Each + * pointer corresponds to a C0 value (typically 2^5 = 32 pointers) and + * each 2-D array has 2^6*2^5 = 2048 or 2^6*2^6 = 4096 entries. Note that + * on 80x86 machines, the pointer row is in near memory but the actual + * arrays are in far memory (same arrangement as we use for image arrays). + */ + +#define MAXNUMCOLORS (MAXJSAMPLE+1) /* maximum size of colormap */ + +/* These will do the right thing for either R,G,B or B,G,R color order, + * but you may not like the results for other color orders. + */ +#define HIST_C0_BITS 5 /* bits of precision in R/B histogram */ +#define HIST_C1_BITS 6 /* bits of precision in G histogram */ +#define HIST_C2_BITS 5 /* bits of precision in B/R histogram */ + +/* Number of elements along histogram axes. */ +#define HIST_C0_ELEMS (1<cquantize; + register JSAMPROW ptr; + register histptr histp; + register hist3d histogram = cquantize->histogram; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + + for (row = 0; row < num_rows; row++) { + ptr = input_buf[row]; + for (col = width; col > 0; col--) { + /* get pixel value and index into the histogram */ + histp = & histogram[GETJSAMPLE(ptr[0]) >> C0_SHIFT] + [GETJSAMPLE(ptr[1]) >> C1_SHIFT] + [GETJSAMPLE(ptr[2]) >> C2_SHIFT]; + /* increment, check for overflow and undo increment if so. */ + if (++(*histp) <= 0) + (*histp)--; + ptr += 3; + } + } +} + + +/* + * Next we have the really interesting routines: selection of a colormap + * given the completed histogram. + * These routines work with a list of "boxes", each representing a rectangular + * subset of the input color space (to histogram precision). + */ + +typedef struct { + /* The bounds of the box (inclusive); expressed as histogram indexes */ + int c0min, c0max; + int c1min, c1max; + int c2min, c2max; + /* The volume (actually 2-norm) of the box */ + INT32 volume; + /* The number of nonzero histogram cells within this box */ + long colorcount; +} box; + +typedef box * boxptr; + + +LOCAL(boxptr) +find_biggest_color_pop (boxptr boxlist, int numboxes) +/* Find the splittable box with the largest color population */ +/* Returns NULL if no splittable boxes remain */ +{ + register boxptr boxp; + register int i; + register long maxc = 0; + boxptr which = NULL; + + for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) { + if (boxp->colorcount > maxc && boxp->volume > 0) { + which = boxp; + maxc = boxp->colorcount; + } + } + return which; +} + + +LOCAL(boxptr) +find_biggest_volume (boxptr boxlist, int numboxes) +/* Find the splittable box with the largest (scaled) volume */ +/* Returns NULL if no splittable boxes remain */ +{ + register boxptr boxp; + register int i; + register INT32 maxv = 0; + boxptr which = NULL; + + for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) { + if (boxp->volume > maxv) { + which = boxp; + maxv = boxp->volume; + } + } + return which; +} + + +LOCAL(void) +update_box (j_decompress_ptr cinfo, boxptr boxp) +/* Shrink the min/max bounds of a box to enclose only nonzero elements, */ +/* and recompute its volume and population */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + histptr histp; + int c0,c1,c2; + int c0min,c0max,c1min,c1max,c2min,c2max; + INT32 dist0,dist1,dist2; + long ccount; + + c0min = boxp->c0min; c0max = boxp->c0max; + c1min = boxp->c1min; c1max = boxp->c1max; + c2min = boxp->c2min; c2max = boxp->c2max; + + if (c0max > c0min) + for (c0 = c0min; c0 <= c0max; c0++) + for (c1 = c1min; c1 <= c1max; c1++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c0min = c0min = c0; + goto have_c0min; + } + } + have_c0min: + if (c0max > c0min) + for (c0 = c0max; c0 >= c0min; c0--) + for (c1 = c1min; c1 <= c1max; c1++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c0max = c0max = c0; + goto have_c0max; + } + } + have_c0max: + if (c1max > c1min) + for (c1 = c1min; c1 <= c1max; c1++) + for (c0 = c0min; c0 <= c0max; c0++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c1min = c1min = c1; + goto have_c1min; + } + } + have_c1min: + if (c1max > c1min) + for (c1 = c1max; c1 >= c1min; c1--) + for (c0 = c0min; c0 <= c0max; c0++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c1max = c1max = c1; + goto have_c1max; + } + } + have_c1max: + if (c2max > c2min) + for (c2 = c2min; c2 <= c2max; c2++) + for (c0 = c0min; c0 <= c0max; c0++) { + histp = & histogram[c0][c1min][c2]; + for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS) + if (*histp != 0) { + boxp->c2min = c2min = c2; + goto have_c2min; + } + } + have_c2min: + if (c2max > c2min) + for (c2 = c2max; c2 >= c2min; c2--) + for (c0 = c0min; c0 <= c0max; c0++) { + histp = & histogram[c0][c1min][c2]; + for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS) + if (*histp != 0) { + boxp->c2max = c2max = c2; + goto have_c2max; + } + } + have_c2max: + + /* Update box volume. + * We use 2-norm rather than real volume here; this biases the method + * against making long narrow boxes, and it has the side benefit that + * a box is splittable iff norm > 0. + * Since the differences are expressed in histogram-cell units, + * we have to shift back to JSAMPLE units to get consistent distances; + * after which, we scale according to the selected distance scale factors. + */ + dist0 = ((c0max - c0min) << C0_SHIFT) * C0_SCALE; + dist1 = ((c1max - c1min) << C1_SHIFT) * C1_SCALE; + dist2 = ((c2max - c2min) << C2_SHIFT) * C2_SCALE; + boxp->volume = dist0*dist0 + dist1*dist1 + dist2*dist2; + + /* Now scan remaining volume of box and compute population */ + ccount = 0; + for (c0 = c0min; c0 <= c0max; c0++) + for (c1 = c1min; c1 <= c1max; c1++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++, histp++) + if (*histp != 0) { + ccount++; + } + } + boxp->colorcount = ccount; +} + + +LOCAL(int) +median_cut (j_decompress_ptr cinfo, boxptr boxlist, int numboxes, + int desired_colors) +/* Repeatedly select and split the largest box until we have enough boxes */ +{ + int n,lb; + int c0,c1,c2,cmax; + register boxptr b1,b2; + + while (numboxes < desired_colors) { + /* Select box to split. + * Current algorithm: by population for first half, then by volume. + */ + if (numboxes*2 <= desired_colors) { + b1 = find_biggest_color_pop(boxlist, numboxes); + } else { + b1 = find_biggest_volume(boxlist, numboxes); + } + if (b1 == NULL) /* no splittable boxes left! */ + break; + b2 = &boxlist[numboxes]; /* where new box will go */ + /* Copy the color bounds to the new box. */ + b2->c0max = b1->c0max; b2->c1max = b1->c1max; b2->c2max = b1->c2max; + b2->c0min = b1->c0min; b2->c1min = b1->c1min; b2->c2min = b1->c2min; + /* Choose which axis to split the box on. + * Current algorithm: longest scaled axis. + * See notes in update_box about scaling distances. + */ + c0 = ((b1->c0max - b1->c0min) << C0_SHIFT) * C0_SCALE; + c1 = ((b1->c1max - b1->c1min) << C1_SHIFT) * C1_SCALE; + c2 = ((b1->c2max - b1->c2min) << C2_SHIFT) * C2_SCALE; + /* We want to break any ties in favor of green, then red, blue last. + * This code does the right thing for R,G,B or B,G,R color orders only. + */ +#if RGB_RED == 0 + cmax = c1; n = 1; + if (c0 > cmax) { cmax = c0; n = 0; } + if (c2 > cmax) { n = 2; } +#else + cmax = c1; n = 1; + if (c2 > cmax) { cmax = c2; n = 2; } + if (c0 > cmax) { n = 0; } +#endif + /* Choose split point along selected axis, and update box bounds. + * Current algorithm: split at halfway point. + * (Since the box has been shrunk to minimum volume, + * any split will produce two nonempty subboxes.) + * Note that lb value is max for lower box, so must be < old max. + */ + switch (n) { + case 0: + lb = (b1->c0max + b1->c0min) / 2; + b1->c0max = lb; + b2->c0min = lb+1; + break; + case 1: + lb = (b1->c1max + b1->c1min) / 2; + b1->c1max = lb; + b2->c1min = lb+1; + break; + case 2: + lb = (b1->c2max + b1->c2min) / 2; + b1->c2max = lb; + b2->c2min = lb+1; + break; + } + /* Update stats for boxes */ + update_box(cinfo, b1); + update_box(cinfo, b2); + numboxes++; + } + return numboxes; +} + + +LOCAL(void) +compute_color (j_decompress_ptr cinfo, boxptr boxp, int icolor) +/* Compute representative color for a box, put it in colormap[icolor] */ +{ + /* Current algorithm: mean weighted by pixels (not colors) */ + /* Note it is important to get the rounding correct! */ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + histptr histp; + int c0,c1,c2; + int c0min,c0max,c1min,c1max,c2min,c2max; + long count; + long total = 0; + long c0total = 0; + long c1total = 0; + long c2total = 0; + + c0min = boxp->c0min; c0max = boxp->c0max; + c1min = boxp->c1min; c1max = boxp->c1max; + c2min = boxp->c2min; c2max = boxp->c2max; + + for (c0 = c0min; c0 <= c0max; c0++) + for (c1 = c1min; c1 <= c1max; c1++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) { + if ((count = *histp++) != 0) { + total += count; + c0total += ((c0 << C0_SHIFT) + ((1<>1)) * count; + c1total += ((c1 << C1_SHIFT) + ((1<>1)) * count; + c2total += ((c2 << C2_SHIFT) + ((1<>1)) * count; + } + } + } + + cinfo->colormap[0][icolor] = (JSAMPLE) ((c0total + (total>>1)) / total); + cinfo->colormap[1][icolor] = (JSAMPLE) ((c1total + (total>>1)) / total); + cinfo->colormap[2][icolor] = (JSAMPLE) ((c2total + (total>>1)) / total); +} + + +LOCAL(void) +select_colors (j_decompress_ptr cinfo, int desired_colors) +/* Master routine for color selection */ +{ + boxptr boxlist; + int numboxes; + int i; + + /* Allocate workspace for box list */ + boxlist = (boxptr) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, desired_colors * SIZEOF(box)); + /* Initialize one box containing whole space */ + numboxes = 1; + boxlist[0].c0min = 0; + boxlist[0].c0max = MAXJSAMPLE >> C0_SHIFT; + boxlist[0].c1min = 0; + boxlist[0].c1max = MAXJSAMPLE >> C1_SHIFT; + boxlist[0].c2min = 0; + boxlist[0].c2max = MAXJSAMPLE >> C2_SHIFT; + /* Shrink it to actually-used volume and set its statistics */ + update_box(cinfo, & boxlist[0]); + /* Perform median-cut to produce final box list */ + numboxes = median_cut(cinfo, boxlist, numboxes, desired_colors); + /* Compute the representative color for each box, fill colormap */ + for (i = 0; i < numboxes; i++) + compute_color(cinfo, & boxlist[i], i); + cinfo->actual_number_of_colors = numboxes; + TRACEMS1(cinfo, 1, JTRC_QUANT_SELECTED, numboxes); +} + + +/* + * These routines are concerned with the time-critical task of mapping input + * colors to the nearest color in the selected colormap. + * + * We re-use the histogram space as an "inverse color map", essentially a + * cache for the results of nearest-color searches. All colors within a + * histogram cell will be mapped to the same colormap entry, namely the one + * closest to the cell's center. This may not be quite the closest entry to + * the actual input color, but it's almost as good. A zero in the cache + * indicates we haven't found the nearest color for that cell yet; the array + * is cleared to zeroes before starting the mapping pass. When we find the + * nearest color for a cell, its colormap index plus one is recorded in the + * cache for future use. The pass2 scanning routines call fill_inverse_cmap + * when they need to use an unfilled entry in the cache. + * + * Our method of efficiently finding nearest colors is based on the "locally + * sorted search" idea described by Heckbert and on the incremental distance + * calculation described by Spencer W. Thomas in chapter III.1 of Graphics + * Gems II (James Arvo, ed. Academic Press, 1991). Thomas points out that + * the distances from a given colormap entry to each cell of the histogram can + * be computed quickly using an incremental method: the differences between + * distances to adjacent cells themselves differ by a constant. This allows a + * fairly fast implementation of the "brute force" approach of computing the + * distance from every colormap entry to every histogram cell. Unfortunately, + * it needs a work array to hold the best-distance-so-far for each histogram + * cell (because the inner loop has to be over cells, not colormap entries). + * The work array elements have to be INT32s, so the work array would need + * 256Kb at our recommended precision. This is not feasible in DOS machines. + * + * To get around these problems, we apply Thomas' method to compute the + * nearest colors for only the cells within a small subbox of the histogram. + * The work array need be only as big as the subbox, so the memory usage + * problem is solved. Furthermore, we need not fill subboxes that are never + * referenced in pass2; many images use only part of the color gamut, so a + * fair amount of work is saved. An additional advantage of this + * approach is that we can apply Heckbert's locality criterion to quickly + * eliminate colormap entries that are far away from the subbox; typically + * three-fourths of the colormap entries are rejected by Heckbert's criterion, + * and we need not compute their distances to individual cells in the subbox. + * The speed of this approach is heavily influenced by the subbox size: too + * small means too much overhead, too big loses because Heckbert's criterion + * can't eliminate as many colormap entries. Empirically the best subbox + * size seems to be about 1/512th of the histogram (1/8th in each direction). + * + * Thomas' article also describes a refined method which is asymptotically + * faster than the brute-force method, but it is also far more complex and + * cannot efficiently be applied to small subboxes. It is therefore not + * useful for programs intended to be portable to DOS machines. On machines + * with plenty of memory, filling the whole histogram in one shot with Thomas' + * refined method might be faster than the present code --- but then again, + * it might not be any faster, and it's certainly more complicated. + */ + + +/* log2(histogram cells in update box) for each axis; this can be adjusted */ +#define BOX_C0_LOG (HIST_C0_BITS-3) +#define BOX_C1_LOG (HIST_C1_BITS-3) +#define BOX_C2_LOG (HIST_C2_BITS-3) + +#define BOX_C0_ELEMS (1<actual_number_of_colors; + int maxc0, maxc1, maxc2; + int centerc0, centerc1, centerc2; + int i, x, ncolors; + INT32 minmaxdist, min_dist, max_dist, tdist; + INT32 mindist[MAXNUMCOLORS]; /* min distance to colormap entry i */ + + /* Compute true coordinates of update box's upper corner and center. + * Actually we compute the coordinates of the center of the upper-corner + * histogram cell, which are the upper bounds of the volume we care about. + * Note that since ">>" rounds down, the "center" values may be closer to + * min than to max; hence comparisons to them must be "<=", not "<". + */ + maxc0 = minc0 + ((1 << BOX_C0_SHIFT) - (1 << C0_SHIFT)); + centerc0 = (minc0 + maxc0) >> 1; + maxc1 = minc1 + ((1 << BOX_C1_SHIFT) - (1 << C1_SHIFT)); + centerc1 = (minc1 + maxc1) >> 1; + maxc2 = minc2 + ((1 << BOX_C2_SHIFT) - (1 << C2_SHIFT)); + centerc2 = (minc2 + maxc2) >> 1; + + /* For each color in colormap, find: + * 1. its minimum squared-distance to any point in the update box + * (zero if color is within update box); + * 2. its maximum squared-distance to any point in the update box. + * Both of these can be found by considering only the corners of the box. + * We save the minimum distance for each color in mindist[]; + * only the smallest maximum distance is of interest. + */ + minmaxdist = 0x7FFFFFFFL; + + for (i = 0; i < numcolors; i++) { + /* We compute the squared-c0-distance term, then add in the other two. */ + x = GETJSAMPLE(cinfo->colormap[0][i]); + if (x < minc0) { + tdist = (x - minc0) * C0_SCALE; + min_dist = tdist*tdist; + tdist = (x - maxc0) * C0_SCALE; + max_dist = tdist*tdist; + } else if (x > maxc0) { + tdist = (x - maxc0) * C0_SCALE; + min_dist = tdist*tdist; + tdist = (x - minc0) * C0_SCALE; + max_dist = tdist*tdist; + } else { + /* within cell range so no contribution to min_dist */ + min_dist = 0; + if (x <= centerc0) { + tdist = (x - maxc0) * C0_SCALE; + max_dist = tdist*tdist; + } else { + tdist = (x - minc0) * C0_SCALE; + max_dist = tdist*tdist; + } + } + + x = GETJSAMPLE(cinfo->colormap[1][i]); + if (x < minc1) { + tdist = (x - minc1) * C1_SCALE; + min_dist += tdist*tdist; + tdist = (x - maxc1) * C1_SCALE; + max_dist += tdist*tdist; + } else if (x > maxc1) { + tdist = (x - maxc1) * C1_SCALE; + min_dist += tdist*tdist; + tdist = (x - minc1) * C1_SCALE; + max_dist += tdist*tdist; + } else { + /* within cell range so no contribution to min_dist */ + if (x <= centerc1) { + tdist = (x - maxc1) * C1_SCALE; + max_dist += tdist*tdist; + } else { + tdist = (x - minc1) * C1_SCALE; + max_dist += tdist*tdist; + } + } + + x = GETJSAMPLE(cinfo->colormap[2][i]); + if (x < minc2) { + tdist = (x - minc2) * C2_SCALE; + min_dist += tdist*tdist; + tdist = (x - maxc2) * C2_SCALE; + max_dist += tdist*tdist; + } else if (x > maxc2) { + tdist = (x - maxc2) * C2_SCALE; + min_dist += tdist*tdist; + tdist = (x - minc2) * C2_SCALE; + max_dist += tdist*tdist; + } else { + /* within cell range so no contribution to min_dist */ + if (x <= centerc2) { + tdist = (x - maxc2) * C2_SCALE; + max_dist += tdist*tdist; + } else { + tdist = (x - minc2) * C2_SCALE; + max_dist += tdist*tdist; + } + } + + mindist[i] = min_dist; /* save away the results */ + if (max_dist < minmaxdist) + minmaxdist = max_dist; + } + + /* Now we know that no cell in the update box is more than minmaxdist + * away from some colormap entry. Therefore, only colors that are + * within minmaxdist of some part of the box need be considered. + */ + ncolors = 0; + for (i = 0; i < numcolors; i++) { + if (mindist[i] <= minmaxdist) + colorlist[ncolors++] = (JSAMPLE) i; + } + return ncolors; +} + + +LOCAL(void) +find_best_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2, + int numcolors, JSAMPLE colorlist[], JSAMPLE bestcolor[]) +/* Find the closest colormap entry for each cell in the update box, + * given the list of candidate colors prepared by find_nearby_colors. + * Return the indexes of the closest entries in the bestcolor[] array. + * This routine uses Thomas' incremental distance calculation method to + * find the distance from a colormap entry to successive cells in the box. + */ +{ + int ic0, ic1, ic2; + int i, icolor; + register INT32 * bptr; /* pointer into bestdist[] array */ + JSAMPLE * cptr; /* pointer into bestcolor[] array */ + INT32 dist0, dist1; /* initial distance values */ + register INT32 dist2; /* current distance in inner loop */ + INT32 xx0, xx1; /* distance increments */ + register INT32 xx2; + INT32 inc0, inc1, inc2; /* initial values for increments */ + /* This array holds the distance to the nearest-so-far color for each cell */ + INT32 bestdist[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS]; + + /* Initialize best-distance for each cell of the update box */ + bptr = bestdist; + for (i = BOX_C0_ELEMS*BOX_C1_ELEMS*BOX_C2_ELEMS-1; i >= 0; i--) + *bptr++ = 0x7FFFFFFFL; + + /* For each color selected by find_nearby_colors, + * compute its distance to the center of each cell in the box. + * If that's less than best-so-far, update best distance and color number. + */ + + /* Nominal steps between cell centers ("x" in Thomas article) */ +#define STEP_C0 ((1 << C0_SHIFT) * C0_SCALE) +#define STEP_C1 ((1 << C1_SHIFT) * C1_SCALE) +#define STEP_C2 ((1 << C2_SHIFT) * C2_SCALE) + + for (i = 0; i < numcolors; i++) { + icolor = GETJSAMPLE(colorlist[i]); + /* Compute (square of) distance from minc0/c1/c2 to this color */ + inc0 = (minc0 - GETJSAMPLE(cinfo->colormap[0][icolor])) * C0_SCALE; + dist0 = inc0*inc0; + inc1 = (minc1 - GETJSAMPLE(cinfo->colormap[1][icolor])) * C1_SCALE; + dist0 += inc1*inc1; + inc2 = (minc2 - GETJSAMPLE(cinfo->colormap[2][icolor])) * C2_SCALE; + dist0 += inc2*inc2; + /* Form the initial difference increments */ + inc0 = inc0 * (2 * STEP_C0) + STEP_C0 * STEP_C0; + inc1 = inc1 * (2 * STEP_C1) + STEP_C1 * STEP_C1; + inc2 = inc2 * (2 * STEP_C2) + STEP_C2 * STEP_C2; + /* Now loop over all cells in box, updating distance per Thomas method */ + bptr = bestdist; + cptr = bestcolor; + xx0 = inc0; + for (ic0 = BOX_C0_ELEMS-1; ic0 >= 0; ic0--) { + dist1 = dist0; + xx1 = inc1; + for (ic1 = BOX_C1_ELEMS-1; ic1 >= 0; ic1--) { + dist2 = dist1; + xx2 = inc2; + for (ic2 = BOX_C2_ELEMS-1; ic2 >= 0; ic2--) { + if (dist2 < *bptr) { + *bptr = dist2; + *cptr = (JSAMPLE) icolor; + } + dist2 += xx2; + xx2 += 2 * STEP_C2 * STEP_C2; + bptr++; + cptr++; + } + dist1 += xx1; + xx1 += 2 * STEP_C1 * STEP_C1; + } + dist0 += xx0; + xx0 += 2 * STEP_C0 * STEP_C0; + } + } +} + + +LOCAL(void) +fill_inverse_cmap (j_decompress_ptr cinfo, int c0, int c1, int c2) +/* Fill the inverse-colormap entries in the update box that contains */ +/* histogram cell c0/c1/c2. (Only that one cell MUST be filled, but */ +/* we can fill as many others as we wish.) */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + int minc0, minc1, minc2; /* lower left corner of update box */ + int ic0, ic1, ic2; + register JSAMPLE * cptr; /* pointer into bestcolor[] array */ + register histptr cachep; /* pointer into main cache array */ + /* This array lists the candidate colormap indexes. */ + JSAMPLE colorlist[MAXNUMCOLORS]; + int numcolors; /* number of candidate colors */ + /* This array holds the actually closest colormap index for each cell. */ + JSAMPLE bestcolor[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS]; + + /* Convert cell coordinates to update box ID */ + c0 >>= BOX_C0_LOG; + c1 >>= BOX_C1_LOG; + c2 >>= BOX_C2_LOG; + + /* Compute true coordinates of update box's origin corner. + * Actually we compute the coordinates of the center of the corner + * histogram cell, which are the lower bounds of the volume we care about. + */ + minc0 = (c0 << BOX_C0_SHIFT) + ((1 << C0_SHIFT) >> 1); + minc1 = (c1 << BOX_C1_SHIFT) + ((1 << C1_SHIFT) >> 1); + minc2 = (c2 << BOX_C2_SHIFT) + ((1 << C2_SHIFT) >> 1); + + /* Determine which colormap entries are close enough to be candidates + * for the nearest entry to some cell in the update box. + */ + numcolors = find_nearby_colors(cinfo, minc0, minc1, minc2, colorlist); + + /* Determine the actually nearest colors. */ + find_best_colors(cinfo, minc0, minc1, minc2, numcolors, colorlist, + bestcolor); + + /* Save the best color numbers (plus 1) in the main cache array */ + c0 <<= BOX_C0_LOG; /* convert ID back to base cell indexes */ + c1 <<= BOX_C1_LOG; + c2 <<= BOX_C2_LOG; + cptr = bestcolor; + for (ic0 = 0; ic0 < BOX_C0_ELEMS; ic0++) { + for (ic1 = 0; ic1 < BOX_C1_ELEMS; ic1++) { + cachep = & histogram[c0+ic0][c1+ic1][c2]; + for (ic2 = 0; ic2 < BOX_C2_ELEMS; ic2++) { + *cachep++ = (histcell) (GETJSAMPLE(*cptr++) + 1); + } + } + } +} + + +/* + * Map some rows of pixels to the output colormapped representation. + */ + +METHODDEF(void) +pass2_no_dither (j_decompress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) +/* This version performs no dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + register JSAMPROW inptr, outptr; + register histptr cachep; + register int c0, c1, c2; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + + for (row = 0; row < num_rows; row++) { + inptr = input_buf[row]; + outptr = output_buf[row]; + for (col = width; col > 0; col--) { + /* get pixel value and index into the cache */ + c0 = GETJSAMPLE(*inptr++) >> C0_SHIFT; + c1 = GETJSAMPLE(*inptr++) >> C1_SHIFT; + c2 = GETJSAMPLE(*inptr++) >> C2_SHIFT; + cachep = & histogram[c0][c1][c2]; + /* If we have not seen this color before, find nearest colormap entry */ + /* and update the cache */ + if (*cachep == 0) + fill_inverse_cmap(cinfo, c0,c1,c2); + /* Now emit the colormap index for this cell */ + *outptr++ = (JSAMPLE) (*cachep - 1); + } + } +} + + +METHODDEF(void) +pass2_fs_dither (j_decompress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) +/* This version performs Floyd-Steinberg dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + register LOCFSERROR cur0, cur1, cur2; /* current error or pixel value */ + LOCFSERROR belowerr0, belowerr1, belowerr2; /* error for pixel below cur */ + LOCFSERROR bpreverr0, bpreverr1, bpreverr2; /* error for below/prev col */ + register FSERRPTR errorptr; /* => fserrors[] at column before current */ + JSAMPROW inptr; /* => current input pixel */ + JSAMPROW outptr; /* => current output pixel */ + histptr cachep; + int dir; /* +1 or -1 depending on direction */ + int dir3; /* 3*dir, for advancing inptr & errorptr */ + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + JSAMPLE *range_limit = cinfo->sample_range_limit; + int *error_limit = cquantize->error_limiter; + JSAMPROW colormap0 = cinfo->colormap[0]; + JSAMPROW colormap1 = cinfo->colormap[1]; + JSAMPROW colormap2 = cinfo->colormap[2]; + SHIFT_TEMPS + + for (row = 0; row < num_rows; row++) { + inptr = input_buf[row]; + outptr = output_buf[row]; + if (cquantize->on_odd_row) { + /* work right to left in this row */ + inptr += (width-1) * 3; /* so point to rightmost pixel */ + outptr += width-1; + dir = -1; + dir3 = -3; + errorptr = cquantize->fserrors + (width+1)*3; /* => entry after last column */ + cquantize->on_odd_row = FALSE; /* flip for next time */ + } else { + /* work left to right in this row */ + dir = 1; + dir3 = 3; + errorptr = cquantize->fserrors; /* => entry before first real column */ + cquantize->on_odd_row = TRUE; /* flip for next time */ + } + /* Preset error values: no error propagated to first pixel from left */ + cur0 = cur1 = cur2 = 0; + /* and no error propagated to row below yet */ + belowerr0 = belowerr1 = belowerr2 = 0; + bpreverr0 = bpreverr1 = bpreverr2 = 0; + + for (col = width; col > 0; col--) { + /* curN holds the error propagated from the previous pixel on the + * current line. Add the error propagated from the previous line + * to form the complete error correction term for this pixel, and + * round the error term (which is expressed * 16) to an integer. + * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct + * for either sign of the error value. + * Note: errorptr points to *previous* column's array entry. + */ + cur0 = RIGHT_SHIFT(cur0 + errorptr[dir3+0] + 8, 4); + cur1 = RIGHT_SHIFT(cur1 + errorptr[dir3+1] + 8, 4); + cur2 = RIGHT_SHIFT(cur2 + errorptr[dir3+2] + 8, 4); + /* Limit the error using transfer function set by init_error_limit. + * See comments with init_error_limit for rationale. + */ + cur0 = error_limit[cur0]; + cur1 = error_limit[cur1]; + cur2 = error_limit[cur2]; + /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE. + * The maximum error is +- MAXJSAMPLE (or less with error limiting); + * this sets the required size of the range_limit array. + */ + cur0 += GETJSAMPLE(inptr[0]); + cur1 += GETJSAMPLE(inptr[1]); + cur2 += GETJSAMPLE(inptr[2]); + cur0 = GETJSAMPLE(range_limit[cur0]); + cur1 = GETJSAMPLE(range_limit[cur1]); + cur2 = GETJSAMPLE(range_limit[cur2]); + /* Index into the cache with adjusted pixel value */ + cachep = & histogram[cur0>>C0_SHIFT][cur1>>C1_SHIFT][cur2>>C2_SHIFT]; + /* If we have not seen this color before, find nearest colormap */ + /* entry and update the cache */ + if (*cachep == 0) + fill_inverse_cmap(cinfo, cur0>>C0_SHIFT,cur1>>C1_SHIFT,cur2>>C2_SHIFT); + /* Now emit the colormap index for this cell */ + { register int pixcode = *cachep - 1; + *outptr = (JSAMPLE) pixcode; + /* Compute representation error for this pixel */ + cur0 -= GETJSAMPLE(colormap0[pixcode]); + cur1 -= GETJSAMPLE(colormap1[pixcode]); + cur2 -= GETJSAMPLE(colormap2[pixcode]); + } + /* Compute error fractions to be propagated to adjacent pixels. + * Add these into the running sums, and simultaneously shift the + * next-line error sums left by 1 column. + */ + { register LOCFSERROR bnexterr, delta; + + bnexterr = cur0; /* Process component 0 */ + delta = cur0 * 2; + cur0 += delta; /* form error * 3 */ + errorptr[0] = (FSERROR) (bpreverr0 + cur0); + cur0 += delta; /* form error * 5 */ + bpreverr0 = belowerr0 + cur0; + belowerr0 = bnexterr; + cur0 += delta; /* form error * 7 */ + bnexterr = cur1; /* Process component 1 */ + delta = cur1 * 2; + cur1 += delta; /* form error * 3 */ + errorptr[1] = (FSERROR) (bpreverr1 + cur1); + cur1 += delta; /* form error * 5 */ + bpreverr1 = belowerr1 + cur1; + belowerr1 = bnexterr; + cur1 += delta; /* form error * 7 */ + bnexterr = cur2; /* Process component 2 */ + delta = cur2 * 2; + cur2 += delta; /* form error * 3 */ + errorptr[2] = (FSERROR) (bpreverr2 + cur2); + cur2 += delta; /* form error * 5 */ + bpreverr2 = belowerr2 + cur2; + belowerr2 = bnexterr; + cur2 += delta; /* form error * 7 */ + } + /* At this point curN contains the 7/16 error value to be propagated + * to the next pixel on the current line, and all the errors for the + * next line have been shifted over. We are therefore ready to move on. + */ + inptr += dir3; /* Advance pixel pointers to next column */ + outptr += dir; + errorptr += dir3; /* advance errorptr to current column */ + } + /* Post-loop cleanup: we must unload the final error values into the + * final fserrors[] entry. Note we need not unload belowerrN because + * it is for the dummy column before or after the actual array. + */ + errorptr[0] = (FSERROR) bpreverr0; /* unload prev errs into array */ + errorptr[1] = (FSERROR) bpreverr1; + errorptr[2] = (FSERROR) bpreverr2; + } +} + + +/* + * Initialize the error-limiting transfer function (lookup table). + * The raw F-S error computation can potentially compute error values of up to + * +- MAXJSAMPLE. But we want the maximum correction applied to a pixel to be + * much less, otherwise obviously wrong pixels will be created. (Typical + * effects include weird fringes at color-area boundaries, isolated bright + * pixels in a dark area, etc.) The standard advice for avoiding this problem + * is to ensure that the "corners" of the color cube are allocated as output + * colors; then repeated errors in the same direction cannot cause cascading + * error buildup. However, that only prevents the error from getting + * completely out of hand; Aaron Giles reports that error limiting improves + * the results even with corner colors allocated. + * A simple clamping of the error values to about +- MAXJSAMPLE/8 works pretty + * well, but the smoother transfer function used below is even better. Thanks + * to Aaron Giles for this idea. + */ + +LOCAL(void) +init_error_limit (j_decompress_ptr cinfo) +/* Allocate and fill in the error_limiter table */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + int * table; + int in, out; + + table = (int *) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE*2+1) * SIZEOF(int)); + table += MAXJSAMPLE; /* so can index -MAXJSAMPLE .. +MAXJSAMPLE */ + cquantize->error_limiter = table; + +#define STEPSIZE ((MAXJSAMPLE+1)/16) + /* Map errors 1:1 up to +- MAXJSAMPLE/16 */ + out = 0; + for (in = 0; in < STEPSIZE; in++, out++) { + table[in] = out; table[-in] = -out; + } + /* Map errors 1:2 up to +- 3*MAXJSAMPLE/16 */ + for (; in < STEPSIZE*3; in++, out += (in&1) ? 0 : 1) { + table[in] = out; table[-in] = -out; + } + /* Clamp the rest to final out value (which is (MAXJSAMPLE+1)/8) */ + for (; in <= MAXJSAMPLE; in++) { + table[in] = out; table[-in] = -out; + } +#undef STEPSIZE +} + + +/* + * Finish up at the end of each pass. + */ + +METHODDEF(void) +finish_pass1 (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + + /* Select the representative colors and fill in cinfo->colormap */ + cinfo->colormap = cquantize->sv_colormap; + select_colors(cinfo, cquantize->desired); + /* Force next pass to zero the color index table */ + cquantize->needs_zeroed = TRUE; +} + + +METHODDEF(void) +finish_pass2 (j_decompress_ptr cinfo) +{ + /* no work */ +} + + +/* + * Initialize for each processing pass. + */ + +METHODDEF(void) +start_pass_2_quant (j_decompress_ptr cinfo, boolean is_pre_scan) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + int i; + + /* Only F-S dithering or no dithering is supported. */ + /* If user asks for ordered dither, give him F-S. */ + if (cinfo->dither_mode != JDITHER_NONE) + cinfo->dither_mode = JDITHER_FS; + + if (is_pre_scan) { + /* Set up method pointers */ + cquantize->pub.color_quantize = prescan_quantize; + cquantize->pub.finish_pass = finish_pass1; + cquantize->needs_zeroed = TRUE; /* Always zero histogram */ + } else { + /* Set up method pointers */ + if (cinfo->dither_mode == JDITHER_FS) + cquantize->pub.color_quantize = pass2_fs_dither; + else + cquantize->pub.color_quantize = pass2_no_dither; + cquantize->pub.finish_pass = finish_pass2; + + /* Make sure color count is acceptable */ + i = cinfo->actual_number_of_colors; + if (i < 1) + ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 1); + if (i > MAXNUMCOLORS) + ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS); + + if (cinfo->dither_mode == JDITHER_FS) { + size_t arraysize = (size_t) ((cinfo->output_width + 2) * + (3 * SIZEOF(FSERROR))); + /* Allocate Floyd-Steinberg workspace if we didn't already. */ + if (cquantize->fserrors == NULL) + cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large) + ((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize); + /* Initialize the propagated errors to zero. */ + jzero_far((void FAR *) cquantize->fserrors, arraysize); + /* Make the error-limit table if we didn't already. */ + if (cquantize->error_limiter == NULL) + init_error_limit(cinfo); + cquantize->on_odd_row = FALSE; + } + + } + /* Zero the histogram or inverse color map, if necessary */ + if (cquantize->needs_zeroed) { + for (i = 0; i < HIST_C0_ELEMS; i++) { + jzero_far((void FAR *) histogram[i], + HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell)); + } + cquantize->needs_zeroed = FALSE; + } +} + + +/* + * Switch to a new external colormap between output passes. + */ + +METHODDEF(void) +new_color_map_2_quant (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + + /* Reset the inverse color map */ + cquantize->needs_zeroed = TRUE; +} + + +/* + * Module initialization routine for 2-pass color quantization. + */ + +GLOBAL(void) +jinit_2pass_quantizer (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize; + int i; + + cquantize = (my_cquantize_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_cquantizer)); + cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize; + cquantize->pub.start_pass = start_pass_2_quant; + cquantize->pub.new_color_map = new_color_map_2_quant; + cquantize->fserrors = NULL; /* flag optional arrays not allocated */ + cquantize->error_limiter = NULL; + + /* Make sure jdmaster didn't give me a case I can't handle */ + if (cinfo->out_color_components != 3) + ERREXIT(cinfo, JERR_NOTIMPL); + + /* Allocate the histogram/inverse colormap storage */ + cquantize->histogram = (hist3d) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, HIST_C0_ELEMS * SIZEOF(hist2d)); + for (i = 0; i < HIST_C0_ELEMS; i++) { + cquantize->histogram[i] = (hist2d) (*cinfo->mem->alloc_large) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell)); + } + cquantize->needs_zeroed = TRUE; /* histogram is garbage now */ + + /* Allocate storage for the completed colormap, if required. + * We do this now since it is FAR storage and may affect + * the memory manager's space calculations. + */ + if (cinfo->enable_2pass_quant) { + /* Make sure color count is acceptable */ + int desired = cinfo->desired_number_of_colors; + /* Lower bound on # of colors ... somewhat arbitrary as long as > 0 */ + if (desired < 8) + ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 8); + /* Make sure colormap indexes can be represented by JSAMPLEs */ + if (desired > MAXNUMCOLORS) + ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS); + cquantize->sv_colormap = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo,JPOOL_IMAGE, (JDIMENSION) desired, (JDIMENSION) 3); + cquantize->desired = desired; + } else + cquantize->sv_colormap = NULL; + + /* Only F-S dithering or no dithering is supported. */ + /* If user asks for ordered dither, give him F-S. */ + if (cinfo->dither_mode != JDITHER_NONE) + cinfo->dither_mode = JDITHER_FS; + + /* Allocate Floyd-Steinberg workspace if necessary. + * This isn't really needed until pass 2, but again it is FAR storage. + * Although we will cope with a later change in dither_mode, + * we do not promise to honor max_memory_to_use if dither_mode changes. + */ + if (cinfo->dither_mode == JDITHER_FS) { + cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (size_t) ((cinfo->output_width + 2) * (3 * SIZEOF(FSERROR)))); + /* Might as well create the error-limiting table too. */ + init_error_limit(cinfo); + } +} + +#endif /* QUANT_2PASS_SUPPORTED */ diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jutils.c b/lc-continuity/mk4/modimage/jpeg-6b/jutils.c new file mode 100644 index 0000000000000000000000000000000000000000..d18a9555621bae9dce0b814e8afc7c05e877a4cb --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jutils.c @@ -0,0 +1,179 @@ +/* + * jutils.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains tables and miscellaneous utility routines needed + * for both compression and decompression. + * Note we prefix all global names with "j" to minimize conflicts with + * a surrounding application. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* + * jpeg_zigzag_order[i] is the zigzag-order position of the i'th element + * of a DCT block read in natural order (left to right, top to bottom). + */ + +#if 0 /* This table is not actually needed in v6a */ + +const int jpeg_zigzag_order[DCTSIZE2] = { + 0, 1, 5, 6, 14, 15, 27, 28, + 2, 4, 7, 13, 16, 26, 29, 42, + 3, 8, 12, 17, 25, 30, 41, 43, + 9, 11, 18, 24, 31, 40, 44, 53, + 10, 19, 23, 32, 39, 45, 52, 54, + 20, 22, 33, 38, 46, 51, 55, 60, + 21, 34, 37, 47, 50, 56, 59, 61, + 35, 36, 48, 49, 57, 58, 62, 63 +}; + +#endif + +/* + * jpeg_natural_order[i] is the natural-order position of the i'th element + * of zigzag order. + * + * When reading corrupted data, the Huffman decoders could attempt + * to reference an entry beyond the end of this array (if the decoded + * zero run length reaches past the end of the block). To prevent + * wild stores without adding an inner-loop test, we put some extra + * "63"s after the real entries. This will cause the extra coefficient + * to be stored in location 63 of the block, not somewhere random. + * The worst case would be a run-length of 15, which means we need 16 + * fake entries. + */ + +const int jpeg_natural_order[DCTSIZE2+16] = { + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63, + 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ + 63, 63, 63, 63, 63, 63, 63, 63 +}; + + +/* + * Arithmetic utilities + */ + +GLOBAL(long) +jdiv_round_up (long a, long b) +/* Compute a/b rounded up to next integer, ie, ceil(a/b) */ +/* Assumes a >= 0, b > 0 */ +{ + return (a + b - 1L) / b; +} + + +GLOBAL(long) +jround_up (long a, long b) +/* Compute a rounded up to next multiple of b, ie, ceil(a/b)*b */ +/* Assumes a >= 0, b > 0 */ +{ + a += b - 1L; + return a - (a % b); +} + + +/* On normal machines we can apply MEMCOPY() and MEMZERO() to sample arrays + * and coefficient-block arrays. This won't work on 80x86 because the arrays + * are FAR and we're assuming a small-pointer memory model. However, some + * DOS compilers provide far-pointer versions of memcpy() and memset() even + * in the small-model libraries. These will be used if USE_FMEM is defined. + * Otherwise, the routines below do it the hard way. (The performance cost + * is not all that great, because these routines aren't very heavily used.) + */ + +#ifndef NEED_FAR_POINTERS /* normal case, same as regular macros */ +#define FMEMCOPY(dest,src,size) MEMCOPY(dest,src,size) +#define FMEMZERO(target,size) MEMZERO(target,size) +#else /* 80x86 case, define if we can */ +#ifdef USE_FMEM +#define FMEMCOPY(dest,src,size) _fmemcpy((void FAR *)(dest), (const void FAR *)(src), (size_t)(size)) +#define FMEMZERO(target,size) _fmemset((void FAR *)(target), 0, (size_t)(size)) +#endif +#endif + + +GLOBAL(void) +jcopy_sample_rows (JSAMPARRAY input_array, int source_row, + JSAMPARRAY output_array, int dest_row, + int num_rows, JDIMENSION num_cols) +/* Copy some rows of samples from one place to another. + * num_rows rows are copied from input_array[source_row++] + * to output_array[dest_row++]; these areas may overlap for duplication. + * The source and destination arrays must be at least as wide as num_cols. + */ +{ + register JSAMPROW inptr, outptr; +#ifdef FMEMCOPY + register size_t count = (size_t) (num_cols * SIZEOF(JSAMPLE)); +#else + register JDIMENSION count; +#endif + register int row; + + input_array += source_row; + output_array += dest_row; + + for (row = num_rows; row > 0; row--) { + inptr = *input_array++; + outptr = *output_array++; +#ifdef FMEMCOPY + FMEMCOPY(outptr, inptr, count); +#else + for (count = num_cols; count > 0; count--) + *outptr++ = *inptr++; /* needn't bother with GETJSAMPLE() here */ +#endif + } +} + + +GLOBAL(void) +jcopy_block_row (JBLOCKROW input_row, JBLOCKROW output_row, + JDIMENSION num_blocks) +/* Copy a row of coefficient blocks from one place to another. */ +{ +#ifdef FMEMCOPY + FMEMCOPY(output_row, input_row, num_blocks * (DCTSIZE2 * SIZEOF(JCOEF))); +#else + register JCOEFPTR inptr, outptr; + register long count; + + inptr = (JCOEFPTR) input_row; + outptr = (JCOEFPTR) output_row; + for (count = (long) num_blocks * DCTSIZE2; count > 0; count--) { + *outptr++ = *inptr++; + } +#endif +} + + +GLOBAL(void) +jzero_far (void FAR * target, size_t bytestozero) +/* Zero out a chunk of FAR memory. */ +/* This might be sample-array data, block-array data, or alloc_large data. */ +{ +#ifdef FMEMZERO + FMEMZERO(target, bytestozero); +#else + register char FAR * ptr = (char FAR *) target; + register size_t count; + + for (count = bytestozero; count > 0; count--) { + *ptr++ = 0; + } +#endif +} diff --git a/lc-continuity/mk4/modimage/jpeg-6b/jversion.h b/lc-continuity/mk4/modimage/jpeg-6b/jversion.h new file mode 100644 index 0000000000000000000000000000000000000000..6472c58d351ac6a286443f692a8ec07a4a752877 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/jversion.h @@ -0,0 +1,14 @@ +/* + * jversion.h + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains software version identification. + */ + + +#define JVERSION "6b 27-Mar-1998" + +#define JCOPYRIGHT "Copyright (C) 1998, Thomas G. Lane" diff --git a/lc-continuity/mk4/modimage/jpeg-6b/libjpeg.doc b/lc-continuity/mk4/modimage/jpeg-6b/libjpeg.doc new file mode 100644 index 0000000000000000000000000000000000000000..689b206c07fdfa03e915abaaf2d7aa458d8cf5bc --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/libjpeg.doc @@ -0,0 +1,3006 @@ +USING THE IJG JPEG LIBRARY + +Copyright (C) 1994-1998, Thomas G. Lane. +This file is part of the Independent JPEG Group's software. +For conditions of distribution and use, see the accompanying README file. + + +This file describes how to use the IJG JPEG library within an application +program. Read it if you want to write a program that uses the library. + +The file example.c provides heavily commented skeleton code for calling the +JPEG library. Also see jpeglib.h (the include file to be used by application +programs) for full details about data structures and function parameter lists. +The library source code, of course, is the ultimate reference. + +Note that there have been *major* changes from the application interface +presented by IJG version 4 and earlier versions. The old design had several +inherent limitations, and it had accumulated a lot of cruft as we added +features while trying to minimize application-interface changes. We have +sacrificed backward compatibility in the version 5 rewrite, but we think the +improvements justify this. + + +TABLE OF CONTENTS +----------------- + +Overview: + Functions provided by the library + Outline of typical usage +Basic library usage: + Data formats + Compression details + Decompression details + Mechanics of usage: include files, linking, etc +Advanced features: + Compression parameter selection + Decompression parameter selection + Special color spaces + Error handling + Compressed data handling (source and destination managers) + I/O suspension + Progressive JPEG support + Buffered-image mode + Abbreviated datastreams and multiple images + Special markers + Raw (downsampled) image data + Really raw data: DCT coefficients + Progress monitoring + Memory management + Memory usage + Library compile-time options + Portability considerations + Notes for MS-DOS implementors + +You should read at least the overview and basic usage sections before trying +to program with the library. The sections on advanced features can be read +if and when you need them. + + +OVERVIEW +======== + +Functions provided by the library +--------------------------------- + +The IJG JPEG library provides C code to read and write JPEG-compressed image +files. The surrounding application program receives or supplies image data a +scanline at a time, using a straightforward uncompressed image format. All +details of color conversion and other preprocessing/postprocessing can be +handled by the library. + +The library includes a substantial amount of code that is not covered by the +JPEG standard but is necessary for typical applications of JPEG. These +functions preprocess the image before JPEG compression or postprocess it after +decompression. They include colorspace conversion, downsampling/upsampling, +and color quantization. The application indirectly selects use of this code +by specifying the format in which it wishes to supply or receive image data. +For example, if colormapped output is requested, then the decompression +library automatically invokes color quantization. + +A wide range of quality vs. speed tradeoffs are possible in JPEG processing, +and even more so in decompression postprocessing. The decompression library +provides multiple implementations that cover most of the useful tradeoffs, +ranging from very-high-quality down to fast-preview operation. On the +compression side we have generally not provided low-quality choices, since +compression is normally less time-critical. It should be understood that the +low-quality modes may not meet the JPEG standard's accuracy requirements; +nonetheless, they are useful for viewers. + +A word about functions *not* provided by the library. We handle a subset of +the ISO JPEG standard; most baseline, extended-sequential, and progressive +JPEG processes are supported. (Our subset includes all features now in common +use.) Unsupported ISO options include: + * Hierarchical storage + * Lossless JPEG + * Arithmetic entropy coding (unsupported for legal reasons) + * DNL marker + * Nonintegral subsampling ratios +We support both 8- and 12-bit data precision, but this is a compile-time +choice rather than a run-time choice; hence it is difficult to use both +precisions in a single application. + +By itself, the library handles only interchange JPEG datastreams --- in +particular the widely used JFIF file format. The library can be used by +surrounding code to process interchange or abbreviated JPEG datastreams that +are embedded in more complex file formats. (For example, this library is +used by the free LIBTIFF library to support JPEG compression in TIFF.) + + +Outline of typical usage +------------------------ + +The rough outline of a JPEG compression operation is: + + Allocate and initialize a JPEG compression object + Specify the destination for the compressed data (eg, a file) + Set parameters for compression, including image size & colorspace + jpeg_start_compress(...); + while (scan lines remain to be written) + jpeg_write_scanlines(...); + jpeg_finish_compress(...); + Release the JPEG compression object + +A JPEG compression object holds parameters and working state for the JPEG +library. We make creation/destruction of the object separate from starting +or finishing compression of an image; the same object can be re-used for a +series of image compression operations. This makes it easy to re-use the +same parameter settings for a sequence of images. Re-use of a JPEG object +also has important implications for processing abbreviated JPEG datastreams, +as discussed later. + +The image data to be compressed is supplied to jpeg_write_scanlines() from +in-memory buffers. If the application is doing file-to-file compression, +reading image data from the source file is the application's responsibility. +The library emits compressed data by calling a "data destination manager", +which typically will write the data into a file; but the application can +provide its own destination manager to do something else. + +Similarly, the rough outline of a JPEG decompression operation is: + + Allocate and initialize a JPEG decompression object + Specify the source of the compressed data (eg, a file) + Call jpeg_read_header() to obtain image info + Set parameters for decompression + jpeg_start_decompress(...); + while (scan lines remain to be read) + jpeg_read_scanlines(...); + jpeg_finish_decompress(...); + Release the JPEG decompression object + +This is comparable to the compression outline except that reading the +datastream header is a separate step. This is helpful because information +about the image's size, colorspace, etc is available when the application +selects decompression parameters. For example, the application can choose an +output scaling ratio that will fit the image into the available screen size. + +The decompression library obtains compressed data by calling a data source +manager, which typically will read the data from a file; but other behaviors +can be obtained with a custom source manager. Decompressed data is delivered +into in-memory buffers passed to jpeg_read_scanlines(). + +It is possible to abort an incomplete compression or decompression operation +by calling jpeg_abort(); or, if you do not need to retain the JPEG object, +simply release it by calling jpeg_destroy(). + +JPEG compression and decompression objects are two separate struct types. +However, they share some common fields, and certain routines such as +jpeg_destroy() can work on either type of object. + +The JPEG library has no static variables: all state is in the compression +or decompression object. Therefore it is possible to process multiple +compression and decompression operations concurrently, using multiple JPEG +objects. + +Both compression and decompression can be done in an incremental memory-to- +memory fashion, if suitable source/destination managers are used. See the +section on "I/O suspension" for more details. + + +BASIC LIBRARY USAGE +=================== + +Data formats +------------ + +Before diving into procedural details, it is helpful to understand the +image data format that the JPEG library expects or returns. + +The standard input image format is a rectangular array of pixels, with each +pixel having the same number of "component" or "sample" values (color +channels). You must specify how many components there are and the colorspace +interpretation of the components. Most applications will use RGB data +(three components per pixel) or grayscale data (one component per pixel). +PLEASE NOTE THAT RGB DATA IS THREE SAMPLES PER PIXEL, GRAYSCALE ONLY ONE. +A remarkable number of people manage to miss this, only to find that their +programs don't work with grayscale JPEG files. + +There is no provision for colormapped input. JPEG files are always full-color +or full grayscale (or sometimes another colorspace such as CMYK). You can +feed in a colormapped image by expanding it to full-color format. However +JPEG often doesn't work very well with source data that has been colormapped, +because of dithering noise. This is discussed in more detail in the JPEG FAQ +and the other references mentioned in the README file. + +Pixels are stored by scanlines, with each scanline running from left to +right. The component values for each pixel are adjacent in the row; for +example, R,G,B,R,G,B,R,G,B,... for 24-bit RGB color. Each scanline is an +array of data type JSAMPLE --- which is typically "unsigned char", unless +you've changed jmorecfg.h. (You can also change the RGB pixel layout, say +to B,G,R order, by modifying jmorecfg.h. But see the restrictions listed in +that file before doing so.) + +A 2-D array of pixels is formed by making a list of pointers to the starts of +scanlines; so the scanlines need not be physically adjacent in memory. Even +if you process just one scanline at a time, you must make a one-element +pointer array to conform to this structure. Pointers to JSAMPLE rows are of +type JSAMPROW, and the pointer to the pointer array is of type JSAMPARRAY. + +The library accepts or supplies one or more complete scanlines per call. +It is not possible to process part of a row at a time. Scanlines are always +processed top-to-bottom. You can process an entire image in one call if you +have it all in memory, but usually it's simplest to process one scanline at +a time. + +For best results, source data values should have the precision specified by +BITS_IN_JSAMPLE (normally 8 bits). For instance, if you choose to compress +data that's only 6 bits/channel, you should left-justify each value in a +byte before passing it to the compressor. If you need to compress data +that has more than 8 bits/channel, compile with BITS_IN_JSAMPLE = 12. +(See "Library compile-time options", later.) + + +The data format returned by the decompressor is the same in all details, +except that colormapped output is supported. (Again, a JPEG file is never +colormapped. But you can ask the decompressor to perform on-the-fly color +quantization to deliver colormapped output.) If you request colormapped +output then the returned data array contains a single JSAMPLE per pixel; +its value is an index into a color map. The color map is represented as +a 2-D JSAMPARRAY in which each row holds the values of one color component, +that is, colormap[i][j] is the value of the i'th color component for pixel +value (map index) j. Note that since the colormap indexes are stored in +JSAMPLEs, the maximum number of colors is limited by the size of JSAMPLE +(ie, at most 256 colors for an 8-bit JPEG library). + + +Compression details +------------------- + +Here we revisit the JPEG compression outline given in the overview. + +1. Allocate and initialize a JPEG compression object. + +A JPEG compression object is a "struct jpeg_compress_struct". (It also has +a bunch of subsidiary structures which are allocated via malloc(), but the +application doesn't control those directly.) This struct can be just a local +variable in the calling routine, if a single routine is going to execute the +whole JPEG compression sequence. Otherwise it can be static or allocated +from malloc(). + +You will also need a structure representing a JPEG error handler. The part +of this that the library cares about is a "struct jpeg_error_mgr". If you +are providing your own error handler, you'll typically want to embed the +jpeg_error_mgr struct in a larger structure; this is discussed later under +"Error handling". For now we'll assume you are just using the default error +handler. The default error handler will print JPEG error/warning messages +on stderr, and it will call exit() if a fatal error occurs. + +You must initialize the error handler structure, store a pointer to it into +the JPEG object's "err" field, and then call jpeg_create_compress() to +initialize the rest of the JPEG object. + +Typical code for this step, if you are using the default error handler, is + + struct jpeg_compress_struct cinfo; + struct jpeg_error_mgr jerr; + ... + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_compress(&cinfo); + +jpeg_create_compress allocates a small amount of memory, so it could fail +if you are out of memory. In that case it will exit via the error handler; +that's why the error handler must be initialized first. + + +2. Specify the destination for the compressed data (eg, a file). + +As previously mentioned, the JPEG library delivers compressed data to a +"data destination" module. The library includes one data destination +module which knows how to write to a stdio stream. You can use your own +destination module if you want to do something else, as discussed later. + +If you use the standard destination module, you must open the target stdio +stream beforehand. Typical code for this step looks like: + + FILE * outfile; + ... + if ((outfile = fopen(filename, "wb")) == NULL) { + fprintf(stderr, "can't open %s\n", filename); + exit(1); + } + jpeg_stdio_dest(&cinfo, outfile); + +where the last line invokes the standard destination module. + +WARNING: it is critical that the binary compressed data be delivered to the +output file unchanged. On non-Unix systems the stdio library may perform +newline translation or otherwise corrupt binary data. To suppress this +behavior, you may need to use a "b" option to fopen (as shown above), or use +setmode() or another routine to put the stdio stream in binary mode. See +cjpeg.c and djpeg.c for code that has been found to work on many systems. + +You can select the data destination after setting other parameters (step 3), +if that's more convenient. You may not change the destination between +calling jpeg_start_compress() and jpeg_finish_compress(). + + +3. Set parameters for compression, including image size & colorspace. + +You must supply information about the source image by setting the following +fields in the JPEG object (cinfo structure): + + image_width Width of image, in pixels + image_height Height of image, in pixels + input_components Number of color channels (samples per pixel) + in_color_space Color space of source image + +The image dimensions are, hopefully, obvious. JPEG supports image dimensions +of 1 to 64K pixels in either direction. The input color space is typically +RGB or grayscale, and input_components is 3 or 1 accordingly. (See "Special +color spaces", later, for more info.) The in_color_space field must be +assigned one of the J_COLOR_SPACE enum constants, typically JCS_RGB or +JCS_GRAYSCALE. + +JPEG has a large number of compression parameters that determine how the +image is encoded. Most applications don't need or want to know about all +these parameters. You can set all the parameters to reasonable defaults by +calling jpeg_set_defaults(); then, if there are particular values you want +to change, you can do so after that. The "Compression parameter selection" +section tells about all the parameters. + +You must set in_color_space correctly before calling jpeg_set_defaults(), +because the defaults depend on the source image colorspace. However the +other three source image parameters need not be valid until you call +jpeg_start_compress(). There's no harm in calling jpeg_set_defaults() more +than once, if that happens to be convenient. + +Typical code for a 24-bit RGB source image is + + cinfo.image_width = Width; /* image width and height, in pixels */ + cinfo.image_height = Height; + cinfo.input_components = 3; /* # of color components per pixel */ + cinfo.in_color_space = JCS_RGB; /* colorspace of input image */ + + jpeg_set_defaults(&cinfo); + /* Make optional parameter settings here */ + + +4. jpeg_start_compress(...); + +After you have established the data destination and set all the necessary +source image info and other parameters, call jpeg_start_compress() to begin +a compression cycle. This will initialize internal state, allocate working +storage, and emit the first few bytes of the JPEG datastream header. + +Typical code: + + jpeg_start_compress(&cinfo, TRUE); + +The "TRUE" parameter ensures that a complete JPEG interchange datastream +will be written. This is appropriate in most cases. If you think you might +want to use an abbreviated datastream, read the section on abbreviated +datastreams, below. + +Once you have called jpeg_start_compress(), you may not alter any JPEG +parameters or other fields of the JPEG object until you have completed +the compression cycle. + + +5. while (scan lines remain to be written) + jpeg_write_scanlines(...); + +Now write all the required image data by calling jpeg_write_scanlines() +one or more times. You can pass one or more scanlines in each call, up +to the total image height. In most applications it is convenient to pass +just one or a few scanlines at a time. The expected format for the passed +data is discussed under "Data formats", above. + +Image data should be written in top-to-bottom scanline order. The JPEG spec +contains some weasel wording about how top and bottom are application-defined +terms (a curious interpretation of the English language...) but if you want +your files to be compatible with everyone else's, you WILL use top-to-bottom +order. If the source data must be read in bottom-to-top order, you can use +the JPEG library's virtual array mechanism to invert the data efficiently. +Examples of this can be found in the sample application cjpeg. + +The library maintains a count of the number of scanlines written so far +in the next_scanline field of the JPEG object. Usually you can just use +this variable as the loop counter, so that the loop test looks like +"while (cinfo.next_scanline < cinfo.image_height)". + +Code for this step depends heavily on the way that you store the source data. +example.c shows the following code for the case of a full-size 2-D source +array containing 3-byte RGB pixels: + + JSAMPROW row_pointer[1]; /* pointer to a single row */ + int row_stride; /* physical row width in buffer */ + + row_stride = image_width * 3; /* JSAMPLEs per row in image_buffer */ + + while (cinfo.next_scanline < cinfo.image_height) { + row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride]; + jpeg_write_scanlines(&cinfo, row_pointer, 1); + } + +jpeg_write_scanlines() returns the number of scanlines actually written. +This will normally be equal to the number passed in, so you can usually +ignore the return value. It is different in just two cases: + * If you try to write more scanlines than the declared image height, + the additional scanlines are ignored. + * If you use a suspending data destination manager, output buffer overrun + will cause the compressor to return before accepting all the passed lines. + This feature is discussed under "I/O suspension", below. The normal + stdio destination manager will NOT cause this to happen. +In any case, the return value is the same as the change in the value of +next_scanline. + + +6. jpeg_finish_compress(...); + +After all the image data has been written, call jpeg_finish_compress() to +complete the compression cycle. This step is ESSENTIAL to ensure that the +last bufferload of data is written to the data destination. +jpeg_finish_compress() also releases working memory associated with the JPEG +object. + +Typical code: + + jpeg_finish_compress(&cinfo); + +If using the stdio destination manager, don't forget to close the output +stdio stream (if necessary) afterwards. + +If you have requested a multi-pass operating mode, such as Huffman code +optimization, jpeg_finish_compress() will perform the additional passes using +data buffered by the first pass. In this case jpeg_finish_compress() may take +quite a while to complete. With the default compression parameters, this will +not happen. + +It is an error to call jpeg_finish_compress() before writing the necessary +total number of scanlines. If you wish to abort compression, call +jpeg_abort() as discussed below. + +After completing a compression cycle, you may dispose of the JPEG object +as discussed next, or you may use it to compress another image. In that case +return to step 2, 3, or 4 as appropriate. If you do not change the +destination manager, the new datastream will be written to the same target. +If you do not change any JPEG parameters, the new datastream will be written +with the same parameters as before. Note that you can change the input image +dimensions freely between cycles, but if you change the input colorspace, you +should call jpeg_set_defaults() to adjust for the new colorspace; and then +you'll need to repeat all of step 3. + + +7. Release the JPEG compression object. + +When you are done with a JPEG compression object, destroy it by calling +jpeg_destroy_compress(). This will free all subsidiary memory (regardless of +the previous state of the object). Or you can call jpeg_destroy(), which +works for either compression or decompression objects --- this may be more +convenient if you are sharing code between compression and decompression +cases. (Actually, these routines are equivalent except for the declared type +of the passed pointer. To avoid gripes from ANSI C compilers, jpeg_destroy() +should be passed a j_common_ptr.) + +If you allocated the jpeg_compress_struct structure from malloc(), freeing +it is your responsibility --- jpeg_destroy() won't. Ditto for the error +handler structure. + +Typical code: + + jpeg_destroy_compress(&cinfo); + + +8. Aborting. + +If you decide to abort a compression cycle before finishing, you can clean up +in either of two ways: + +* If you don't need the JPEG object any more, just call + jpeg_destroy_compress() or jpeg_destroy() to release memory. This is + legitimate at any point after calling jpeg_create_compress() --- in fact, + it's safe even if jpeg_create_compress() fails. + +* If you want to re-use the JPEG object, call jpeg_abort_compress(), or call + jpeg_abort() which works on both compression and decompression objects. + This will return the object to an idle state, releasing any working memory. + jpeg_abort() is allowed at any time after successful object creation. + +Note that cleaning up the data destination, if required, is your +responsibility; neither of these routines will call term_destination(). +(See "Compressed data handling", below, for more about that.) + +jpeg_destroy() and jpeg_abort() are the only safe calls to make on a JPEG +object that has reported an error by calling error_exit (see "Error handling" +for more info). The internal state of such an object is likely to be out of +whack. Either of these two routines will return the object to a known state. + + +Decompression details +--------------------- + +Here we revisit the JPEG decompression outline given in the overview. + +1. Allocate and initialize a JPEG decompression object. + +This is just like initialization for compression, as discussed above, +except that the object is a "struct jpeg_decompress_struct" and you +call jpeg_create_decompress(). Error handling is exactly the same. + +Typical code: + + struct jpeg_decompress_struct cinfo; + struct jpeg_error_mgr jerr; + ... + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_decompress(&cinfo); + +(Both here and in the IJG code, we usually use variable name "cinfo" for +both compression and decompression objects.) + + +2. Specify the source of the compressed data (eg, a file). + +As previously mentioned, the JPEG library reads compressed data from a "data +source" module. The library includes one data source module which knows how +to read from a stdio stream. You can use your own source module if you want +to do something else, as discussed later. + +If you use the standard source module, you must open the source stdio stream +beforehand. Typical code for this step looks like: + + FILE * infile; + ... + if ((infile = fopen(filename, "rb")) == NULL) { + fprintf(stderr, "can't open %s\n", filename); + exit(1); + } + jpeg_stdio_src(&cinfo, infile); + +where the last line invokes the standard source module. + +WARNING: it is critical that the binary compressed data be read unchanged. +On non-Unix systems the stdio library may perform newline translation or +otherwise corrupt binary data. To suppress this behavior, you may need to use +a "b" option to fopen (as shown above), or use setmode() or another routine to +put the stdio stream in binary mode. See cjpeg.c and djpeg.c for code that +has been found to work on many systems. + +You may not change the data source between calling jpeg_read_header() and +jpeg_finish_decompress(). If you wish to read a series of JPEG images from +a single source file, you should repeat the jpeg_read_header() to +jpeg_finish_decompress() sequence without reinitializing either the JPEG +object or the data source module; this prevents buffered input data from +being discarded. + + +3. Call jpeg_read_header() to obtain image info. + +Typical code for this step is just + + jpeg_read_header(&cinfo, TRUE); + +This will read the source datastream header markers, up to the beginning +of the compressed data proper. On return, the image dimensions and other +info have been stored in the JPEG object. The application may wish to +consult this information before selecting decompression parameters. + +More complex code is necessary if + * A suspending data source is used --- in that case jpeg_read_header() + may return before it has read all the header data. See "I/O suspension", + below. The normal stdio source manager will NOT cause this to happen. + * Abbreviated JPEG files are to be processed --- see the section on + abbreviated datastreams. Standard applications that deal only in + interchange JPEG files need not be concerned with this case either. + +It is permissible to stop at this point if you just wanted to find out the +image dimensions and other header info for a JPEG file. In that case, +call jpeg_destroy() when you are done with the JPEG object, or call +jpeg_abort() to return it to an idle state before selecting a new data +source and reading another header. + + +4. Set parameters for decompression. + +jpeg_read_header() sets appropriate default decompression parameters based on +the properties of the image (in particular, its colorspace). However, you +may well want to alter these defaults before beginning the decompression. +For example, the default is to produce full color output from a color file. +If you want colormapped output you must ask for it. Other options allow the +returned image to be scaled and allow various speed/quality tradeoffs to be +selected. "Decompression parameter selection", below, gives details. + +If the defaults are appropriate, nothing need be done at this step. + +Note that all default values are set by each call to jpeg_read_header(). +If you reuse a decompression object, you cannot expect your parameter +settings to be preserved across cycles, as you can for compression. +You must set desired parameter values each time. + + +5. jpeg_start_decompress(...); + +Once the parameter values are satisfactory, call jpeg_start_decompress() to +begin decompression. This will initialize internal state, allocate working +memory, and prepare for returning data. + +Typical code is just + + jpeg_start_decompress(&cinfo); + +If you have requested a multi-pass operating mode, such as 2-pass color +quantization, jpeg_start_decompress() will do everything needed before data +output can begin. In this case jpeg_start_decompress() may take quite a while +to complete. With a single-scan (non progressive) JPEG file and default +decompression parameters, this will not happen; jpeg_start_decompress() will +return quickly. + +After this call, the final output image dimensions, including any requested +scaling, are available in the JPEG object; so is the selected colormap, if +colormapped output has been requested. Useful fields include + + output_width image width and height, as scaled + output_height + out_color_components # of color components in out_color_space + output_components # of color components returned per pixel + colormap the selected colormap, if any + actual_number_of_colors number of entries in colormap + +output_components is 1 (a colormap index) when quantizing colors; otherwise it +equals out_color_components. It is the number of JSAMPLE values that will be +emitted per pixel in the output arrays. + +Typically you will need to allocate data buffers to hold the incoming image. +You will need output_width * output_components JSAMPLEs per scanline in your +output buffer, and a total of output_height scanlines will be returned. + +Note: if you are using the JPEG library's internal memory manager to allocate +data buffers (as djpeg does), then the manager's protocol requires that you +request large buffers *before* calling jpeg_start_decompress(). This is a +little tricky since the output_XXX fields are not normally valid then. You +can make them valid by calling jpeg_calc_output_dimensions() after setting the +relevant parameters (scaling, output color space, and quantization flag). + + +6. while (scan lines remain to be read) + jpeg_read_scanlines(...); + +Now you can read the decompressed image data by calling jpeg_read_scanlines() +one or more times. At each call, you pass in the maximum number of scanlines +to be read (ie, the height of your working buffer); jpeg_read_scanlines() +will return up to that many lines. The return value is the number of lines +actually read. The format of the returned data is discussed under "Data +formats", above. Don't forget that grayscale and color JPEGs will return +different data formats! + +Image data is returned in top-to-bottom scanline order. If you must write +out the image in bottom-to-top order, you can use the JPEG library's virtual +array mechanism to invert the data efficiently. Examples of this can be +found in the sample application djpeg. + +The library maintains a count of the number of scanlines returned so far +in the output_scanline field of the JPEG object. Usually you can just use +this variable as the loop counter, so that the loop test looks like +"while (cinfo.output_scanline < cinfo.output_height)". (Note that the test +should NOT be against image_height, unless you never use scaling. The +image_height field is the height of the original unscaled image.) +The return value always equals the change in the value of output_scanline. + +If you don't use a suspending data source, it is safe to assume that +jpeg_read_scanlines() reads at least one scanline per call, until the +bottom of the image has been reached. + +If you use a buffer larger than one scanline, it is NOT safe to assume that +jpeg_read_scanlines() fills it. (The current implementation returns only a +few scanlines per call, no matter how large a buffer you pass.) So you must +always provide a loop that calls jpeg_read_scanlines() repeatedly until the +whole image has been read. + + +7. jpeg_finish_decompress(...); + +After all the image data has been read, call jpeg_finish_decompress() to +complete the decompression cycle. This causes working memory associated +with the JPEG object to be released. + +Typical code: + + jpeg_finish_decompress(&cinfo); + +If using the stdio source manager, don't forget to close the source stdio +stream if necessary. + +It is an error to call jpeg_finish_decompress() before reading the correct +total number of scanlines. If you wish to abort decompression, call +jpeg_abort() as discussed below. + +After completing a decompression cycle, you may dispose of the JPEG object as +discussed next, or you may use it to decompress another image. In that case +return to step 2 or 3 as appropriate. If you do not change the source +manager, the next image will be read from the same source. + + +8. Release the JPEG decompression object. + +When you are done with a JPEG decompression object, destroy it by calling +jpeg_destroy_decompress() or jpeg_destroy(). The previous discussion of +destroying compression objects applies here too. + +Typical code: + + jpeg_destroy_decompress(&cinfo); + + +9. Aborting. + +You can abort a decompression cycle by calling jpeg_destroy_decompress() or +jpeg_destroy() if you don't need the JPEG object any more, or +jpeg_abort_decompress() or jpeg_abort() if you want to reuse the object. +The previous discussion of aborting compression cycles applies here too. + + +Mechanics of usage: include files, linking, etc +----------------------------------------------- + +Applications using the JPEG library should include the header file jpeglib.h +to obtain declarations of data types and routines. Before including +jpeglib.h, include system headers that define at least the typedefs FILE and +size_t. On ANSI-conforming systems, including is sufficient; on +older Unix systems, you may need to define size_t. + +If the application needs to refer to individual JPEG library error codes, also +include jerror.h to define those symbols. + +jpeglib.h indirectly includes the files jconfig.h and jmorecfg.h. If you are +installing the JPEG header files in a system directory, you will want to +install all four files: jpeglib.h, jerror.h, jconfig.h, jmorecfg.h. + +The most convenient way to include the JPEG code into your executable program +is to prepare a library file ("libjpeg.a", or a corresponding name on non-Unix +machines) and reference it at your link step. If you use only half of the +library (only compression or only decompression), only that much code will be +included from the library, unless your linker is hopelessly brain-damaged. +The supplied makefiles build libjpeg.a automatically (see install.doc). + +While you can build the JPEG library as a shared library if the whim strikes +you, we don't really recommend it. The trouble with shared libraries is that +at some point you'll probably try to substitute a new version of the library +without recompiling the calling applications. That generally doesn't work +because the parameter struct declarations usually change with each new +version. In other words, the library's API is *not* guaranteed binary +compatible across versions; we only try to ensure source-code compatibility. +(In hindsight, it might have been smarter to hide the parameter structs from +applications and introduce a ton of access functions instead. Too late now, +however.) + +On some systems your application may need to set up a signal handler to ensure +that temporary files are deleted if the program is interrupted. This is most +critical if you are on MS-DOS and use the jmemdos.c memory manager back end; +it will try to grab extended memory for temp files, and that space will NOT be +freed automatically. See cjpeg.c or djpeg.c for an example signal handler. + +It may be worth pointing out that the core JPEG library does not actually +require the stdio library: only the default source/destination managers and +error handler need it. You can use the library in a stdio-less environment +if you replace those modules and use jmemnobs.c (or another memory manager of +your own devising). More info about the minimum system library requirements +may be found in jinclude.h. + + +ADVANCED FEATURES +================= + +Compression parameter selection +------------------------------- + +This section describes all the optional parameters you can set for JPEG +compression, as well as the "helper" routines provided to assist in this +task. Proper setting of some parameters requires detailed understanding +of the JPEG standard; if you don't know what a parameter is for, it's best +not to mess with it! See REFERENCES in the README file for pointers to +more info about JPEG. + +It's a good idea to call jpeg_set_defaults() first, even if you plan to set +all the parameters; that way your code is more likely to work with future JPEG +libraries that have additional parameters. For the same reason, we recommend +you use a helper routine where one is provided, in preference to twiddling +cinfo fields directly. + +The helper routines are: + +jpeg_set_defaults (j_compress_ptr cinfo) + This routine sets all JPEG parameters to reasonable defaults, using + only the input image's color space (field in_color_space, which must + already be set in cinfo). Many applications will only need to use + this routine and perhaps jpeg_set_quality(). + +jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace) + Sets the JPEG file's colorspace (field jpeg_color_space) as specified, + and sets other color-space-dependent parameters appropriately. See + "Special color spaces", below, before using this. A large number of + parameters, including all per-component parameters, are set by this + routine; if you want to twiddle individual parameters you should call + jpeg_set_colorspace() before rather than after. + +jpeg_default_colorspace (j_compress_ptr cinfo) + Selects an appropriate JPEG colorspace based on cinfo->in_color_space, + and calls jpeg_set_colorspace(). This is actually a subroutine of + jpeg_set_defaults(). It's broken out in case you want to change + just the colorspace-dependent JPEG parameters. + +jpeg_set_quality (j_compress_ptr cinfo, int quality, boolean force_baseline) + Constructs JPEG quantization tables appropriate for the indicated + quality setting. The quality value is expressed on the 0..100 scale + recommended by IJG (cjpeg's "-quality" switch uses this routine). + Note that the exact mapping from quality values to tables may change + in future IJG releases as more is learned about DCT quantization. + If the force_baseline parameter is TRUE, then the quantization table + entries are constrained to the range 1..255 for full JPEG baseline + compatibility. In the current implementation, this only makes a + difference for quality settings below 25, and it effectively prevents + very small/low quality files from being generated. The IJG decoder + is capable of reading the non-baseline files generated at low quality + settings when force_baseline is FALSE, but other decoders may not be. + +jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor, + boolean force_baseline) + Same as jpeg_set_quality() except that the generated tables are the + sample tables given in the JPEC spec section K.1, multiplied by the + specified scale factor (which is expressed as a percentage; thus + scale_factor = 100 reproduces the spec's tables). Note that larger + scale factors give lower quality. This entry point is useful for + conforming to the Adobe PostScript DCT conventions, but we do not + recommend linear scaling as a user-visible quality scale otherwise. + force_baseline again constrains the computed table entries to 1..255. + +int jpeg_quality_scaling (int quality) + Converts a value on the IJG-recommended quality scale to a linear + scaling percentage. Note that this routine may change or go away + in future releases --- IJG may choose to adopt a scaling method that + can't be expressed as a simple scalar multiplier, in which case the + premise of this routine collapses. Caveat user. + +jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl, + const unsigned int *basic_table, + int scale_factor, boolean force_baseline) + Allows an arbitrary quantization table to be created. which_tbl + indicates which table slot to fill. basic_table points to an array + of 64 unsigned ints given in normal array order. These values are + multiplied by scale_factor/100 and then clamped to the range 1..65535 + (or to 1..255 if force_baseline is TRUE). + CAUTION: prior to library version 6a, jpeg_add_quant_table expected + the basic table to be given in JPEG zigzag order. If you need to + write code that works with either older or newer versions of this + routine, you must check the library version number. Something like + "#if JPEG_LIB_VERSION >= 61" is the right test. + +jpeg_simple_progression (j_compress_ptr cinfo) + Generates a default scan script for writing a progressive-JPEG file. + This is the recommended method of creating a progressive file, + unless you want to make a custom scan sequence. You must ensure that + the JPEG color space is set correctly before calling this routine. + + +Compression parameters (cinfo fields) include: + +J_DCT_METHOD dct_method + Selects the algorithm used for the DCT step. Choices are: + JDCT_ISLOW: slow but accurate integer algorithm + JDCT_IFAST: faster, less accurate integer method + JDCT_FLOAT: floating-point method + JDCT_DEFAULT: default method (normally JDCT_ISLOW) + JDCT_FASTEST: fastest method (normally JDCT_IFAST) + The FLOAT method is very slightly more accurate than the ISLOW method, + but may give different results on different machines due to varying + roundoff behavior. The integer methods should give the same results + on all machines. On machines with sufficiently fast FP hardware, the + floating-point method may also be the fastest. The IFAST method is + considerably less accurate than the other two; its use is not + recommended if high quality is a concern. JDCT_DEFAULT and + JDCT_FASTEST are macros configurable by each installation. + +J_COLOR_SPACE jpeg_color_space +int num_components + The JPEG color space and corresponding number of components; see + "Special color spaces", below, for more info. We recommend using + jpeg_set_color_space() if you want to change these. + +boolean optimize_coding + TRUE causes the compressor to compute optimal Huffman coding tables + for the image. This requires an extra pass over the data and + therefore costs a good deal of space and time. The default is + FALSE, which tells the compressor to use the supplied or default + Huffman tables. In most cases optimal tables save only a few percent + of file size compared to the default tables. Note that when this is + TRUE, you need not supply Huffman tables at all, and any you do + supply will be overwritten. + +unsigned int restart_interval +int restart_in_rows + To emit restart markers in the JPEG file, set one of these nonzero. + Set restart_interval to specify the exact interval in MCU blocks. + Set restart_in_rows to specify the interval in MCU rows. (If + restart_in_rows is not 0, then restart_interval is set after the + image width in MCUs is computed.) Defaults are zero (no restarts). + One restart marker per MCU row is often a good choice. + NOTE: the overhead of restart markers is higher in grayscale JPEG + files than in color files, and MUCH higher in progressive JPEGs. + If you use restarts, you may want to use larger intervals in those + cases. + +const jpeg_scan_info * scan_info +int num_scans + By default, scan_info is NULL; this causes the compressor to write a + single-scan sequential JPEG file. If not NULL, scan_info points to + an array of scan definition records of length num_scans. The + compressor will then write a JPEG file having one scan for each scan + definition record. This is used to generate noninterleaved or + progressive JPEG files. The library checks that the scan array + defines a valid JPEG scan sequence. (jpeg_simple_progression creates + a suitable scan definition array for progressive JPEG.) This is + discussed further under "Progressive JPEG support". + +int smoothing_factor + If non-zero, the input image is smoothed; the value should be 1 for + minimal smoothing to 100 for maximum smoothing. Consult jcsample.c + for details of the smoothing algorithm. The default is zero. + +boolean write_JFIF_header + If TRUE, a JFIF APP0 marker is emitted. jpeg_set_defaults() and + jpeg_set_colorspace() set this TRUE if a JFIF-legal JPEG color space + (ie, YCbCr or grayscale) is selected, otherwise FALSE. + +UINT8 JFIF_major_version +UINT8 JFIF_minor_version + The version number to be written into the JFIF marker. + jpeg_set_defaults() initializes the version to 1.01 (major=minor=1). + You should set it to 1.02 (major=1, minor=2) if you plan to write + any JFIF 1.02 extension markers. + +UINT8 density_unit +UINT16 X_density +UINT16 Y_density + The resolution information to be written into the JFIF marker; + not used otherwise. density_unit may be 0 for unknown, + 1 for dots/inch, or 2 for dots/cm. The default values are 0,1,1 + indicating square pixels of unknown size. + +boolean write_Adobe_marker + If TRUE, an Adobe APP14 marker is emitted. jpeg_set_defaults() and + jpeg_set_colorspace() set this TRUE if JPEG color space RGB, CMYK, + or YCCK is selected, otherwise FALSE. It is generally a bad idea + to set both write_JFIF_header and write_Adobe_marker. In fact, + you probably shouldn't change the default settings at all --- the + default behavior ensures that the JPEG file's color space can be + recognized by the decoder. + +JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS] + Pointers to coefficient quantization tables, one per table slot, + or NULL if no table is defined for a slot. Usually these should + be set via one of the above helper routines; jpeg_add_quant_table() + is general enough to define any quantization table. The other + routines will set up table slot 0 for luminance quality and table + slot 1 for chrominance. + +JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS] +JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS] + Pointers to Huffman coding tables, one per table slot, or NULL if + no table is defined for a slot. Slots 0 and 1 are filled with the + JPEG sample tables by jpeg_set_defaults(). If you need to allocate + more table structures, jpeg_alloc_huff_table() may be used. + Note that optimal Huffman tables can be computed for an image + by setting optimize_coding, as discussed above; there's seldom + any need to mess with providing your own Huffman tables. + +There are some additional cinfo fields which are not documented here +because you currently can't change them; for example, you can't set +arith_code TRUE because arithmetic coding is unsupported. + + +Per-component parameters are stored in the struct cinfo.comp_info[i] for +component number i. Note that components here refer to components of the +JPEG color space, *not* the source image color space. A suitably large +comp_info[] array is allocated by jpeg_set_defaults(); if you choose not +to use that routine, it's up to you to allocate the array. + +int component_id + The one-byte identifier code to be recorded in the JPEG file for + this component. For the standard color spaces, we recommend you + leave the default values alone. + +int h_samp_factor +int v_samp_factor + Horizontal and vertical sampling factors for the component; must + be 1..4 according to the JPEG standard. Note that larger sampling + factors indicate a higher-resolution component; many people find + this behavior quite unintuitive. The default values are 2,2 for + luminance components and 1,1 for chrominance components, except + for grayscale where 1,1 is used. + +int quant_tbl_no + Quantization table number for component. The default value is + 0 for luminance components and 1 for chrominance components. + +int dc_tbl_no +int ac_tbl_no + DC and AC entropy coding table numbers. The default values are + 0 for luminance components and 1 for chrominance components. + +int component_index + Must equal the component's index in comp_info[]. (Beginning in + release v6, the compressor library will fill this in automatically; + you don't have to.) + + +Decompression parameter selection +--------------------------------- + +Decompression parameter selection is somewhat simpler than compression +parameter selection, since all of the JPEG internal parameters are +recorded in the source file and need not be supplied by the application. +(Unless you are working with abbreviated files, in which case see +"Abbreviated datastreams", below.) Decompression parameters control +the postprocessing done on the image to deliver it in a format suitable +for the application's use. Many of the parameters control speed/quality +tradeoffs, in which faster decompression may be obtained at the price of +a poorer-quality image. The defaults select the highest quality (slowest) +processing. + +The following fields in the JPEG object are set by jpeg_read_header() and +may be useful to the application in choosing decompression parameters: + +JDIMENSION image_width Width and height of image +JDIMENSION image_height +int num_components Number of color components +J_COLOR_SPACE jpeg_color_space Colorspace of image +boolean saw_JFIF_marker TRUE if a JFIF APP0 marker was seen + UINT8 JFIF_major_version Version information from JFIF marker + UINT8 JFIF_minor_version + UINT8 density_unit Resolution data from JFIF marker + UINT16 X_density + UINT16 Y_density +boolean saw_Adobe_marker TRUE if an Adobe APP14 marker was seen + UINT8 Adobe_transform Color transform code from Adobe marker + +The JPEG color space, unfortunately, is something of a guess since the JPEG +standard proper does not provide a way to record it. In practice most files +adhere to the JFIF or Adobe conventions, and the decoder will recognize these +correctly. See "Special color spaces", below, for more info. + + +The decompression parameters that determine the basic properties of the +returned image are: + +J_COLOR_SPACE out_color_space + Output color space. jpeg_read_header() sets an appropriate default + based on jpeg_color_space; typically it will be RGB or grayscale. + The application can change this field to request output in a different + colorspace. For example, set it to JCS_GRAYSCALE to get grayscale + output from a color file. (This is useful for previewing: grayscale + output is faster than full color since the color components need not + be processed.) Note that not all possible color space transforms are + currently implemented; you may need to extend jdcolor.c if you want an + unusual conversion. + +unsigned int scale_num, scale_denom + Scale the image by the fraction scale_num/scale_denom. Default is + 1/1, or no scaling. Currently, the only supported scaling ratios + are 1/1, 1/2, 1/4, and 1/8. (The library design allows for arbitrary + scaling ratios but this is not likely to be implemented any time soon.) + Smaller scaling ratios permit significantly faster decoding since + fewer pixels need be processed and a simpler IDCT method can be used. + +boolean quantize_colors + If set TRUE, colormapped output will be delivered. Default is FALSE, + meaning that full-color output will be delivered. + +The next three parameters are relevant only if quantize_colors is TRUE. + +int desired_number_of_colors + Maximum number of colors to use in generating a library-supplied color + map (the actual number of colors is returned in a different field). + Default 256. Ignored when the application supplies its own color map. + +boolean two_pass_quantize + If TRUE, an extra pass over the image is made to select a custom color + map for the image. This usually looks a lot better than the one-size- + fits-all colormap that is used otherwise. Default is TRUE. Ignored + when the application supplies its own color map. + +J_DITHER_MODE dither_mode + Selects color dithering method. Supported values are: + JDITHER_NONE no dithering: fast, very low quality + JDITHER_ORDERED ordered dither: moderate speed and quality + JDITHER_FS Floyd-Steinberg dither: slow, high quality + Default is JDITHER_FS. (At present, ordered dither is implemented + only in the single-pass, standard-colormap case. If you ask for + ordered dither when two_pass_quantize is TRUE or when you supply + an external color map, you'll get F-S dithering.) + +When quantize_colors is TRUE, the target color map is described by the next +two fields. colormap is set to NULL by jpeg_read_header(). The application +can supply a color map by setting colormap non-NULL and setting +actual_number_of_colors to the map size. Otherwise, jpeg_start_decompress() +selects a suitable color map and sets these two fields itself. +[Implementation restriction: at present, an externally supplied colormap is +only accepted for 3-component output color spaces.] + +JSAMPARRAY colormap + The color map, represented as a 2-D pixel array of out_color_components + rows and actual_number_of_colors columns. Ignored if not quantizing. + CAUTION: if the JPEG library creates its own colormap, the storage + pointed to by this field is released by jpeg_finish_decompress(). + Copy the colormap somewhere else first, if you want to save it. + +int actual_number_of_colors + The number of colors in the color map. + +Additional decompression parameters that the application may set include: + +J_DCT_METHOD dct_method + Selects the algorithm used for the DCT step. Choices are the same + as described above for compression. + +boolean do_fancy_upsampling + If TRUE, do careful upsampling of chroma components. If FALSE, + a faster but sloppier method is used. Default is TRUE. The visual + impact of the sloppier method is often very small. + +boolean do_block_smoothing + If TRUE, interblock smoothing is applied in early stages of decoding + progressive JPEG files; if FALSE, not. Default is TRUE. Early + progression stages look "fuzzy" with smoothing, "blocky" without. + In any case, block smoothing ceases to be applied after the first few + AC coefficients are known to full accuracy, so it is relevant only + when using buffered-image mode for progressive images. + +boolean enable_1pass_quant +boolean enable_external_quant +boolean enable_2pass_quant + These are significant only in buffered-image mode, which is + described in its own section below. + + +The output image dimensions are given by the following fields. These are +computed from the source image dimensions and the decompression parameters +by jpeg_start_decompress(). You can also call jpeg_calc_output_dimensions() +to obtain the values that will result from the current parameter settings. +This can be useful if you are trying to pick a scaling ratio that will get +close to a desired target size. It's also important if you are using the +JPEG library's memory manager to allocate output buffer space, because you +are supposed to request such buffers *before* jpeg_start_decompress(). + +JDIMENSION output_width Actual dimensions of output image. +JDIMENSION output_height +int out_color_components Number of color components in out_color_space. +int output_components Number of color components returned. +int rec_outbuf_height Recommended height of scanline buffer. + +When quantizing colors, output_components is 1, indicating a single color map +index per pixel. Otherwise it equals out_color_components. The output arrays +are required to be output_width * output_components JSAMPLEs wide. + +rec_outbuf_height is the recommended minimum height (in scanlines) of the +buffer passed to jpeg_read_scanlines(). If the buffer is smaller, the +library will still work, but time will be wasted due to unnecessary data +copying. In high-quality modes, rec_outbuf_height is always 1, but some +faster, lower-quality modes set it to larger values (typically 2 to 4). +If you are going to ask for a high-speed processing mode, you may as well +go to the trouble of honoring rec_outbuf_height so as to avoid data copying. +(An output buffer larger than rec_outbuf_height lines is OK, but won't +provide any material speed improvement over that height.) + + +Special color spaces +-------------------- + +The JPEG standard itself is "color blind" and doesn't specify any particular +color space. It is customary to convert color data to a luminance/chrominance +color space before compressing, since this permits greater compression. The +existing de-facto JPEG file format standards specify YCbCr or grayscale data +(JFIF), or grayscale, RGB, YCbCr, CMYK, or YCCK (Adobe). For special +applications such as multispectral images, other color spaces can be used, +but it must be understood that such files will be unportable. + +The JPEG library can handle the most common colorspace conversions (namely +RGB <=> YCbCr and CMYK <=> YCCK). It can also deal with data of an unknown +color space, passing it through without conversion. If you deal extensively +with an unusual color space, you can easily extend the library to understand +additional color spaces and perform appropriate conversions. + +For compression, the source data's color space is specified by field +in_color_space. This is transformed to the JPEG file's color space given +by jpeg_color_space. jpeg_set_defaults() chooses a reasonable JPEG color +space depending on in_color_space, but you can override this by calling +jpeg_set_colorspace(). Of course you must select a supported transformation. +jccolor.c currently supports the following transformations: + RGB => YCbCr + RGB => GRAYSCALE + YCbCr => GRAYSCALE + CMYK => YCCK +plus the null transforms: GRAYSCALE => GRAYSCALE, RGB => RGB, +YCbCr => YCbCr, CMYK => CMYK, YCCK => YCCK, and UNKNOWN => UNKNOWN. + +The de-facto file format standards (JFIF and Adobe) specify APPn markers that +indicate the color space of the JPEG file. It is important to ensure that +these are written correctly, or omitted if the JPEG file's color space is not +one of the ones supported by the de-facto standards. jpeg_set_colorspace() +will set the compression parameters to include or omit the APPn markers +properly, so long as it is told the truth about the JPEG color space. +For example, if you are writing some random 3-component color space without +conversion, don't try to fake out the library by setting in_color_space and +jpeg_color_space to JCS_YCbCr; use JCS_UNKNOWN. You may want to write an +APPn marker of your own devising to identify the colorspace --- see "Special +markers", below. + +When told that the color space is UNKNOWN, the library will default to using +luminance-quality compression parameters for all color components. You may +well want to change these parameters. See the source code for +jpeg_set_colorspace(), in jcparam.c, for details. + +For decompression, the JPEG file's color space is given in jpeg_color_space, +and this is transformed to the output color space out_color_space. +jpeg_read_header's setting of jpeg_color_space can be relied on if the file +conforms to JFIF or Adobe conventions, but otherwise it is no better than a +guess. If you know the JPEG file's color space for certain, you can override +jpeg_read_header's guess by setting jpeg_color_space. jpeg_read_header also +selects a default output color space based on (its guess of) jpeg_color_space; +set out_color_space to override this. Again, you must select a supported +transformation. jdcolor.c currently supports + YCbCr => GRAYSCALE + YCbCr => RGB + GRAYSCALE => RGB + YCCK => CMYK +as well as the null transforms. (Since GRAYSCALE=>RGB is provided, an +application can force grayscale JPEGs to look like color JPEGs if it only +wants to handle one case.) + +The two-pass color quantizer, jquant2.c, is specialized to handle RGB data +(it weights distances appropriately for RGB colors). You'll need to modify +the code if you want to use it for non-RGB output color spaces. Note that +jquant2.c is used to map to an application-supplied colormap as well as for +the normal two-pass colormap selection process. + +CAUTION: it appears that Adobe Photoshop writes inverted data in CMYK JPEG +files: 0 represents 100% ink coverage, rather than 0% ink as you'd expect. +This is arguably a bug in Photoshop, but if you need to work with Photoshop +CMYK files, you will have to deal with it in your application. We cannot +"fix" this in the library by inverting the data during the CMYK<=>YCCK +transform, because that would break other applications, notably Ghostscript. +Photoshop versions prior to 3.0 write EPS files containing JPEG-encoded CMYK +data in the same inverted-YCCK representation used in bare JPEG files, but +the surrounding PostScript code performs an inversion using the PS image +operator. I am told that Photoshop 3.0 will write uninverted YCCK in +EPS/JPEG files, and will omit the PS-level inversion. (But the data +polarity used in bare JPEG files will not change in 3.0.) In either case, +the JPEG library must not invert the data itself, or else Ghostscript would +read these EPS files incorrectly. + + +Error handling +-------------- + +When the default error handler is used, any error detected inside the JPEG +routines will cause a message to be printed on stderr, followed by exit(). +You can supply your own error handling routines to override this behavior +and to control the treatment of nonfatal warnings and trace/debug messages. +The file example.c illustrates the most common case, which is to have the +application regain control after an error rather than exiting. + +The JPEG library never writes any message directly; it always goes through +the error handling routines. Three classes of messages are recognized: + * Fatal errors: the library cannot continue. + * Warnings: the library can continue, but the data is corrupt, and a + damaged output image is likely to result. + * Trace/informational messages. These come with a trace level indicating + the importance of the message; you can control the verbosity of the + program by adjusting the maximum trace level that will be displayed. + +You may, if you wish, simply replace the entire JPEG error handling module +(jerror.c) with your own code. However, you can avoid code duplication by +only replacing some of the routines depending on the behavior you need. +This is accomplished by calling jpeg_std_error() as usual, but then overriding +some of the method pointers in the jpeg_error_mgr struct, as illustrated by +example.c. + +All of the error handling routines will receive a pointer to the JPEG object +(a j_common_ptr which points to either a jpeg_compress_struct or a +jpeg_decompress_struct; if you need to tell which, test the is_decompressor +field). This struct includes a pointer to the error manager struct in its +"err" field. Frequently, custom error handler routines will need to access +additional data which is not known to the JPEG library or the standard error +handler. The most convenient way to do this is to embed either the JPEG +object or the jpeg_error_mgr struct in a larger structure that contains +additional fields; then casting the passed pointer provides access to the +additional fields. Again, see example.c for one way to do it. (Beginning +with IJG version 6b, there is also a void pointer "client_data" in each +JPEG object, which the application can also use to find related data. +The library does not touch client_data at all.) + +The individual methods that you might wish to override are: + +error_exit (j_common_ptr cinfo) + Receives control for a fatal error. Information sufficient to + generate the error message has been stored in cinfo->err; call + output_message to display it. Control must NOT return to the caller; + generally this routine will exit() or longjmp() somewhere. + Typically you would override this routine to get rid of the exit() + default behavior. Note that if you continue processing, you should + clean up the JPEG object with jpeg_abort() or jpeg_destroy(). + +output_message (j_common_ptr cinfo) + Actual output of any JPEG message. Override this to send messages + somewhere other than stderr. Note that this method does not know + how to generate a message, only where to send it. + +format_message (j_common_ptr cinfo, char * buffer) + Constructs a readable error message string based on the error info + stored in cinfo->err. This method is called by output_message. Few + applications should need to override this method. One possible + reason for doing so is to implement dynamic switching of error message + language. + +emit_message (j_common_ptr cinfo, int msg_level) + Decide whether or not to emit a warning or trace message; if so, + calls output_message. The main reason for overriding this method + would be to abort on warnings. msg_level is -1 for warnings, + 0 and up for trace messages. + +Only error_exit() and emit_message() are called from the rest of the JPEG +library; the other two are internal to the error handler. + +The actual message texts are stored in an array of strings which is pointed to +by the field err->jpeg_message_table. The messages are numbered from 0 to +err->last_jpeg_message, and it is these code numbers that are used in the +JPEG library code. You could replace the message texts (for instance, with +messages in French or German) by changing the message table pointer. See +jerror.h for the default texts. CAUTION: this table will almost certainly +change or grow from one library version to the next. + +It may be useful for an application to add its own message texts that are +handled by the same mechanism. The error handler supports a second "add-on" +message table for this purpose. To define an addon table, set the pointer +err->addon_message_table and the message numbers err->first_addon_message and +err->last_addon_message. If you number the addon messages beginning at 1000 +or so, you won't have to worry about conflicts with the library's built-in +messages. See the sample applications cjpeg/djpeg for an example of using +addon messages (the addon messages are defined in cderror.h). + +Actual invocation of the error handler is done via macros defined in jerror.h: + ERREXITn(...) for fatal errors + WARNMSn(...) for corrupt-data warnings + TRACEMSn(...) for trace and informational messages. +These macros store the message code and any additional parameters into the +error handler struct, then invoke the error_exit() or emit_message() method. +The variants of each macro are for varying numbers of additional parameters. +The additional parameters are inserted into the generated message using +standard printf() format codes. + +See jerror.h and jerror.c for further details. + + +Compressed data handling (source and destination managers) +---------------------------------------------------------- + +The JPEG compression library sends its compressed data to a "destination +manager" module. The default destination manager just writes the data to a +stdio stream, but you can provide your own manager to do something else. +Similarly, the decompression library calls a "source manager" to obtain the +compressed data; you can provide your own source manager if you want the data +to come from somewhere other than a stdio stream. + +In both cases, compressed data is processed a bufferload at a time: the +destination or source manager provides a work buffer, and the library invokes +the manager only when the buffer is filled or emptied. (You could define a +one-character buffer to force the manager to be invoked for each byte, but +that would be rather inefficient.) The buffer's size and location are +controlled by the manager, not by the library. For example, if you desired to +decompress a JPEG datastream that was all in memory, you could just make the +buffer pointer and length point to the original data in memory. Then the +buffer-reload procedure would be invoked only if the decompressor ran off the +end of the datastream, which would indicate an erroneous datastream. + +The work buffer is defined as an array of datatype JOCTET, which is generally +"char" or "unsigned char". On a machine where char is not exactly 8 bits +wide, you must define JOCTET as a wider data type and then modify the data +source and destination modules to transcribe the work arrays into 8-bit units +on external storage. + +A data destination manager struct contains a pointer and count defining the +next byte to write in the work buffer and the remaining free space: + + JOCTET * next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + +The library increments the pointer and decrements the count until the buffer +is filled. The manager's empty_output_buffer method must reset the pointer +and count. The manager is expected to remember the buffer's starting address +and total size in private fields not visible to the library. + +A data destination manager provides three methods: + +init_destination (j_compress_ptr cinfo) + Initialize destination. This is called by jpeg_start_compress() + before any data is actually written. It must initialize + next_output_byte and free_in_buffer. free_in_buffer must be + initialized to a positive value. + +empty_output_buffer (j_compress_ptr cinfo) + This is called whenever the buffer has filled (free_in_buffer + reaches zero). In typical applications, it should write out the + *entire* buffer (use the saved start address and buffer length; + ignore the current state of next_output_byte and free_in_buffer). + Then reset the pointer & count to the start of the buffer, and + return TRUE indicating that the buffer has been dumped. + free_in_buffer must be set to a positive value when TRUE is + returned. A FALSE return should only be used when I/O suspension is + desired (this operating mode is discussed in the next section). + +term_destination (j_compress_ptr cinfo) + Terminate destination --- called by jpeg_finish_compress() after all + data has been written. In most applications, this must flush any + data remaining in the buffer. Use either next_output_byte or + free_in_buffer to determine how much data is in the buffer. + +term_destination() is NOT called by jpeg_abort() or jpeg_destroy(). If you +want the destination manager to be cleaned up during an abort, you must do it +yourself. + +You will also need code to create a jpeg_destination_mgr struct, fill in its +method pointers, and insert a pointer to the struct into the "dest" field of +the JPEG compression object. This can be done in-line in your setup code if +you like, but it's probably cleaner to provide a separate routine similar to +the jpeg_stdio_dest() routine of the supplied destination manager. + +Decompression source managers follow a parallel design, but with some +additional frammishes. The source manager struct contains a pointer and count +defining the next byte to read from the work buffer and the number of bytes +remaining: + + const JOCTET * next_input_byte; /* => next byte to read from buffer */ + size_t bytes_in_buffer; /* # of bytes remaining in buffer */ + +The library increments the pointer and decrements the count until the buffer +is emptied. The manager's fill_input_buffer method must reset the pointer and +count. In most applications, the manager must remember the buffer's starting +address and total size in private fields not visible to the library. + +A data source manager provides five methods: + +init_source (j_decompress_ptr cinfo) + Initialize source. This is called by jpeg_read_header() before any + data is actually read. Unlike init_destination(), it may leave + bytes_in_buffer set to 0 (in which case a fill_input_buffer() call + will occur immediately). + +fill_input_buffer (j_decompress_ptr cinfo) + This is called whenever bytes_in_buffer has reached zero and more + data is wanted. In typical applications, it should read fresh data + into the buffer (ignoring the current state of next_input_byte and + bytes_in_buffer), reset the pointer & count to the start of the + buffer, and return TRUE indicating that the buffer has been reloaded. + It is not necessary to fill the buffer entirely, only to obtain at + least one more byte. bytes_in_buffer MUST be set to a positive value + if TRUE is returned. A FALSE return should only be used when I/O + suspension is desired (this mode is discussed in the next section). + +skip_input_data (j_decompress_ptr cinfo, long num_bytes) + Skip num_bytes worth of data. The buffer pointer and count should + be advanced over num_bytes input bytes, refilling the buffer as + needed. This is used to skip over a potentially large amount of + uninteresting data (such as an APPn marker). In some applications + it may be possible to optimize away the reading of the skipped data, + but it's not clear that being smart is worth much trouble; large + skips are uncommon. bytes_in_buffer may be zero on return. + A zero or negative skip count should be treated as a no-op. + +resync_to_restart (j_decompress_ptr cinfo, int desired) + This routine is called only when the decompressor has failed to find + a restart (RSTn) marker where one is expected. Its mission is to + find a suitable point for resuming decompression. For most + applications, we recommend that you just use the default resync + procedure, jpeg_resync_to_restart(). However, if you are able to back + up in the input data stream, or if you have a-priori knowledge about + the likely location of restart markers, you may be able to do better. + Read the read_restart_marker() and jpeg_resync_to_restart() routines + in jdmarker.c if you think you'd like to implement your own resync + procedure. + +term_source (j_decompress_ptr cinfo) + Terminate source --- called by jpeg_finish_decompress() after all + data has been read. Often a no-op. + +For both fill_input_buffer() and skip_input_data(), there is no such thing +as an EOF return. If the end of the file has been reached, the routine has +a choice of exiting via ERREXIT() or inserting fake data into the buffer. +In most cases, generating a warning message and inserting a fake EOI marker +is the best course of action --- this will allow the decompressor to output +however much of the image is there. In pathological cases, the decompressor +may swallow the EOI and again demand data ... just keep feeding it fake EOIs. +jdatasrc.c illustrates the recommended error recovery behavior. + +term_source() is NOT called by jpeg_abort() or jpeg_destroy(). If you want +the source manager to be cleaned up during an abort, you must do it yourself. + +You will also need code to create a jpeg_source_mgr struct, fill in its method +pointers, and insert a pointer to the struct into the "src" field of the JPEG +decompression object. This can be done in-line in your setup code if you +like, but it's probably cleaner to provide a separate routine similar to the +jpeg_stdio_src() routine of the supplied source manager. + +For more information, consult the stdio source and destination managers +in jdatasrc.c and jdatadst.c. + + +I/O suspension +-------------- + +Some applications need to use the JPEG library as an incremental memory-to- +memory filter: when the compressed data buffer is filled or emptied, they want +control to return to the outer loop, rather than expecting that the buffer can +be emptied or reloaded within the data source/destination manager subroutine. +The library supports this need by providing an "I/O suspension" mode, which we +describe in this section. + +The I/O suspension mode is not a panacea: nothing is guaranteed about the +maximum amount of time spent in any one call to the library, so it will not +eliminate response-time problems in single-threaded applications. If you +need guaranteed response time, we suggest you "bite the bullet" and implement +a real multi-tasking capability. + +To use I/O suspension, cooperation is needed between the calling application +and the data source or destination manager; you will always need a custom +source/destination manager. (Please read the previous section if you haven't +already.) The basic idea is that the empty_output_buffer() or +fill_input_buffer() routine is a no-op, merely returning FALSE to indicate +that it has done nothing. Upon seeing this, the JPEG library suspends +operation and returns to its caller. The surrounding application is +responsible for emptying or refilling the work buffer before calling the +JPEG library again. + +Compression suspension: + +For compression suspension, use an empty_output_buffer() routine that returns +FALSE; typically it will not do anything else. This will cause the +compressor to return to the caller of jpeg_write_scanlines(), with the return +value indicating that not all the supplied scanlines have been accepted. +The application must make more room in the output buffer, adjust the output +buffer pointer/count appropriately, and then call jpeg_write_scanlines() +again, pointing to the first unconsumed scanline. + +When forced to suspend, the compressor will backtrack to a convenient stopping +point (usually the start of the current MCU); it will regenerate some output +data when restarted. Therefore, although empty_output_buffer() is only +called when the buffer is filled, you should NOT write out the entire buffer +after a suspension. Write only the data up to the current position of +next_output_byte/free_in_buffer. The data beyond that point will be +regenerated after resumption. + +Because of the backtracking behavior, a good-size output buffer is essential +for efficiency; you don't want the compressor to suspend often. (In fact, an +overly small buffer could lead to infinite looping, if a single MCU required +more data than would fit in the buffer.) We recommend a buffer of at least +several Kbytes. You may want to insert explicit code to ensure that you don't +call jpeg_write_scanlines() unless there is a reasonable amount of space in +the output buffer; in other words, flush the buffer before trying to compress +more data. + +The compressor does not allow suspension while it is trying to write JPEG +markers at the beginning and end of the file. This means that: + * At the beginning of a compression operation, there must be enough free + space in the output buffer to hold the header markers (typically 600 or + so bytes). The recommended buffer size is bigger than this anyway, so + this is not a problem as long as you start with an empty buffer. However, + this restriction might catch you if you insert large special markers, such + as a JFIF thumbnail image, without flushing the buffer afterwards. + * When you call jpeg_finish_compress(), there must be enough space in the + output buffer to emit any buffered data and the final EOI marker. In the + current implementation, half a dozen bytes should suffice for this, but + for safety's sake we recommend ensuring that at least 100 bytes are free + before calling jpeg_finish_compress(). + +A more significant restriction is that jpeg_finish_compress() cannot suspend. +This means you cannot use suspension with multi-pass operating modes, namely +Huffman code optimization and multiple-scan output. Those modes write the +whole file during jpeg_finish_compress(), which will certainly result in +buffer overrun. (Note that this restriction applies only to compression, +not decompression. The decompressor supports input suspension in all of its +operating modes.) + +Decompression suspension: + +For decompression suspension, use a fill_input_buffer() routine that simply +returns FALSE (except perhaps during error recovery, as discussed below). +This will cause the decompressor to return to its caller with an indication +that suspension has occurred. This can happen at four places: + * jpeg_read_header(): will return JPEG_SUSPENDED. + * jpeg_start_decompress(): will return FALSE, rather than its usual TRUE. + * jpeg_read_scanlines(): will return the number of scanlines already + completed (possibly 0). + * jpeg_finish_decompress(): will return FALSE, rather than its usual TRUE. +The surrounding application must recognize these cases, load more data into +the input buffer, and repeat the call. In the case of jpeg_read_scanlines(), +increment the passed pointers past any scanlines successfully read. + +Just as with compression, the decompressor will typically backtrack to a +convenient restart point before suspending. When fill_input_buffer() is +called, next_input_byte/bytes_in_buffer point to the current restart point, +which is where the decompressor will backtrack to if FALSE is returned. +The data beyond that position must NOT be discarded if you suspend; it needs +to be re-read upon resumption. In most implementations, you'll need to shift +this data down to the start of your work buffer and then load more data after +it. Again, this behavior means that a several-Kbyte work buffer is essential +for decent performance; furthermore, you should load a reasonable amount of +new data before resuming decompression. (If you loaded, say, only one new +byte each time around, you could waste a LOT of cycles.) + +The skip_input_data() source manager routine requires special care in a +suspension scenario. This routine is NOT granted the ability to suspend the +decompressor; it can decrement bytes_in_buffer to zero, but no more. If the +requested skip distance exceeds the amount of data currently in the input +buffer, then skip_input_data() must set bytes_in_buffer to zero and record the +additional skip distance somewhere else. The decompressor will immediately +call fill_input_buffer(), which should return FALSE, which will cause a +suspension return. The surrounding application must then arrange to discard +the recorded number of bytes before it resumes loading the input buffer. +(Yes, this design is rather baroque, but it avoids complexity in the far more +common case where a non-suspending source manager is used.) + +If the input data has been exhausted, we recommend that you emit a warning +and insert dummy EOI markers just as a non-suspending data source manager +would do. This can be handled either in the surrounding application logic or +within fill_input_buffer(); the latter is probably more efficient. If +fill_input_buffer() knows that no more data is available, it can set the +pointer/count to point to a dummy EOI marker and then return TRUE just as +though it had read more data in a non-suspending situation. + +The decompressor does not attempt to suspend within standard JPEG markers; +instead it will backtrack to the start of the marker and reprocess the whole +marker next time. Hence the input buffer must be large enough to hold the +longest standard marker in the file. Standard JPEG markers should normally +not exceed a few hundred bytes each (DHT tables are typically the longest). +We recommend at least a 2K buffer for performance reasons, which is much +larger than any correct marker is likely to be. For robustness against +damaged marker length counts, you may wish to insert a test in your +application for the case that the input buffer is completely full and yet +the decoder has suspended without consuming any data --- otherwise, if this +situation did occur, it would lead to an endless loop. (The library can't +provide this test since it has no idea whether "the buffer is full", or +even whether there is a fixed-size input buffer.) + +The input buffer would need to be 64K to allow for arbitrary COM or APPn +markers, but these are handled specially: they are either saved into allocated +memory, or skipped over by calling skip_input_data(). In the former case, +suspension is handled correctly, and in the latter case, the problem of +buffer overrun is placed on skip_input_data's shoulders, as explained above. +Note that if you provide your own marker handling routine for large markers, +you should consider how to deal with buffer overflow. + +Multiple-buffer management: + +In some applications it is desirable to store the compressed data in a linked +list of buffer areas, so as to avoid data copying. This can be handled by +having empty_output_buffer() or fill_input_buffer() set the pointer and count +to reference the next available buffer; FALSE is returned only if no more +buffers are available. Although seemingly straightforward, there is a +pitfall in this approach: the backtrack that occurs when FALSE is returned +could back up into an earlier buffer. For example, when fill_input_buffer() +is called, the current pointer & count indicate the backtrack restart point. +Since fill_input_buffer() will set the pointer and count to refer to a new +buffer, the restart position must be saved somewhere else. Suppose a second +call to fill_input_buffer() occurs in the same library call, and no +additional input data is available, so fill_input_buffer must return FALSE. +If the JPEG library has not moved the pointer/count forward in the current +buffer, then *the correct restart point is the saved position in the prior +buffer*. Prior buffers may be discarded only after the library establishes +a restart point within a later buffer. Similar remarks apply for output into +a chain of buffers. + +The library will never attempt to backtrack over a skip_input_data() call, +so any skipped data can be permanently discarded. You still have to deal +with the case of skipping not-yet-received data, however. + +It's much simpler to use only a single buffer; when fill_input_buffer() is +called, move any unconsumed data (beyond the current pointer/count) down to +the beginning of this buffer and then load new data into the remaining buffer +space. This approach requires a little more data copying but is far easier +to get right. + + +Progressive JPEG support +------------------------ + +Progressive JPEG rearranges the stored data into a series of scans of +increasing quality. In situations where a JPEG file is transmitted across a +slow communications link, a decoder can generate a low-quality image very +quickly from the first scan, then gradually improve the displayed quality as +more scans are received. The final image after all scans are complete is +identical to that of a regular (sequential) JPEG file of the same quality +setting. Progressive JPEG files are often slightly smaller than equivalent +sequential JPEG files, but the possibility of incremental display is the main +reason for using progressive JPEG. + +The IJG encoder library generates progressive JPEG files when given a +suitable "scan script" defining how to divide the data into scans. +Creation of progressive JPEG files is otherwise transparent to the encoder. +Progressive JPEG files can also be read transparently by the decoder library. +If the decoding application simply uses the library as defined above, it +will receive a final decoded image without any indication that the file was +progressive. Of course, this approach does not allow incremental display. +To perform incremental display, an application needs to use the decoder +library's "buffered-image" mode, in which it receives a decoded image +multiple times. + +Each displayed scan requires about as much work to decode as a full JPEG +image of the same size, so the decoder must be fairly fast in relation to the +data transmission rate in order to make incremental display useful. However, +it is possible to skip displaying the image and simply add the incoming bits +to the decoder's coefficient buffer. This is fast because only Huffman +decoding need be done, not IDCT, upsampling, colorspace conversion, etc. +The IJG decoder library allows the application to switch dynamically between +displaying the image and simply absorbing the incoming bits. A properly +coded application can automatically adapt the number of display passes to +suit the time available as the image is received. Also, a final +higher-quality display cycle can be performed from the buffered data after +the end of the file is reached. + +Progressive compression: + +To create a progressive JPEG file (or a multiple-scan sequential JPEG file), +set the scan_info cinfo field to point to an array of scan descriptors, and +perform compression as usual. Instead of constructing your own scan list, +you can call the jpeg_simple_progression() helper routine to create a +recommended progression sequence; this method should be used by all +applications that don't want to get involved in the nitty-gritty of +progressive scan sequence design. (If you want to provide user control of +scan sequences, you may wish to borrow the scan script reading code found +in rdswitch.c, so that you can read scan script files just like cjpeg's.) +When scan_info is not NULL, the compression library will store DCT'd data +into a buffer array as jpeg_write_scanlines() is called, and will emit all +the requested scans during jpeg_finish_compress(). This implies that +multiple-scan output cannot be created with a suspending data destination +manager, since jpeg_finish_compress() does not support suspension. We +should also note that the compressor currently forces Huffman optimization +mode when creating a progressive JPEG file, because the default Huffman +tables are unsuitable for progressive files. + +Progressive decompression: + +When buffered-image mode is not used, the decoder library will read all of +a multi-scan file during jpeg_start_decompress(), so that it can provide a +final decoded image. (Here "multi-scan" means either progressive or +multi-scan sequential.) This makes multi-scan files transparent to the +decoding application. However, existing applications that used suspending +input with version 5 of the IJG library will need to be modified to check +for a suspension return from jpeg_start_decompress(). + +To perform incremental display, an application must use the library's +buffered-image mode. This is described in the next section. + + +Buffered-image mode +------------------- + +In buffered-image mode, the library stores the partially decoded image in a +coefficient buffer, from which it can be read out as many times as desired. +This mode is typically used for incremental display of progressive JPEG files, +but it can be used with any JPEG file. Each scan of a progressive JPEG file +adds more data (more detail) to the buffered image. The application can +display in lockstep with the source file (one display pass per input scan), +or it can allow input processing to outrun display processing. By making +input and display processing run independently, it is possible for the +application to adapt progressive display to a wide range of data transmission +rates. + +The basic control flow for buffered-image decoding is + + jpeg_create_decompress() + set data source + jpeg_read_header() + set overall decompression parameters + cinfo.buffered_image = TRUE; /* select buffered-image mode */ + jpeg_start_decompress() + for (each output pass) { + adjust output decompression parameters if required + jpeg_start_output() /* start a new output pass */ + for (all scanlines in image) { + jpeg_read_scanlines() + display scanlines + } + jpeg_finish_output() /* terminate output pass */ + } + jpeg_finish_decompress() + jpeg_destroy_decompress() + +This differs from ordinary unbuffered decoding in that there is an additional +level of looping. The application can choose how many output passes to make +and how to display each pass. + +The simplest approach to displaying progressive images is to do one display +pass for each scan appearing in the input file. In this case the outer loop +condition is typically + while (! jpeg_input_complete(&cinfo)) +and the start-output call should read + jpeg_start_output(&cinfo, cinfo.input_scan_number); +The second parameter to jpeg_start_output() indicates which scan of the input +file is to be displayed; the scans are numbered starting at 1 for this +purpose. (You can use a loop counter starting at 1 if you like, but using +the library's input scan counter is easier.) The library automatically reads +data as necessary to complete each requested scan, and jpeg_finish_output() +advances to the next scan or end-of-image marker (hence input_scan_number +will be incremented by the time control arrives back at jpeg_start_output()). +With this technique, data is read from the input file only as needed, and +input and output processing run in lockstep. + +After reading the final scan and reaching the end of the input file, the +buffered image remains available; it can be read additional times by +repeating the jpeg_start_output()/jpeg_read_scanlines()/jpeg_finish_output() +sequence. For example, a useful technique is to use fast one-pass color +quantization for display passes made while the image is arriving, followed by +a final display pass using two-pass quantization for highest quality. This +is done by changing the library parameters before the final output pass. +Changing parameters between passes is discussed in detail below. + +In general the last scan of a progressive file cannot be recognized as such +until after it is read, so a post-input display pass is the best approach if +you want special processing in the final pass. + +When done with the image, be sure to call jpeg_finish_decompress() to release +the buffered image (or just use jpeg_destroy_decompress()). + +If input data arrives faster than it can be displayed, the application can +cause the library to decode input data in advance of what's needed to produce +output. This is done by calling the routine jpeg_consume_input(). +The return value is one of the following: + JPEG_REACHED_SOS: reached an SOS marker (the start of a new scan) + JPEG_REACHED_EOI: reached the EOI marker (end of image) + JPEG_ROW_COMPLETED: completed reading one MCU row of compressed data + JPEG_SCAN_COMPLETED: completed reading last MCU row of current scan + JPEG_SUSPENDED: suspended before completing any of the above +(JPEG_SUSPENDED can occur only if a suspending data source is used.) This +routine can be called at any time after initializing the JPEG object. It +reads some additional data and returns when one of the indicated significant +events occurs. (If called after the EOI marker is reached, it will +immediately return JPEG_REACHED_EOI without attempting to read more data.) + +The library's output processing will automatically call jpeg_consume_input() +whenever the output processing overtakes the input; thus, simple lockstep +display requires no direct calls to jpeg_consume_input(). But by adding +calls to jpeg_consume_input(), you can absorb data in advance of what is +being displayed. This has two benefits: + * You can limit buildup of unprocessed data in your input buffer. + * You can eliminate extra display passes by paying attention to the + state of the library's input processing. + +The first of these benefits only requires interspersing calls to +jpeg_consume_input() with your display operations and any other processing +you may be doing. To avoid wasting cycles due to backtracking, it's best to +call jpeg_consume_input() only after a hundred or so new bytes have arrived. +This is discussed further under "I/O suspension", above. (Note: the JPEG +library currently is not thread-safe. You must not call jpeg_consume_input() +from one thread of control if a different library routine is working on the +same JPEG object in another thread.) + +When input arrives fast enough that more than one new scan is available +before you start a new output pass, you may as well skip the output pass +corresponding to the completed scan. This occurs for free if you pass +cinfo.input_scan_number as the target scan number to jpeg_start_output(). +The input_scan_number field is simply the index of the scan currently being +consumed by the input processor. You can ensure that this is up-to-date by +emptying the input buffer just before calling jpeg_start_output(): call +jpeg_consume_input() repeatedly until it returns JPEG_SUSPENDED or +JPEG_REACHED_EOI. + +The target scan number passed to jpeg_start_output() is saved in the +cinfo.output_scan_number field. The library's output processing calls +jpeg_consume_input() whenever the current input scan number and row within +that scan is less than or equal to the current output scan number and row. +Thus, input processing can "get ahead" of the output processing but is not +allowed to "fall behind". You can achieve several different effects by +manipulating this interlock rule. For example, if you pass a target scan +number greater than the current input scan number, the output processor will +wait until that scan starts to arrive before producing any output. (To avoid +an infinite loop, the target scan number is automatically reset to the last +scan number when the end of image is reached. Thus, if you specify a large +target scan number, the library will just absorb the entire input file and +then perform an output pass. This is effectively the same as what +jpeg_start_decompress() does when you don't select buffered-image mode.) +When you pass a target scan number equal to the current input scan number, +the image is displayed no faster than the current input scan arrives. The +final possibility is to pass a target scan number less than the current input +scan number; this disables the input/output interlock and causes the output +processor to simply display whatever it finds in the image buffer, without +waiting for input. (However, the library will not accept a target scan +number less than one, so you can't avoid waiting for the first scan.) + +When data is arriving faster than the output display processing can advance +through the image, jpeg_consume_input() will store data into the buffered +image beyond the point at which the output processing is reading data out +again. If the input arrives fast enough, it may "wrap around" the buffer to +the point where the input is more than one whole scan ahead of the output. +If the output processing simply proceeds through its display pass without +paying attention to the input, the effect seen on-screen is that the lower +part of the image is one or more scans better in quality than the upper part. +Then, when the next output scan is started, you have a choice of what target +scan number to use. The recommended choice is to use the current input scan +number at that time, which implies that you've skipped the output scans +corresponding to the input scans that were completed while you processed the +previous output scan. In this way, the decoder automatically adapts its +speed to the arriving data, by skipping output scans as necessary to keep up +with the arriving data. + +When using this strategy, you'll want to be sure that you perform a final +output pass after receiving all the data; otherwise your last display may not +be full quality across the whole screen. So the right outer loop logic is +something like this: + do { + absorb any waiting input by calling jpeg_consume_input() + final_pass = jpeg_input_complete(&cinfo); + adjust output decompression parameters if required + jpeg_start_output(&cinfo, cinfo.input_scan_number); + ... + jpeg_finish_output() + } while (! final_pass); +rather than quitting as soon as jpeg_input_complete() returns TRUE. This +arrangement makes it simple to use higher-quality decoding parameters +for the final pass. But if you don't want to use special parameters for +the final pass, the right loop logic is like this: + for (;;) { + absorb any waiting input by calling jpeg_consume_input() + jpeg_start_output(&cinfo, cinfo.input_scan_number); + ... + jpeg_finish_output() + if (jpeg_input_complete(&cinfo) && + cinfo.input_scan_number == cinfo.output_scan_number) + break; + } +In this case you don't need to know in advance whether an output pass is to +be the last one, so it's not necessary to have reached EOF before starting +the final output pass; rather, what you want to test is whether the output +pass was performed in sync with the final input scan. This form of the loop +will avoid an extra output pass whenever the decoder is able (or nearly able) +to keep up with the incoming data. + +When the data transmission speed is high, you might begin a display pass, +then find that much or all of the file has arrived before you can complete +the pass. (You can detect this by noting the JPEG_REACHED_EOI return code +from jpeg_consume_input(), or equivalently by testing jpeg_input_complete().) +In this situation you may wish to abort the current display pass and start a +new one using the newly arrived information. To do so, just call +jpeg_finish_output() and then start a new pass with jpeg_start_output(). + +A variant strategy is to abort and restart display if more than one complete +scan arrives during an output pass; this can be detected by noting +JPEG_REACHED_SOS returns and/or examining cinfo.input_scan_number. This +idea should be employed with caution, however, since the display process +might never get to the bottom of the image before being aborted, resulting +in the lower part of the screen being several passes worse than the upper. +In most cases it's probably best to abort an output pass only if the whole +file has arrived and you want to begin the final output pass immediately. + +When receiving data across a communication link, we recommend always using +the current input scan number for the output target scan number; if a +higher-quality final pass is to be done, it should be started (aborting any +incomplete output pass) as soon as the end of file is received. However, +many other strategies are possible. For example, the application can examine +the parameters of the current input scan and decide whether to display it or +not. If the scan contains only chroma data, one might choose not to use it +as the target scan, expecting that the scan will be small and will arrive +quickly. To skip to the next scan, call jpeg_consume_input() until it +returns JPEG_REACHED_SOS or JPEG_REACHED_EOI. Or just use the next higher +number as the target scan for jpeg_start_output(); but that method doesn't +let you inspect the next scan's parameters before deciding to display it. + + +In buffered-image mode, jpeg_start_decompress() never performs input and +thus never suspends. An application that uses input suspension with +buffered-image mode must be prepared for suspension returns from these +routines: +* jpeg_start_output() performs input only if you request 2-pass quantization + and the target scan isn't fully read yet. (This is discussed below.) +* jpeg_read_scanlines(), as always, returns the number of scanlines that it + was able to produce before suspending. +* jpeg_finish_output() will read any markers following the target scan, + up to the end of the file or the SOS marker that begins another scan. + (But it reads no input if jpeg_consume_input() has already reached the + end of the file or a SOS marker beyond the target output scan.) +* jpeg_finish_decompress() will read until the end of file, and thus can + suspend if the end hasn't already been reached (as can be tested by + calling jpeg_input_complete()). +jpeg_start_output(), jpeg_finish_output(), and jpeg_finish_decompress() +all return TRUE if they completed their tasks, FALSE if they had to suspend. +In the event of a FALSE return, the application must load more input data +and repeat the call. Applications that use non-suspending data sources need +not check the return values of these three routines. + + +It is possible to change decoding parameters between output passes in the +buffered-image mode. The decoder library currently supports only very +limited changes of parameters. ONLY THE FOLLOWING parameter changes are +allowed after jpeg_start_decompress() is called: +* dct_method can be changed before each call to jpeg_start_output(). + For example, one could use a fast DCT method for early scans, changing + to a higher quality method for the final scan. +* dither_mode can be changed before each call to jpeg_start_output(); + of course this has no impact if not using color quantization. Typically + one would use ordered dither for initial passes, then switch to + Floyd-Steinberg dither for the final pass. Caution: changing dither mode + can cause more memory to be allocated by the library. Although the amount + of memory involved is not large (a scanline or so), it may cause the + initial max_memory_to_use specification to be exceeded, which in the worst + case would result in an out-of-memory failure. +* do_block_smoothing can be changed before each call to jpeg_start_output(). + This setting is relevant only when decoding a progressive JPEG image. + During the first DC-only scan, block smoothing provides a very "fuzzy" look + instead of the very "blocky" look seen without it; which is better seems a + matter of personal taste. But block smoothing is nearly always a win + during later stages, especially when decoding a successive-approximation + image: smoothing helps to hide the slight blockiness that otherwise shows + up on smooth gradients until the lowest coefficient bits are sent. +* Color quantization mode can be changed under the rules described below. + You *cannot* change between full-color and quantized output (because that + would alter the required I/O buffer sizes), but you can change which + quantization method is used. + +When generating color-quantized output, changing quantization method is a +very useful way of switching between high-speed and high-quality display. +The library allows you to change among its three quantization methods: +1. Single-pass quantization to a fixed color cube. + Selected by cinfo.two_pass_quantize = FALSE and cinfo.colormap = NULL. +2. Single-pass quantization to an application-supplied colormap. + Selected by setting cinfo.colormap to point to the colormap (the value of + two_pass_quantize is ignored); also set cinfo.actual_number_of_colors. +3. Two-pass quantization to a colormap chosen specifically for the image. + Selected by cinfo.two_pass_quantize = TRUE and cinfo.colormap = NULL. + (This is the default setting selected by jpeg_read_header, but it is + probably NOT what you want for the first pass of progressive display!) +These methods offer successively better quality and lesser speed. However, +only the first method is available for quantizing in non-RGB color spaces. + +IMPORTANT: because the different quantizer methods have very different +working-storage requirements, the library requires you to indicate which +one(s) you intend to use before you call jpeg_start_decompress(). (If we did +not require this, the max_memory_to_use setting would be a complete fiction.) +You do this by setting one or more of these three cinfo fields to TRUE: + enable_1pass_quant Fixed color cube colormap + enable_external_quant Externally-supplied colormap + enable_2pass_quant Two-pass custom colormap +All three are initialized FALSE by jpeg_read_header(). But +jpeg_start_decompress() automatically sets TRUE the one selected by the +current two_pass_quantize and colormap settings, so you only need to set the +enable flags for any other quantization methods you plan to change to later. + +After setting the enable flags correctly at jpeg_start_decompress() time, you +can change to any enabled quantization method by setting two_pass_quantize +and colormap properly just before calling jpeg_start_output(). The following +special rules apply: +1. You must explicitly set cinfo.colormap to NULL when switching to 1-pass + or 2-pass mode from a different mode, or when you want the 2-pass + quantizer to be re-run to generate a new colormap. +2. To switch to an external colormap, or to change to a different external + colormap than was used on the prior pass, you must call + jpeg_new_colormap() after setting cinfo.colormap. +NOTE: if you want to use the same colormap as was used in the prior pass, +you should not do either of these things. This will save some nontrivial +switchover costs. +(These requirements exist because cinfo.colormap will always be non-NULL +after completing a prior output pass, since both the 1-pass and 2-pass +quantizers set it to point to their output colormaps. Thus you have to +do one of these two things to notify the library that something has changed. +Yup, it's a bit klugy, but it's necessary to do it this way for backwards +compatibility.) + +Note that in buffered-image mode, the library generates any requested colormap +during jpeg_start_output(), not during jpeg_start_decompress(). + +When using two-pass quantization, jpeg_start_output() makes a pass over the +buffered image to determine the optimum color map; it therefore may take a +significant amount of time, whereas ordinarily it does little work. The +progress monitor hook is called during this pass, if defined. It is also +important to realize that if the specified target scan number is greater than +or equal to the current input scan number, jpeg_start_output() will attempt +to consume input as it makes this pass. If you use a suspending data source, +you need to check for a FALSE return from jpeg_start_output() under these +conditions. The combination of 2-pass quantization and a not-yet-fully-read +target scan is the only case in which jpeg_start_output() will consume input. + + +Application authors who support buffered-image mode may be tempted to use it +for all JPEG images, even single-scan ones. This will work, but it is +inefficient: there is no need to create an image-sized coefficient buffer for +single-scan images. Requesting buffered-image mode for such an image wastes +memory. Worse, it can cost time on large images, since the buffered data has +to be swapped out or written to a temporary file. If you are concerned about +maximum performance on baseline JPEG files, you should use buffered-image +mode only when the incoming file actually has multiple scans. This can be +tested by calling jpeg_has_multiple_scans(), which will return a correct +result at any time after jpeg_read_header() completes. + +It is also worth noting that when you use jpeg_consume_input() to let input +processing get ahead of output processing, the resulting pattern of access to +the coefficient buffer is quite nonsequential. It's best to use the memory +manager jmemnobs.c if you can (ie, if you have enough real or virtual main +memory). If not, at least make sure that max_memory_to_use is set as high as +possible. If the JPEG memory manager has to use a temporary file, you will +probably see a lot of disk traffic and poor performance. (This could be +improved with additional work on the memory manager, but we haven't gotten +around to it yet.) + +In some applications it may be convenient to use jpeg_consume_input() for all +input processing, including reading the initial markers; that is, you may +wish to call jpeg_consume_input() instead of jpeg_read_header() during +startup. This works, but note that you must check for JPEG_REACHED_SOS and +JPEG_REACHED_EOI return codes as the equivalent of jpeg_read_header's codes. +Once the first SOS marker has been reached, you must call +jpeg_start_decompress() before jpeg_consume_input() will consume more input; +it'll just keep returning JPEG_REACHED_SOS until you do. If you read a +tables-only file this way, jpeg_consume_input() will return JPEG_REACHED_EOI +without ever returning JPEG_REACHED_SOS; be sure to check for this case. +If this happens, the decompressor will not read any more input until you call +jpeg_abort() to reset it. It is OK to call jpeg_consume_input() even when not +using buffered-image mode, but in that case it's basically a no-op after the +initial markers have been read: it will just return JPEG_SUSPENDED. + + +Abbreviated datastreams and multiple images +------------------------------------------- + +A JPEG compression or decompression object can be reused to process multiple +images. This saves a small amount of time per image by eliminating the +"create" and "destroy" operations, but that isn't the real purpose of the +feature. Rather, reuse of an object provides support for abbreviated JPEG +datastreams. Object reuse can also simplify processing a series of images in +a single input or output file. This section explains these features. + +A JPEG file normally contains several hundred bytes worth of quantization +and Huffman tables. In a situation where many images will be stored or +transmitted with identical tables, this may represent an annoying overhead. +The JPEG standard therefore permits tables to be omitted. The standard +defines three classes of JPEG datastreams: + * "Interchange" datastreams contain an image and all tables needed to decode + the image. These are the usual kind of JPEG file. + * "Abbreviated image" datastreams contain an image, but are missing some or + all of the tables needed to decode that image. + * "Abbreviated table specification" (henceforth "tables-only") datastreams + contain only table specifications. +To decode an abbreviated image, it is necessary to load the missing table(s) +into the decoder beforehand. This can be accomplished by reading a separate +tables-only file. A variant scheme uses a series of images in which the first +image is an interchange (complete) datastream, while subsequent ones are +abbreviated and rely on the tables loaded by the first image. It is assumed +that once the decoder has read a table, it will remember that table until a +new definition for the same table number is encountered. + +It is the application designer's responsibility to figure out how to associate +the correct tables with an abbreviated image. While abbreviated datastreams +can be useful in a closed environment, their use is strongly discouraged in +any situation where data exchange with other applications might be needed. +Caveat designer. + +The JPEG library provides support for reading and writing any combination of +tables-only datastreams and abbreviated images. In both compression and +decompression objects, a quantization or Huffman table will be retained for +the lifetime of the object, unless it is overwritten by a new table definition. + + +To create abbreviated image datastreams, it is only necessary to tell the +compressor not to emit some or all of the tables it is using. Each +quantization and Huffman table struct contains a boolean field "sent_table", +which normally is initialized to FALSE. For each table used by the image, the +header-writing process emits the table and sets sent_table = TRUE unless it is +already TRUE. (In normal usage, this prevents outputting the same table +definition multiple times, as would otherwise occur because the chroma +components typically share tables.) Thus, setting this field to TRUE before +calling jpeg_start_compress() will prevent the table from being written at +all. + +If you want to create a "pure" abbreviated image file containing no tables, +just call "jpeg_suppress_tables(&cinfo, TRUE)" after constructing all the +tables. If you want to emit some but not all tables, you'll need to set the +individual sent_table fields directly. + +To create an abbreviated image, you must also call jpeg_start_compress() +with a second parameter of FALSE, not TRUE. Otherwise jpeg_start_compress() +will force all the sent_table fields to FALSE. (This is a safety feature to +prevent abbreviated images from being created accidentally.) + +To create a tables-only file, perform the same parameter setup that you +normally would, but instead of calling jpeg_start_compress() and so on, call +jpeg_write_tables(&cinfo). This will write an abbreviated datastream +containing only SOI, DQT and/or DHT markers, and EOI. All the quantization +and Huffman tables that are currently defined in the compression object will +be emitted unless their sent_tables flag is already TRUE, and then all the +sent_tables flags will be set TRUE. + +A sure-fire way to create matching tables-only and abbreviated image files +is to proceed as follows: + + create JPEG compression object + set JPEG parameters + set destination to tables-only file + jpeg_write_tables(&cinfo); + set destination to image file + jpeg_start_compress(&cinfo, FALSE); + write data... + jpeg_finish_compress(&cinfo); + +Since the JPEG parameters are not altered between writing the table file and +the abbreviated image file, the same tables are sure to be used. Of course, +you can repeat the jpeg_start_compress() ... jpeg_finish_compress() sequence +many times to produce many abbreviated image files matching the table file. + +You cannot suppress output of the computed Huffman tables when Huffman +optimization is selected. (If you could, there'd be no way to decode the +image...) Generally, you don't want to set optimize_coding = TRUE when +you are trying to produce abbreviated files. + +In some cases you might want to compress an image using tables which are +not stored in the application, but are defined in an interchange or +tables-only file readable by the application. This can be done by setting up +a JPEG decompression object to read the specification file, then copying the +tables into your compression object. See jpeg_copy_critical_parameters() +for an example of copying quantization tables. + + +To read abbreviated image files, you simply need to load the proper tables +into the decompression object before trying to read the abbreviated image. +If the proper tables are stored in the application program, you can just +allocate the table structs and fill in their contents directly. For example, +to load a fixed quantization table into table slot "n": + + if (cinfo.quant_tbl_ptrs[n] == NULL) + cinfo.quant_tbl_ptrs[n] = jpeg_alloc_quant_table((j_common_ptr) &cinfo); + quant_ptr = cinfo.quant_tbl_ptrs[n]; /* quant_ptr is JQUANT_TBL* */ + for (i = 0; i < 64; i++) { + /* Qtable[] is desired quantization table, in natural array order */ + quant_ptr->quantval[i] = Qtable[i]; + } + +Code to load a fixed Huffman table is typically (for AC table "n"): + + if (cinfo.ac_huff_tbl_ptrs[n] == NULL) + cinfo.ac_huff_tbl_ptrs[n] = jpeg_alloc_huff_table((j_common_ptr) &cinfo); + huff_ptr = cinfo.ac_huff_tbl_ptrs[n]; /* huff_ptr is JHUFF_TBL* */ + for (i = 1; i <= 16; i++) { + /* counts[i] is number of Huffman codes of length i bits, i=1..16 */ + huff_ptr->bits[i] = counts[i]; + } + for (i = 0; i < 256; i++) { + /* symbols[] is the list of Huffman symbols, in code-length order */ + huff_ptr->huffval[i] = symbols[i]; + } + +(Note that trying to set cinfo.quant_tbl_ptrs[n] to point directly at a +constant JQUANT_TBL object is not safe. If the incoming file happened to +contain a quantization table definition, your master table would get +overwritten! Instead allocate a working table copy and copy the master table +into it, as illustrated above. Ditto for Huffman tables, of course.) + +You might want to read the tables from a tables-only file, rather than +hard-wiring them into your application. The jpeg_read_header() call is +sufficient to read a tables-only file. You must pass a second parameter of +FALSE to indicate that you do not require an image to be present. Thus, the +typical scenario is + + create JPEG decompression object + set source to tables-only file + jpeg_read_header(&cinfo, FALSE); + set source to abbreviated image file + jpeg_read_header(&cinfo, TRUE); + set decompression parameters + jpeg_start_decompress(&cinfo); + read data... + jpeg_finish_decompress(&cinfo); + +In some cases, you may want to read a file without knowing whether it contains +an image or just tables. In that case, pass FALSE and check the return value +from jpeg_read_header(): it will be JPEG_HEADER_OK if an image was found, +JPEG_HEADER_TABLES_ONLY if only tables were found. (A third return value, +JPEG_SUSPENDED, is possible when using a suspending data source manager.) +Note that jpeg_read_header() will not complain if you read an abbreviated +image for which you haven't loaded the missing tables; the missing-table check +occurs later, in jpeg_start_decompress(). + + +It is possible to read a series of images from a single source file by +repeating the jpeg_read_header() ... jpeg_finish_decompress() sequence, +without releasing/recreating the JPEG object or the data source module. +(If you did reinitialize, any partial bufferload left in the data source +buffer at the end of one image would be discarded, causing you to lose the +start of the next image.) When you use this method, stored tables are +automatically carried forward, so some of the images can be abbreviated images +that depend on tables from earlier images. + +If you intend to write a series of images into a single destination file, +you might want to make a specialized data destination module that doesn't +flush the output buffer at term_destination() time. This would speed things +up by some trifling amount. Of course, you'd need to remember to flush the +buffer after the last image. You can make the later images be abbreviated +ones by passing FALSE to jpeg_start_compress(). + + +Special markers +--------------- + +Some applications may need to insert or extract special data in the JPEG +datastream. The JPEG standard provides marker types "COM" (comment) and +"APP0" through "APP15" (application) to hold application-specific data. +Unfortunately, the use of these markers is not specified by the standard. +COM markers are fairly widely used to hold user-supplied text. The JFIF file +format spec uses APP0 markers with specified initial strings to hold certain +data. Adobe applications use APP14 markers beginning with the string "Adobe" +for miscellaneous data. Other APPn markers are rarely seen, but might +contain almost anything. + +If you wish to store user-supplied text, we recommend you use COM markers +and place readable 7-bit ASCII text in them. Newline conventions are not +standardized --- expect to find LF (Unix style), CR/LF (DOS style), or CR +(Mac style). A robust COM reader should be able to cope with random binary +garbage, including nulls, since some applications generate COM markers +containing non-ASCII junk. (But yours should not be one of them.) + +For program-supplied data, use an APPn marker, and be sure to begin it with an +identifying string so that you can tell whether the marker is actually yours. +It's probably best to avoid using APP0 or APP14 for any private markers. +(NOTE: the upcoming SPIFF standard will use APP8 markers; we recommend you +not use APP8 markers for any private purposes, either.) + +Keep in mind that at most 65533 bytes can be put into one marker, but you +can have as many markers as you like. + +By default, the IJG compression library will write a JFIF APP0 marker if the +selected JPEG colorspace is grayscale or YCbCr, or an Adobe APP14 marker if +the selected colorspace is RGB, CMYK, or YCCK. You can disable this, but +we don't recommend it. The decompression library will recognize JFIF and +Adobe markers and will set the JPEG colorspace properly when one is found. + + +You can write special markers immediately following the datastream header by +calling jpeg_write_marker() after jpeg_start_compress() and before the first +call to jpeg_write_scanlines(). When you do this, the markers appear after +the SOI and the JFIF APP0 and Adobe APP14 markers (if written), but before +all else. Specify the marker type parameter as "JPEG_COM" for COM or +"JPEG_APP0 + n" for APPn. (Actually, jpeg_write_marker will let you write +any marker type, but we don't recommend writing any other kinds of marker.) +For example, to write a user comment string pointed to by comment_text: + jpeg_write_marker(cinfo, JPEG_COM, comment_text, strlen(comment_text)); + +If it's not convenient to store all the marker data in memory at once, +you can instead call jpeg_write_m_header() followed by multiple calls to +jpeg_write_m_byte(). If you do it this way, it's your responsibility to +call jpeg_write_m_byte() exactly the number of times given in the length +parameter to jpeg_write_m_header(). (This method lets you empty the +output buffer partway through a marker, which might be important when +using a suspending data destination module. In any case, if you are using +a suspending destination, you should flush its buffer after inserting +any special markers. See "I/O suspension".) + +Or, if you prefer to synthesize the marker byte sequence yourself, +you can just cram it straight into the data destination module. + +If you are writing JFIF 1.02 extension markers (thumbnail images), don't +forget to set cinfo.JFIF_minor_version = 2 so that the encoder will write the +correct JFIF version number in the JFIF header marker. The library's default +is to write version 1.01, but that's wrong if you insert any 1.02 extension +markers. (We could probably get away with just defaulting to 1.02, but there +used to be broken decoders that would complain about unknown minor version +numbers. To reduce compatibility risks it's safest not to write 1.02 unless +you are actually using 1.02 extensions.) + + +When reading, two methods of handling special markers are available: +1. You can ask the library to save the contents of COM and/or APPn markers +into memory, and then examine them at your leisure afterwards. +2. You can supply your own routine to process COM and/or APPn markers +on-the-fly as they are read. +The first method is simpler to use, especially if you are using a suspending +data source; writing a marker processor that copes with input suspension is +not easy (consider what happens if the marker is longer than your available +input buffer). However, the second method conserves memory since the marker +data need not be kept around after it's been processed. + +For either method, you'd normally set up marker handling after creating a +decompression object and before calling jpeg_read_header(), because the +markers of interest will typically be near the head of the file and so will +be scanned by jpeg_read_header. Once you've established a marker handling +method, it will be used for the life of that decompression object +(potentially many datastreams), unless you change it. Marker handling is +determined separately for COM markers and for each APPn marker code. + + +To save the contents of special markers in memory, call + jpeg_save_markers(cinfo, marker_code, length_limit) +where marker_code is the marker type to save, JPEG_COM or JPEG_APP0+n. +(To arrange to save all the special marker types, you need to call this +routine 17 times, for COM and APP0-APP15.) If the incoming marker is longer +than length_limit data bytes, only length_limit bytes will be saved; this +parameter allows you to avoid chewing up memory when you only need to see the +first few bytes of a potentially large marker. If you want to save all the +data, set length_limit to 0xFFFF; that is enough since marker lengths are only +16 bits. As a special case, setting length_limit to 0 prevents that marker +type from being saved at all. (That is the default behavior, in fact.) + +After jpeg_read_header() completes, you can examine the special markers by +following the cinfo->marker_list pointer chain. All the special markers in +the file appear in this list, in order of their occurrence in the file (but +omitting any markers of types you didn't ask for). Both the original data +length and the saved data length are recorded for each list entry; the latter +will not exceed length_limit for the particular marker type. Note that these +lengths exclude the marker length word, whereas the stored representation +within the JPEG file includes it. (Hence the maximum data length is really +only 65533.) + +It is possible that additional special markers appear in the file beyond the +SOS marker at which jpeg_read_header stops; if so, the marker list will be +extended during reading of the rest of the file. This is not expected to be +common, however. If you are short on memory you may want to reset the length +limit to zero for all marker types after finishing jpeg_read_header, to +ensure that the max_memory_to_use setting cannot be exceeded due to addition +of later markers. + +The marker list remains stored until you call jpeg_finish_decompress or +jpeg_abort, at which point the memory is freed and the list is set to empty. +(jpeg_destroy also releases the storage, of course.) + +Note that the library is internally interested in APP0 and APP14 markers; +if you try to set a small nonzero length limit on these types, the library +will silently force the length up to the minimum it wants. (But you can set +a zero length limit to prevent them from being saved at all.) Also, in a +16-bit environment, the maximum length limit may be constrained to less than +65533 by malloc() limitations. It is therefore best not to assume that the +effective length limit is exactly what you set it to be. + + +If you want to supply your own marker-reading routine, you do it by calling +jpeg_set_marker_processor(). A marker processor routine must have the +signature + boolean jpeg_marker_parser_method (j_decompress_ptr cinfo) +Although the marker code is not explicitly passed, the routine can find it +in cinfo->unread_marker. At the time of call, the marker proper has been +read from the data source module. The processor routine is responsible for +reading the marker length word and the remaining parameter bytes, if any. +Return TRUE to indicate success. (FALSE should be returned only if you are +using a suspending data source and it tells you to suspend. See the standard +marker processors in jdmarker.c for appropriate coding methods if you need to +use a suspending data source.) + +If you override the default APP0 or APP14 processors, it is up to you to +recognize JFIF and Adobe markers if you want colorspace recognition to occur +properly. We recommend copying and extending the default processors if you +want to do that. (A better idea is to save these marker types for later +examination by calling jpeg_save_markers(); that method doesn't interfere +with the library's own processing of these markers.) + +jpeg_set_marker_processor() and jpeg_save_markers() are mutually exclusive +--- if you call one it overrides any previous call to the other, for the +particular marker type specified. + +A simple example of an external COM processor can be found in djpeg.c. +Also, see jpegtran.c for an example of using jpeg_save_markers. + + +Raw (downsampled) image data +---------------------------- + +Some applications need to supply already-downsampled image data to the JPEG +compressor, or to receive raw downsampled data from the decompressor. The +library supports this requirement by allowing the application to write or +read raw data, bypassing the normal preprocessing or postprocessing steps. +The interface is different from the standard one and is somewhat harder to +use. If your interest is merely in bypassing color conversion, we recommend +that you use the standard interface and simply set jpeg_color_space = +in_color_space (or jpeg_color_space = out_color_space for decompression). +The mechanism described in this section is necessary only to supply or +receive downsampled image data, in which not all components have the same +dimensions. + + +To compress raw data, you must supply the data in the colorspace to be used +in the JPEG file (please read the earlier section on Special color spaces) +and downsampled to the sampling factors specified in the JPEG parameters. +You must supply the data in the format used internally by the JPEG library, +namely a JSAMPIMAGE array. This is an array of pointers to two-dimensional +arrays, each of type JSAMPARRAY. Each 2-D array holds the values for one +color component. This structure is necessary since the components are of +different sizes. If the image dimensions are not a multiple of the MCU size, +you must also pad the data correctly (usually, this is done by replicating +the last column and/or row). The data must be padded to a multiple of a DCT +block in each component: that is, each downsampled row must contain a +multiple of 8 valid samples, and there must be a multiple of 8 sample rows +for each component. (For applications such as conversion of digital TV +images, the standard image size is usually a multiple of the DCT block size, +so that no padding need actually be done.) + +The procedure for compression of raw data is basically the same as normal +compression, except that you call jpeg_write_raw_data() in place of +jpeg_write_scanlines(). Before calling jpeg_start_compress(), you must do +the following: + * Set cinfo->raw_data_in to TRUE. (It is set FALSE by jpeg_set_defaults().) + This notifies the library that you will be supplying raw data. + * Ensure jpeg_color_space is correct --- an explicit jpeg_set_colorspace() + call is a good idea. Note that since color conversion is bypassed, + in_color_space is ignored, except that jpeg_set_defaults() uses it to + choose the default jpeg_color_space setting. + * Ensure the sampling factors, cinfo->comp_info[i].h_samp_factor and + cinfo->comp_info[i].v_samp_factor, are correct. Since these indicate the + dimensions of the data you are supplying, it's wise to set them + explicitly, rather than assuming the library's defaults are what you want. + +To pass raw data to the library, call jpeg_write_raw_data() in place of +jpeg_write_scanlines(). The two routines work similarly except that +jpeg_write_raw_data takes a JSAMPIMAGE data array rather than JSAMPARRAY. +The scanlines count passed to and returned from jpeg_write_raw_data is +measured in terms of the component with the largest v_samp_factor. + +jpeg_write_raw_data() processes one MCU row per call, which is to say +v_samp_factor*DCTSIZE sample rows of each component. The passed num_lines +value must be at least max_v_samp_factor*DCTSIZE, and the return value will +be exactly that amount (or possibly some multiple of that amount, in future +library versions). This is true even on the last call at the bottom of the +image; don't forget to pad your data as necessary. + +The required dimensions of the supplied data can be computed for each +component as + cinfo->comp_info[i].width_in_blocks*DCTSIZE samples per row + cinfo->comp_info[i].height_in_blocks*DCTSIZE rows in image +after jpeg_start_compress() has initialized those fields. If the valid data +is smaller than this, it must be padded appropriately. For some sampling +factors and image sizes, additional dummy DCT blocks are inserted to make +the image a multiple of the MCU dimensions. The library creates such dummy +blocks itself; it does not read them from your supplied data. Therefore you +need never pad by more than DCTSIZE samples. An example may help here. +Assume 2h2v downsampling of YCbCr data, that is + cinfo->comp_info[0].h_samp_factor = 2 for Y + cinfo->comp_info[0].v_samp_factor = 2 + cinfo->comp_info[1].h_samp_factor = 1 for Cb + cinfo->comp_info[1].v_samp_factor = 1 + cinfo->comp_info[2].h_samp_factor = 1 for Cr + cinfo->comp_info[2].v_samp_factor = 1 +and suppose that the nominal image dimensions (cinfo->image_width and +cinfo->image_height) are 101x101 pixels. Then jpeg_start_compress() will +compute downsampled_width = 101 and width_in_blocks = 13 for Y, +downsampled_width = 51 and width_in_blocks = 7 for Cb and Cr (and the same +for the height fields). You must pad the Y data to at least 13*8 = 104 +columns and rows, the Cb/Cr data to at least 7*8 = 56 columns and rows. The +MCU height is max_v_samp_factor = 2 DCT rows so you must pass at least 16 +scanlines on each call to jpeg_write_raw_data(), which is to say 16 actual +sample rows of Y and 8 each of Cb and Cr. A total of 7 MCU rows are needed, +so you must pass a total of 7*16 = 112 "scanlines". The last DCT block row +of Y data is dummy, so it doesn't matter what you pass for it in the data +arrays, but the scanlines count must total up to 112 so that all of the Cb +and Cr data gets passed. + +Output suspension is supported with raw-data compression: if the data +destination module suspends, jpeg_write_raw_data() will return 0. +In this case the same data rows must be passed again on the next call. + + +Decompression with raw data output implies bypassing all postprocessing: +you cannot ask for rescaling or color quantization, for instance. More +seriously, you must deal with the color space and sampling factors present in +the incoming file. If your application only handles, say, 2h1v YCbCr data, +you must check for and fail on other color spaces or other sampling factors. +The library will not convert to a different color space for you. + +To obtain raw data output, set cinfo->raw_data_out = TRUE before +jpeg_start_decompress() (it is set FALSE by jpeg_read_header()). Be sure to +verify that the color space and sampling factors are ones you can handle. +Then call jpeg_read_raw_data() in place of jpeg_read_scanlines(). The +decompression process is otherwise the same as usual. + +jpeg_read_raw_data() returns one MCU row per call, and thus you must pass a +buffer of at least max_v_samp_factor*DCTSIZE scanlines (scanline counting is +the same as for raw-data compression). The buffer you pass must be large +enough to hold the actual data plus padding to DCT-block boundaries. As with +compression, any entirely dummy DCT blocks are not processed so you need not +allocate space for them, but the total scanline count includes them. The +above example of computing buffer dimensions for raw-data compression is +equally valid for decompression. + +Input suspension is supported with raw-data decompression: if the data source +module suspends, jpeg_read_raw_data() will return 0. You can also use +buffered-image mode to read raw data in multiple passes. + + +Really raw data: DCT coefficients +--------------------------------- + +It is possible to read or write the contents of a JPEG file as raw DCT +coefficients. This facility is mainly intended for use in lossless +transcoding between different JPEG file formats. Other possible applications +include lossless cropping of a JPEG image, lossless reassembly of a +multi-strip or multi-tile TIFF/JPEG file into a single JPEG datastream, etc. + +To read the contents of a JPEG file as DCT coefficients, open the file and do +jpeg_read_header() as usual. But instead of calling jpeg_start_decompress() +and jpeg_read_scanlines(), call jpeg_read_coefficients(). This will read the +entire image into a set of virtual coefficient-block arrays, one array per +component. The return value is a pointer to an array of virtual-array +descriptors. Each virtual array can be accessed directly using the JPEG +memory manager's access_virt_barray method (see Memory management, below, +and also read structure.doc's discussion of virtual array handling). Or, +for simple transcoding to a different JPEG file format, the array list can +just be handed directly to jpeg_write_coefficients(). + +Each block in the block arrays contains quantized coefficient values in +normal array order (not JPEG zigzag order). The block arrays contain only +DCT blocks containing real data; any entirely-dummy blocks added to fill out +interleaved MCUs at the right or bottom edges of the image are discarded +during reading and are not stored in the block arrays. (The size of each +block array can be determined from the width_in_blocks and height_in_blocks +fields of the component's comp_info entry.) This is also the data format +expected by jpeg_write_coefficients(). + +When you are done using the virtual arrays, call jpeg_finish_decompress() +to release the array storage and return the decompression object to an idle +state; or just call jpeg_destroy() if you don't need to reuse the object. + +If you use a suspending data source, jpeg_read_coefficients() will return +NULL if it is forced to suspend; a non-NULL return value indicates successful +completion. You need not test for a NULL return value when using a +non-suspending data source. + +It is also possible to call jpeg_read_coefficients() to obtain access to the +decoder's coefficient arrays during a normal decode cycle in buffered-image +mode. This frammish might be useful for progressively displaying an incoming +image and then re-encoding it without loss. To do this, decode in buffered- +image mode as discussed previously, then call jpeg_read_coefficients() after +the last jpeg_finish_output() call. The arrays will be available for your use +until you call jpeg_finish_decompress(). + + +To write the contents of a JPEG file as DCT coefficients, you must provide +the DCT coefficients stored in virtual block arrays. You can either pass +block arrays read from an input JPEG file by jpeg_read_coefficients(), or +allocate virtual arrays from the JPEG compression object and fill them +yourself. In either case, jpeg_write_coefficients() is substituted for +jpeg_start_compress() and jpeg_write_scanlines(). Thus the sequence is + * Create compression object + * Set all compression parameters as necessary + * Request virtual arrays if needed + * jpeg_write_coefficients() + * jpeg_finish_compress() + * Destroy or re-use compression object +jpeg_write_coefficients() is passed a pointer to an array of virtual block +array descriptors; the number of arrays is equal to cinfo.num_components. + +The virtual arrays need only have been requested, not realized, before +jpeg_write_coefficients() is called. A side-effect of +jpeg_write_coefficients() is to realize any virtual arrays that have been +requested from the compression object's memory manager. Thus, when obtaining +the virtual arrays from the compression object, you should fill the arrays +after calling jpeg_write_coefficients(). The data is actually written out +when you call jpeg_finish_compress(); jpeg_write_coefficients() only writes +the file header. + +When writing raw DCT coefficients, it is crucial that the JPEG quantization +tables and sampling factors match the way the data was encoded, or the +resulting file will be invalid. For transcoding from an existing JPEG file, +we recommend using jpeg_copy_critical_parameters(). This routine initializes +all the compression parameters to default values (like jpeg_set_defaults()), +then copies the critical information from a source decompression object. +The decompression object should have just been used to read the entire +JPEG input file --- that is, it should be awaiting jpeg_finish_decompress(). + +jpeg_write_coefficients() marks all tables stored in the compression object +as needing to be written to the output file (thus, it acts like +jpeg_start_compress(cinfo, TRUE)). This is for safety's sake, to avoid +emitting abbreviated JPEG files by accident. If you really want to emit an +abbreviated JPEG file, call jpeg_suppress_tables(), or set the tables' +individual sent_table flags, between calling jpeg_write_coefficients() and +jpeg_finish_compress(). + + +Progress monitoring +------------------- + +Some applications may need to regain control from the JPEG library every so +often. The typical use of this feature is to produce a percent-done bar or +other progress display. (For a simple example, see cjpeg.c or djpeg.c.) +Although you do get control back frequently during the data-transferring pass +(the jpeg_read_scanlines or jpeg_write_scanlines loop), any additional passes +will occur inside jpeg_finish_compress or jpeg_start_decompress; those +routines may take a long time to execute, and you don't get control back +until they are done. + +You can define a progress-monitor routine which will be called periodically +by the library. No guarantees are made about how often this call will occur, +so we don't recommend you use it for mouse tracking or anything like that. +At present, a call will occur once per MCU row, scanline, or sample row +group, whichever unit is convenient for the current processing mode; so the +wider the image, the longer the time between calls. During the data +transferring pass, only one call occurs per call of jpeg_read_scanlines or +jpeg_write_scanlines, so don't pass a large number of scanlines at once if +you want fine resolution in the progress count. (If you really need to use +the callback mechanism for time-critical tasks like mouse tracking, you could +insert additional calls inside some of the library's inner loops.) + +To establish a progress-monitor callback, create a struct jpeg_progress_mgr, +fill in its progress_monitor field with a pointer to your callback routine, +and set cinfo->progress to point to the struct. The callback will be called +whenever cinfo->progress is non-NULL. (This pointer is set to NULL by +jpeg_create_compress or jpeg_create_decompress; the library will not change +it thereafter. So if you allocate dynamic storage for the progress struct, +make sure it will live as long as the JPEG object does. Allocating from the +JPEG memory manager with lifetime JPOOL_PERMANENT will work nicely.) You +can use the same callback routine for both compression and decompression. + +The jpeg_progress_mgr struct contains four fields which are set by the library: + long pass_counter; /* work units completed in this pass */ + long pass_limit; /* total number of work units in this pass */ + int completed_passes; /* passes completed so far */ + int total_passes; /* total number of passes expected */ +During any one pass, pass_counter increases from 0 up to (not including) +pass_limit; the step size is usually but not necessarily 1. The pass_limit +value may change from one pass to another. The expected total number of +passes is in total_passes, and the number of passes already completed is in +completed_passes. Thus the fraction of work completed may be estimated as + completed_passes + (pass_counter/pass_limit) + -------------------------------------------- + total_passes +ignoring the fact that the passes may not be equal amounts of work. + +When decompressing, pass_limit can even change within a pass, because it +depends on the number of scans in the JPEG file, which isn't always known in +advance. The computed fraction-of-work-done may jump suddenly (if the library +discovers it has overestimated the number of scans) or even decrease (in the +opposite case). It is not wise to put great faith in the work estimate. + +When using the decompressor's buffered-image mode, the progress monitor work +estimate is likely to be completely unhelpful, because the library has no way +to know how many output passes will be demanded of it. Currently, the library +sets total_passes based on the assumption that there will be one more output +pass if the input file end hasn't yet been read (jpeg_input_complete() isn't +TRUE), but no more output passes if the file end has been reached when the +output pass is started. This means that total_passes will rise as additional +output passes are requested. If you have a way of determining the input file +size, estimating progress based on the fraction of the file that's been read +will probably be more useful than using the library's value. + + +Memory management +----------------- + +This section covers some key facts about the JPEG library's built-in memory +manager. For more info, please read structure.doc's section about the memory +manager, and consult the source code if necessary. + +All memory and temporary file allocation within the library is done via the +memory manager. If necessary, you can replace the "back end" of the memory +manager to control allocation yourself (for example, if you don't want the +library to use malloc() and free() for some reason). + +Some data is allocated "permanently" and will not be freed until the JPEG +object is destroyed. Most data is allocated "per image" and is freed by +jpeg_finish_compress, jpeg_finish_decompress, or jpeg_abort. You can call the +memory manager yourself to allocate structures that will automatically be +freed at these times. Typical code for this is + ptr = (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, size); +Use JPOOL_PERMANENT to get storage that lasts as long as the JPEG object. +Use alloc_large instead of alloc_small for anything bigger than a few Kbytes. +There are also alloc_sarray and alloc_barray routines that automatically +build 2-D sample or block arrays. + +The library's minimum space requirements to process an image depend on the +image's width, but not on its height, because the library ordinarily works +with "strip" buffers that are as wide as the image but just a few rows high. +Some operating modes (eg, two-pass color quantization) require full-image +buffers. Such buffers are treated as "virtual arrays": only the current strip +need be in memory, and the rest can be swapped out to a temporary file. + +If you use the simplest memory manager back end (jmemnobs.c), then no +temporary files are used; virtual arrays are simply malloc()'d. Images bigger +than memory can be processed only if your system supports virtual memory. +The other memory manager back ends support temporary files of various flavors +and thus work in machines without virtual memory. They may also be useful on +Unix machines if you need to process images that exceed available swap space. + +When using temporary files, the library will make the in-memory buffers for +its virtual arrays just big enough to stay within a "maximum memory" setting. +Your application can set this limit by setting cinfo->mem->max_memory_to_use +after creating the JPEG object. (Of course, there is still a minimum size for +the buffers, so the max-memory setting is effective only if it is bigger than +the minimum space needed.) If you allocate any large structures yourself, you +must allocate them before jpeg_start_compress() or jpeg_start_decompress() in +order to have them counted against the max memory limit. Also keep in mind +that space allocated with alloc_small() is ignored, on the assumption that +it's too small to be worth worrying about; so a reasonable safety margin +should be left when setting max_memory_to_use. + +If you use the jmemname.c or jmemdos.c memory manager back end, it is +important to clean up the JPEG object properly to ensure that the temporary +files get deleted. (This is especially crucial with jmemdos.c, where the +"temporary files" may be extended-memory segments; if they are not freed, +DOS will require a reboot to recover the memory.) Thus, with these memory +managers, it's a good idea to provide a signal handler that will trap any +early exit from your program. The handler should call either jpeg_abort() +or jpeg_destroy() for any active JPEG objects. A handler is not needed with +jmemnobs.c, and shouldn't be necessary with jmemansi.c or jmemmac.c either, +since the C library is supposed to take care of deleting files made with +tmpfile(). + + +Memory usage +------------ + +Working memory requirements while performing compression or decompression +depend on image dimensions, image characteristics (such as colorspace and +JPEG process), and operating mode (application-selected options). + +As of v6b, the decompressor requires: + 1. About 24K in more-or-less-fixed-size data. This varies a bit depending + on operating mode and image characteristics (particularly color vs. + grayscale), but it doesn't depend on image dimensions. + 2. Strip buffers (of size proportional to the image width) for IDCT and + upsampling results. The worst case for commonly used sampling factors + is about 34 bytes * width in pixels for a color image. A grayscale image + only needs about 8 bytes per pixel column. + 3. A full-image DCT coefficient buffer is needed to decode a multi-scan JPEG + file (including progressive JPEGs), or whenever you select buffered-image + mode. This takes 2 bytes/coefficient. At typical 2x2 sampling, that's + 3 bytes per pixel for a color image. Worst case (1x1 sampling) requires + 6 bytes/pixel. For grayscale, figure 2 bytes/pixel. + 4. To perform 2-pass color quantization, the decompressor also needs a + 128K color lookup table and a full-image pixel buffer (3 bytes/pixel). +This does not count any memory allocated by the application, such as a +buffer to hold the final output image. + +The above figures are valid for 8-bit JPEG data precision and a machine with +32-bit ints. For 12-bit JPEG data, double the size of the strip buffers and +quantization pixel buffer. The "fixed-size" data will be somewhat smaller +with 16-bit ints, larger with 64-bit ints. Also, CMYK or other unusual +color spaces will require different amounts of space. + +The full-image coefficient and pixel buffers, if needed at all, do not +have to be fully RAM resident; you can have the library use temporary +files instead when the total memory usage would exceed a limit you set. +(But if your OS supports virtual memory, it's probably better to just use +jmemnobs and let the OS do the swapping.) + +The compressor's memory requirements are similar, except that it has no need +for color quantization. Also, it needs a full-image DCT coefficient buffer +if Huffman-table optimization is asked for, even if progressive mode is not +requested. + +If you need more detailed information about memory usage in a particular +situation, you can enable the MEM_STATS code in jmemmgr.c. + + +Library compile-time options +---------------------------- + +A number of compile-time options are available by modifying jmorecfg.h. + +The JPEG standard provides for both the baseline 8-bit DCT process and +a 12-bit DCT process. The IJG code supports 12-bit lossy JPEG if you define +BITS_IN_JSAMPLE as 12 rather than 8. Note that this causes JSAMPLE to be +larger than a char, so it affects the surrounding application's image data. +The sample applications cjpeg and djpeg can support 12-bit mode only for PPM +and GIF file formats; you must disable the other file formats to compile a +12-bit cjpeg or djpeg. (install.doc has more information about that.) +At present, a 12-bit library can handle *only* 12-bit images, not both +precisions. (If you need to include both 8- and 12-bit libraries in a single +application, you could probably do it by defining NEED_SHORT_EXTERNAL_NAMES +for just one of the copies. You'd have to access the 8-bit and 12-bit copies +from separate application source files. This is untested ... if you try it, +we'd like to hear whether it works!) + +Note that a 12-bit library always compresses in Huffman optimization mode, +in order to generate valid Huffman tables. This is necessary because our +default Huffman tables only cover 8-bit data. If you need to output 12-bit +files in one pass, you'll have to supply suitable default Huffman tables. +You may also want to supply your own DCT quantization tables; the existing +quality-scaling code has been developed for 8-bit use, and probably doesn't +generate especially good tables for 12-bit. + +The maximum number of components (color channels) in the image is determined +by MAX_COMPONENTS. The JPEG standard allows up to 255 components, but we +expect that few applications will need more than four or so. + +On machines with unusual data type sizes, you may be able to improve +performance or reduce memory space by tweaking the various typedefs in +jmorecfg.h. In particular, on some RISC CPUs, access to arrays of "short"s +is quite slow; consider trading memory for speed by making JCOEF, INT16, and +UINT16 be "int" or "unsigned int". UINT8 is also a candidate to become int. +You probably don't want to make JSAMPLE be int unless you have lots of memory +to burn. + +You can reduce the size of the library by compiling out various optional +functions. To do this, undefine xxx_SUPPORTED symbols as necessary. + +You can also save a few K by not having text error messages in the library; +the standard error message table occupies about 5Kb. This is particularly +reasonable for embedded applications where there's no good way to display +a message anyway. To do this, remove the creation of the message table +(jpeg_std_message_table[]) from jerror.c, and alter format_message to do +something reasonable without it. You could output the numeric value of the +message code number, for example. If you do this, you can also save a couple +more K by modifying the TRACEMSn() macros in jerror.h to expand to nothing; +you don't need trace capability anyway, right? + + +Portability considerations +-------------------------- + +The JPEG library has been written to be extremely portable; the sample +applications cjpeg and djpeg are slightly less so. This section summarizes +the design goals in this area. (If you encounter any bugs that cause the +library to be less portable than is claimed here, we'd appreciate hearing +about them.) + +The code works fine on ANSI C, C++, and pre-ANSI C compilers, using any of +the popular system include file setups, and some not-so-popular ones too. +See install.doc for configuration procedures. + +The code is not dependent on the exact sizes of the C data types. As +distributed, we make the assumptions that + char is at least 8 bits wide + short is at least 16 bits wide + int is at least 16 bits wide + long is at least 32 bits wide +(These are the minimum requirements of the ANSI C standard.) Wider types will +work fine, although memory may be used inefficiently if char is much larger +than 8 bits or short is much bigger than 16 bits. The code should work +equally well with 16- or 32-bit ints. + +In a system where these assumptions are not met, you may be able to make the +code work by modifying the typedefs in jmorecfg.h. However, you will probably +have difficulty if int is less than 16 bits wide, since references to plain +int abound in the code. + +char can be either signed or unsigned, although the code runs faster if an +unsigned char type is available. If char is wider than 8 bits, you will need +to redefine JOCTET and/or provide custom data source/destination managers so +that JOCTET represents exactly 8 bits of data on external storage. + +The JPEG library proper does not assume ASCII representation of characters. +But some of the image file I/O modules in cjpeg/djpeg do have ASCII +dependencies in file-header manipulation; so does cjpeg's select_file_type() +routine. + +The JPEG library does not rely heavily on the C library. In particular, C +stdio is used only by the data source/destination modules and the error +handler, all of which are application-replaceable. (cjpeg/djpeg are more +heavily dependent on stdio.) malloc and free are called only from the memory +manager "back end" module, so you can use a different memory allocator by +replacing that one file. + +The code generally assumes that C names must be unique in the first 15 +characters. However, global function names can be made unique in the +first 6 characters by defining NEED_SHORT_EXTERNAL_NAMES. + +More info about porting the code may be gleaned by reading jconfig.doc, +jmorecfg.h, and jinclude.h. + + +Notes for MS-DOS implementors +----------------------------- + +The IJG code is designed to work efficiently in 80x86 "small" or "medium" +memory models (i.e., data pointers are 16 bits unless explicitly declared +"far"; code pointers can be either size). You may be able to use small +model to compile cjpeg or djpeg by itself, but you will probably have to use +medium model for any larger application. This won't make much difference in +performance. You *will* take a noticeable performance hit if you use a +large-data memory model (perhaps 10%-25%), and you should avoid "huge" model +if at all possible. + +The JPEG library typically needs 2Kb-3Kb of stack space. It will also +malloc about 20K-30K of near heap space while executing (and lots of far +heap, but that doesn't count in this calculation). This figure will vary +depending on selected operating mode, and to a lesser extent on image size. +There is also about 5Kb-6Kb of constant data which will be allocated in the +near data segment (about 4Kb of this is the error message table). +Thus you have perhaps 20K available for other modules' static data and near +heap space before you need to go to a larger memory model. The C library's +static data will account for several K of this, but that still leaves a good +deal for your needs. (If you are tight on space, you could reduce the sizes +of the I/O buffers allocated by jdatasrc.c and jdatadst.c, say from 4K to +1K. Another possibility is to move the error message table to far memory; +this should be doable with only localized hacking on jerror.c.) + +About 2K of the near heap space is "permanent" memory that will not be +released until you destroy the JPEG object. This is only an issue if you +save a JPEG object between compression or decompression operations. + +Far data space may also be a tight resource when you are dealing with large +images. The most memory-intensive case is decompression with two-pass color +quantization, or single-pass quantization to an externally supplied color +map. This requires a 128Kb color lookup table plus strip buffers amounting +to about 40 bytes per column for typical sampling ratios (eg, about 25600 +bytes for a 640-pixel-wide image). You may not be able to process wide +images if you have large data structures of your own. + +Of course, all of these concerns vanish if you use a 32-bit flat-memory-model +compiler, such as DJGPP or Watcom C. We highly recommend flat model if you +can use it; the JPEG library is significantly faster in flat model. diff --git a/lc-continuity/mk4/modimage/jpeg-6b/ltconfig b/lc-continuity/mk4/modimage/jpeg-6b/ltconfig new file mode 100644 index 0000000000000000000000000000000000000000..2347e694395095e8db2c131d683b157f07eca29e --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/ltconfig @@ -0,0 +1,1512 @@ +#! /bin/sh + +# ltconfig - Create a system-specific libtool. +# Copyright (C) 1996-1998 Free Software Foundation, Inc. +# Gordon Matzigkeit , 1996 +# +# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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. + +# A lot of this script is taken from autoconf-2.10. + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +if test "${CDPATH+set}" = set; then CDPATH=; export CDPATH; fi + +echo=echo +if test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then : +else + # The Solaris and AIX default echo program unquotes backslashes. + # This makes it impossible to quote backslashes using + # echo "$something" | sed 's/\\/\\\\/g' + # So, we emulate echo with printf '%s\n' + echo="printf %s\\n" + if test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then : + else + # Oops. We have no working printf. Try to find a not-so-buggy echo. + echo=echo + IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}:" + for dir in $PATH /usr/ucb; do + if test -f $dir/echo && test "X`$dir/echo '\t'`" = 'X\t'; then + echo="$dir/echo" + break + fi + done + IFS="$save_ifs" + fi +fi + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='sed -e s/^X//' +sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g' + +# The name of this program. +progname=`$echo "X$0" | $Xsed -e 's%^.*/%%'` + +# Constants: +PROGRAM=ltconfig +PACKAGE=libtool +VERSION=1.2 +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.c 1>&5' +ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.c $LIBS 1>&5' +rm="rm -f" + +help="Try \`$progname --help' for more information." + +# Global variables: +can_build_shared=yes +enable_shared=yes +# All known linkers require a `.a' archive for static linking. +enable_static=yes +ltmain= +silent= +srcdir= +ac_config_guess= +ac_config_sub= +host= +nonopt= +verify_host=yes +with_gcc=no +with_gnu_ld=no + +old_AR="$AR" +old_CC="$CC" +old_CFLAGS="$CFLAGS" +old_CPPFLAGS="$CPPFLAGS" +old_LD="$LD" +old_LN_S="$LN_S" +old_NM="$NM" +old_RANLIB="$RANLIB" + +# Parse the command line options. +args= +prev= +for option +do + case "$option" in + -*=*) optarg=`echo "$option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) optarg= ;; + esac + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + eval "$prev=\$option" + prev= + continue + fi + + case "$option" in + --help) cat <&2 + echo "$help" 1>&2 + exit 1 + ;; + + *) + if test -z "$ltmain"; then + ltmain="$option" + elif test -z "$host"; then +# This generates an unnecessary warning for sparc-sun-solaris4.1.3_U1 +# if test -n "`echo $option| sed 's/[-a-z0-9.]//g'`"; then +# echo "$progname: warning \`$option' is not a valid host type" 1>&2 +# fi + host="$option" + else + echo "$progname: too many arguments" 1>&2 + echo "$help" 1>&2 + exit 1 + fi ;; + esac +done + +if test -z "$ltmain"; then + echo "$progname: you must specify a LTMAIN file" 1>&2 + echo "$help" 1>&2 + exit 1 +fi + +if test -f "$ltmain"; then : +else + echo "$progname: \`$ltmain' does not exist" 1>&2 + echo "$help" 1>&2 + exit 1 +fi + +# Quote any args containing shell metacharacters. +ltconfig_args= +for arg +do + case "$arg" in + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ltconfig_args="$ltconfig_args '$arg'" ;; + *) ltconfig_args="$ltconfig_args $arg" ;; + esac +done + +# A relevant subset of AC_INIT. + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 5 compiler messages saved in config.log +# 6 checking for... messages and results +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>>./config.log + +# NLS nuisances. +# Only set LANG and LC_ALL to C if already set. +# These must not be set unconditionally because not all systems understand +# e.g. LANG=C (notably SCO). +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LANG+set}" = set; then LANG=C; export LANG; fi + +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + +if test -z "$srcdir"; then + # Assume the source directory is the same one as the path to ltmain.sh. + srcdir=`$echo "$ltmain" | $Xsed -e 's%/[^/]*$%%'` + test "$srcdir" = "$ltmain" && srcdir=. +fi + +trap "$rm conftest*; exit 1" 1 2 15 +if test "$verify_host" = yes; then + # Check for config.guess and config.sub. + ac_aux_dir= + for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/config.guess; then + ac_aux_dir=$ac_dir + break + fi + done + if test -z "$ac_aux_dir"; then + echo "$progname: cannot find config.guess in $srcdir $srcdir/.. $srcdir/../.." 1>&2 + echo "$help" 1>&2 + exit 1 + fi + ac_config_guess=$ac_aux_dir/config.guess + ac_config_sub=$ac_aux_dir/config.sub + + # Make sure we can run config.sub. + if $ac_config_sub sun4 >/dev/null 2>&1; then : + else + echo "$progname: cannot run $ac_config_sub" 1>&2 + echo "$help" 1>&2 + exit 1 + fi + + echo $ac_n "checking host system type""... $ac_c" 1>&6 + + host_alias=$host + case "$host_alias" in + "") + if host_alias=`$ac_config_guess`; then : + else + echo "$progname: cannot guess host type; you must specify one" 1>&2 + echo "$help" 1>&2 + exit 1 + fi ;; + esac + host=`$ac_config_sub $host_alias` + echo "$ac_t$host" 1>&6 + + # Make sure the host verified. + test -z "$host" && exit 1 + +elif test -z "$host"; then + echo "$progname: you must specify a host type if you use \`--no-verify'" 1>&2 + echo "$help" 1>&2 + exit 1 +else + host_alias=$host +fi + +# Transform linux* to *-*-linux-gnu*, to support old configure scripts. +case "$host_os" in +linux-gnu*) ;; +linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'` +esac + +host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` + +case "$host_os" in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "${COLLECT_NAMES+set}" != set; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR cru $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +# Set a sane default for `AR'. +test -z "$AR" && AR=ar + +# If RANLIB is not set, then run the test. +if test "${RANLIB+set}" != "set"; then + result=no + + echo $ac_n "checking for ranlib... $ac_c" 1>&6 + IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}:" + for dir in $PATH; do + test -z "$dir" && dir=. + if test -f $dir/ranlib; then + RANLIB="ranlib" + result="ranlib" + break + fi + done + IFS="$save_ifs" + + echo "$ac_t$result" 1>&6 +fi + +if test -n "$RANLIB"; then + old_archive_cmds="$old_archive_cmds;\$RANLIB \$oldlib" + old_postinstall_cmds="\$RANLIB \$oldlib;$old_postinstall_cmds" +fi + +# Check to see if we are using GCC. +if test "$with_gcc" != yes || test -z "$CC"; then + # If CC is not set, then try to find GCC or a usable CC. + if test -z "$CC"; then + echo $ac_n "checking for gcc... $ac_c" 1>&6 + IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}:" + for dir in $PATH; do + IFS="$save_ifs" + test -z "$dir" && dir=. + if test -f $dir/gcc; then + CC="gcc" + break + fi + done + IFS="$save_ifs" + + if test -n "$CC"; then + echo "$ac_t$CC" 1>&6 + else + echo "$ac_t"no 1>&6 + fi + fi + + # Not "gcc", so try "cc", rejecting "/usr/ucb/cc". + if test -z "$CC"; then + echo $ac_n "checking for cc... $ac_c" 1>&6 + IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}:" + cc_rejected=no + for dir in $PATH; do + test -z "$dir" && dir=. + if test -f $dir/cc; then + if test "$dir/cc" = "/usr/ucb/cc"; then + cc_rejected=yes + continue + fi + CC="cc" + break + fi + done + IFS="$save_ifs" + if test $cc_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $CC + shift + if test $# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same name, so the bogon will be chosen + # first if we set CC to just the name; use the full file name. + shift + set dummy "$dir/cc" "$@" + shift + CC="$@" + fi + fi + + if test -n "$CC"; then + echo "$ac_t$CC" 1>&6 + else + echo "$ac_t"no 1>&6 + fi + + if test -z "$CC"; then + echo "$progname: error: no acceptable cc found in \$PATH" 1>&2 + exit 1 + fi + fi + + # Now see if the compiler is really GCC. + with_gcc=no + echo $ac_n "checking whether we are using GNU C... $ac_c" 1>&6 + echo "$progname:424: checking whether we are using GNU C" >&5 + + $rm conftest.c + cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + with_gcc=yes + fi + $rm conftest.c + echo "$ac_t$with_gcc" 1>&6 +fi + +# Allow CC to be a program name with arguments. +set dummy $CC +compiler="$2" + +echo $ac_n "checking for $compiler option to produce PIC... $ac_c" 1>&6 +pic_flag= +special_shlib_compile_flags= +wl= +link_static_flag= +no_builtin_flag= + +if test "$with_gcc" = yes; then + wl='-Wl,' + link_static_flag='-static' + no_builtin_flag=' -fno-builtin' + + case "$host_os" in + aix3* | aix4* | irix5* | irix6* | osf3* | osf4*) + # PIC is the default for these OSes. + ;; + os2*) + # We can build DLLs from non-PIC. + ;; + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + pic_flag='-m68020 -resident32 -malways-restore-a4' + ;; + *) + pic_flag='-fPIC' + ;; + esac +else + # PORTME Check for PIC flags for the system compiler. + case "$host_os" in + aix3* | aix4*) + # All AIX code is PIC. + link_static_flag='-bnso -bI:/lib/syscalls.exp' + ;; + + hpux9* | hpux10*) + # Is there a better link_static_flag that works with the bundled CC? + wl='-Wl,' + link_static_flag="${wl}-a ${wl}archive" + pic_flag='+Z' + ;; + + irix5* | irix6*) + wl='-Wl,' + link_static_flag='-non_shared' + # PIC (with -KPIC) is the default. + ;; + + os2*) + # We can build DLLs from non-PIC. + ;; + + osf3* | osf4*) + # All OSF/1 code is PIC. + wl='-Wl,' + link_static_flag='-non_shared' + ;; + + sco3.2v5*) + pic_flag='-Kpic' + link_static_flag='-dn' + special_shlib_compile_flags='-belf' + ;; + + solaris2*) + pic_flag='-KPIC' + link_static_flag='-Bstatic' + wl='-Wl,' + ;; + + sunos4*) + pic_flag='-PIC' + link_static_flag='-Bstatic' + wl='-Qoption ld ' + ;; + + sysv4.2uw2*) + pic_flag='-KPIC' + link_static_flag='-Bstatic' + wl='-Wl,' + ;; + + uts4*) + pic_flag='-pic' + link_static_flag='-Bstatic' + ;; + + *) + can_build_shared=no + ;; + esac +fi + +if test -n "$pic_flag"; then + echo "$ac_t$pic_flag" 1>&6 + + # Check to make sure the pic_flag actually works. + echo $ac_n "checking if $compiler PIC flag $pic_flag works... $ac_c" 1>&6 + $rm conftest* + echo > conftest.c + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $pic_flag -DPIC" + echo "$progname:547: checking if $compiler PIC flag $pic_flag works" >&5 + if { (eval echo $progname:548: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.o; then + # Append any warnings to the config.log. + cat conftest.err 1>&5 + + # On HP-UX, both CC and GCC only warn that PIC is supported... then they + # create non-PIC objects. So, if there were any warnings, we assume that + # PIC is not supported. + if test -s conftest.err; then + echo "$ac_t"no 1>&6 + can_build_shared=no + pic_flag= + else + echo "$ac_t"yes 1>&6 + pic_flag=" $pic_flag" + fi + else + # Append any errors to the config.log. + cat conftest.err 1>&5 + can_build_shared=no + pic_flag= + echo "$ac_t"no 1>&6 + fi + CFLAGS="$save_CFLAGS" + $rm conftest* +else + echo "$ac_t"none 1>&6 +fi + +# Check for any special shared library compilation flags. +if test -n "$special_shlib_compile_flags"; then + echo "$progname: warning: \`$CC' requires \`$special_shlib_compile_flags' to build shared libraries" 1>&2 + if echo "$old_CC $old_CFLAGS " | egrep -e "[ ]$special_shlib_compile_flags[ ]" >/dev/null; then : + else + echo "$progname: add \`$special_shlib_compile_flags' to the CC or CFLAGS env variable and reconfigure" 1>&2 + can_build_shared=no + fi +fi + +echo $ac_n "checking if $compiler static flag $link_static_flag works... $ac_c" 1>&6 +$rm conftest* +echo 'main(){return(0);}' > conftest.c +save_LDFLAGS="$LDFLAGS" +LDFLAGS="$LDFLAGS $link_static_flag" +echo "$progname:591: checking if $compiler static flag $link_static_flag works" >&5 +if { (eval echo $progname:592: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + echo "$ac_t$link_static_flag" 1>&6 +else + echo "$ac_t"none 1>&6 + link_static_flag= +fi +LDFLAGS="$save_LDFLAGS" +$rm conftest* + +if test -z "$LN_S"; then + # Check to see if we can use ln -s, or we need hard links. + echo $ac_n "checking whether ln -s works... $ac_c" 1>&6 + $rm conftestdata + if ln -s X conftestdata 2>/dev/null; then + $rm conftestdata + LN_S="ln -s" + else + LN_S=ln + fi + if test "$LN_S" = "ln -s"; then + echo "$ac_t"yes 1>&6 + else + echo "$ac_t"no 1>&6 + fi +fi + +# Make sure LD is an absolute path. +if test -z "$LD"; then + ac_prog=ld + if test "$with_gcc" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + echo $ac_n "checking for ld used by GCC... $ac_c" 1>&6 + echo "$progname:624: checking for ld used by GCC" >&5 + ac_prog=`($CC -print-prog-name=ld) 2>&5` + case "$ac_prog" in + # Accept absolute paths. + /* | [A-Za-z]:\\*) + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we are not using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac + elif test "$with_gnu_ld" = yes; then + echo $ac_n "checking for GNU ld... $ac_c" 1>&6 + echo "$progname:642: checking for GNU ld" >&5 + else + echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6 + echo "$progname:645: checking for non-GNU ld" >&5 + fi + + if test -z "$LD"; then + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog"; then + LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some GNU ld's only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + if "$LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then + test "$with_gnu_ld" != no && break + else + test "$with_gnu_ld" != yes && break + fi + fi + done + IFS="$ac_save_ifs" + fi + + if test -n "$LD"; then + echo "$ac_t$LD" 1>&6 + else + echo "$ac_t"no 1>&6 + fi + + if test -z "$LD"; then + echo "$progname: error: no acceptable ld found in \$PATH" 1>&2 + exit 1 + fi +fi + +# Check to see if it really is or is not GNU ld. +echo $ac_n "checking if the linker ($LD) is GNU ld... $ac_c" 1>&6 +# I'd rather use --version here, but apparently some GNU ld's only accept -v. +if $LD -v 2>&1 &5; then + with_gnu_ld=yes +else + with_gnu_ld=no +fi +echo "$ac_t$with_gnu_ld" 1>&6 + +# See if the linker supports building shared libraries. +echo $ac_n "checking whether the linker ($LD) supports shared libraries... $ac_c" 1>&6 + +allow_undefined_flag= +no_undefined_flag= +archive_cmds= +old_archive_from_new_cmds= +export_dynamic_flag_spec= +hardcode_libdir_flag_spec= +hardcode_libdir_separator= +hardcode_direct=no +hardcode_minus_L=no +hardcode_shlibpath_var=unsupported +runpath_var= + +case "$host_os" in +amigaos* | sunos4*) + # On these operating systems, we should treat GNU ld like the system ld. + gnu_ld_acts_native=yes + ;; +*) + gnu_ld_acts_native=no + ;; +esac + +ld_shlibs=yes +if test "$with_gnu_ld" = yes && test "$gnu_ld_acts_native" != yes; then + + # See if GNU ld supports shared libraries. + if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared ${wl}-soname $wl$soname -o $lib$libobjs' + runpath_var=LD_RUN_PATH + ld_shlibs=yes + else + ld_shlibs=no + fi + + if test "$ld_shlibs" = yes; then + hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec='${wl}--export-dynamic' + fi +else + # PORTME fill in a description of your system's linker (not GNU ld) + case "$host_os" in + aix3*) + allow_undefined_flag=unsupported + archive_cmds='$NM$libobjs | $global_symbol_pipe | sed '\''s/.* //'\'' > $lib.exp;$LD -o $objdir/$soname$libobjs -bE:$lib.exp -T512 -H512 -bM:SRE;$AR cru $lib $objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test "$with_gcc" = yes && test -z "$link_static_flag"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + + aix4*) + allow_undefined_flag=unsupported + archive_cmds='$NM$libobjs | $global_symbol_pipe | sed '\''s/.* //'\'' > $lib.exp;$CC -o $objdir/$soname$libobjs ${wl}-bE:$lib.exp ${wl}-bM:SRE ${wl}-bnoentry;$AR cru $lib $objdir/$soname' + hardcode_direct=yes + hardcode_minus_L=yes + ;; + + amigaos*) + archive_cmds='$rm $objdir/a2ixlibrary.data;$echo "#define NAME $libname" > $objdir/a2ixlibrary.data;$echo "#define LIBRARY_ID 1" >> $objdir/a2ixlibrary.data;$echo "#define VERSION $major" >> $objdir/a2ixlibrary.data;$echo "#define REVISION $revision" >> $objdir/a2ixlibrary.data;$AR cru $lib$libobjs;$RANLIB $lib;(cd $objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds='$LD -Bshareable -o $lib$libobjs /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + archive_cmds='$LD -Bshareable -o $lib$libobjs' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + # FreeBSD 3, at last, uses gcc -shared to do shared libraries. + freebsd3*) + archive_cmds='$CC -shared -o $lib$libobjs' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + hpux9*) + archive_cmds='$rm $objdir/$soname;$LD -b +s +b $install_libdir -o $objdir/$soname$libobjs;mv $objdir/$soname $lib' + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + export_dynamic_flag_spec='${wl}-E' + ;; + + hpux10*) + archive_cmds='$LD -b +h $soname +s +b $install_libdir -o $lib$libobjs' + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + export_dynamic_flag_spec='${wl}-E' + ;; + + irix5* | irix6*) + archive_cmds='$LD -shared -o $lib -soname $soname -set_version $verstring$libobjs' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + ;; + + netbsd*) + # Tested with NetBSD 1.2 ld + archive_cmds='$LD -Bshareable -o $lib$libobjs' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + openbsd*) + archive_cmds='$LD -Bshareable -o $lib$libobjs' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $objdir/$libname.def;$echo "DESCRIPTION \"$libname\"" >> $objdir/$libname.def;$echo DATA >> $objdir/$libname.def;$echo " SINGLE NONSHARED" >> $objdir/$libname.def;$echo EXPORTS >> $objdir/$libname.def;emxexp$libobjs >> $objdir/$libname.def;$CC -Zdll -Zcrtdll -o $lib$libobjs $objdir/$libname.def' + old_archive_from_new_cmds='emximp -o $objdir/$libname.a $objdir/$libname.def' + ;; + + osf3* | osf4*) + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$LD -shared${allow_undefined_flag} -o $lib -soname $soname -set_version $verstring$libobjs$deplibs' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + + sco3.2v5*) + archive_cmds='$LD -G -o $lib$libobjs' + hardcode_direct=yes + ;; + + solaris2*) + no_undefined_flag=' -z text' + archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib$libobjs' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_shlibpath_var=no + + # Solaris 2 before 2.5 hardcodes -L paths. + case "$host_os" in + solaris2.[0-4]*) + hardcode_minus_L=yes + ;; + esac + ;; + + sunos4*) + if test "$with_gcc" = yes; then + archive_cmds='$CC -shared -o $lib$libobjs' + else + archive_cmds='$LD -assert pure-text -Bstatic -o $lib$libobjs' + fi + + if test "$with_gnu_ld" = yes; then + export_dynamic_flag_spec='${wl}-export-dynamic' + fi + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + uts4*) + archive_cmds='$LD -G -h $soname -o $lib$libobjs' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=no + hardcode_minus_L=no + hardcode_shlibpath_var=no + ;; + + *) + ld_shlibs=no + can_build_shared=no + ;; + esac +fi +echo "$ac_t$ld_shlibs" 1>&6 + +if test -z "$NM"; then + echo $ac_n "checking for BSD-compatible nm... $ac_c" 1>&6 + case "$NM" in + /* | [A-Za-z]:\\*) ;; # Let the user override the test with a path. + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in /usr/ucb /usr/ccs/bin $PATH /bin; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/nm; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then + NM="$ac_dir/nm -B" + elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then + NM="$ac_dir/nm -p" + else + NM="$ac_dir/nm" + fi + break + fi + done + IFS="$ac_save_ifs" + test -z "$NM" && NM=nm + ;; + esac + echo "$ac_t$NM" 1>&6 +fi + +# Check for command to grab the raw symbol name followed by C symbol from nm. +echo $ac_n "checking command to parse $NM output... $ac_c" 1>&6 + +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[BCDEGRSTU]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Transform the above into a raw symbol and a C symbol. +symxfrm='\1 \1' + +# Define system-specific variables. +case "$host_os" in +aix*) + symcode='[BCDTU]' + ;; +irix*) + # Cannot use undefined symbols on IRIX because inlined functions mess us up. + symcode='[BCDEGRST]' + ;; +solaris2*) + symcode='[BDTU]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then + symcode='[ABCDGISTUW]' +fi + +# Write the raw and C identifiers. +global_symbol_pipe="sed -n -e 's/^.* $symcode $sympat$/$symxfrm/p'" + +# Check to see that the pipe works correctly. +pipe_works=no +$rm conftest* +cat > conftest.c <&5 +if { (eval echo $progname:972: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; } && test -s conftest.o; then + # Now try to grab the symbols. + nlist=conftest.nm + if { echo "$progname:975: eval \"$NM conftest.o | $global_symbol_pipe > $nlist\"" >&5; eval "$NM conftest.o | $global_symbol_pipe > $nlist 2>&5"; } && test -s "$nlist"; then + + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + wcout=`wc "$nlist" 2>/dev/null` + count=`$echo "X$wcout" | $Xsed -e 's/^[ ]*\([0-9][0-9]*\).*$/\1/'` + (test "$count" -ge 0) 2>/dev/null || count=-1 + else + rm -f "$nlist"T + count=-1 + fi + + # Make sure that we snagged all the symbols we need. + if egrep ' nm_test_var$' "$nlist" >/dev/null; then + if egrep ' nm_test_func$' "$nlist" >/dev/null; then + cat < conftest.c +#ifdef __cplusplus +extern "C" { +#endif + +EOF + # Now generate the symbol file. + sed 's/^.* \(.*\)$/extern char \1;/' < "$nlist" >> conftest.c + + cat <> conftest.c +#if defined (__STDC__) && __STDC__ +# define __ptr_t void * +#else +# define __ptr_t char * +#endif + +/* The number of symbols in dld_preloaded_symbols, -1 if unsorted. */ +int dld_preloaded_symbol_count = $count; + +/* The mapping between symbol names and symbols. */ +struct { + char *name; + __ptr_t address; +} +dld_preloaded_symbols[] = +{ +EOF + sed 's/^\(.*\) \(.*\)$/ {"\1", (__ptr_t) \&\2},/' < "$nlist" >> conftest.c + cat <<\EOF >> conftest.c + {0, (__ptr_t) 0} +}; + +#ifdef __cplusplus +} +#endif +EOF + # Now try linking the two files. + mv conftest.o conftestm.o + save_LIBS="$LIBS" + save_CFLAGS="$CFLAGS" + LIBS='conftestm.o' + CFLAGS="$CFLAGS$no_builtin_flag" + if { (eval echo $progname:1033: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + pipe_works=yes + else + echo "$progname: failed program was:" >&5 + cat conftest.c >&5 + fi + LIBS="$save_LIBS" + else + echo "cannot find nm_test_func in $nlist" >&5 + fi + else + echo "cannot find nm_test_var in $nlist" >&5 + fi + else + echo "cannot run $global_symbol_pipe" >&5 + fi +else + echo "$progname: failed program was:" >&5 + cat conftest.c >&5 +fi +$rm conftest* + +# Do not use the global_symbol_pipe unless it works. +echo "$ac_t$pipe_works" 1>&6 +test "$pipe_works" = yes || global_symbol_pipe= + +# Check hardcoding attributes. +echo $ac_n "checking how to hardcode library paths into programs... $ac_c" 1>&6 +hardcode_action= +if test -n "$hardcode_libdir_flag_spec" || \ + test -n "$runpath_var"; then + + # We can hardcode non-existant directories. + if test "$hardcode_direct" != no && \ + test "$hardcode_minus_L" != no && \ + test "$hardcode_shlibpath_var" != no; then + + # Linking always hardcodes the temporary library directory. + hardcode_action=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action=immediate + fi +elif test "$hardcode_direct" != yes && \ + test "$hardcode_minus_L" != yes && \ + test "$hardcode_shlibpath_var" != yes; then + # We cannot hardcode anything. + hardcode_action=unsupported +else + # We can only hardcode existing directories. + hardcode_action=relink +fi +echo "$ac_t$hardcode_action" 1>&6 +test "$hardcode_action" = unsupported && can_build_shared=no + + +reload_flag= +reload_cmds='$LD$reload_flag -o $output$reload_objs' +echo $ac_n "checking for $LD option to reload object files... $ac_c" 1>&6 +# PORTME Some linker may need a different reload flag. +reload_flag='-r' +echo "$ac_t$reload_flag" +test -n "$reload_flag" && reload_flag=" $reload_flag" + +# PORTME Fill in your ld.so characteristics +library_names_spec= +libname_spec='lib$name' +soname_spec= +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +version_type=none +dynamic_linker="$host_os ld.so" + +echo $ac_n "checking dynamic linker characteristics... $ac_c" 1>&6 +case "$host_os" in +aix3* | aix4*) + version_type=linux + library_names_spec='${libname}${release}.so.$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}.so.$major' + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "(cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a)"; (cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a) || exit 1; done' + ;; + +freebsd2* | freebsd3*) + version_type=sunos + library_names_spec='${libname}${release}.so.$versuffix $libname.so' + finish_cmds='PATH="$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + ;; + +gnu*) + version_type=sunos + library_names_spec='${libname}${release}.so.$versuffix' + shlibpath_var=LD_LIBRARY_PATH + ;; + +hpux9* | hpux10*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + dynamic_linker="$host_os dld.sl" + version_type=sunos + shlibpath_var=SHLIB_PATH + library_names_spec='${libname}${release}.sl.$versuffix ${libname}${release}.sl.$major $libname.sl' + soname_spec='${libname}${release}.sl.$major' + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +irix5* | irix6*) + version_type=osf + soname_spec='${libname}${release}.so' + library_names_spec='${libname}${release}.so.$versuffix $libname.so' + shlibpath_var=LD_LIBRARY_PATH + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux-gnuoldld* | linux-gnuaout* | linux-gnucoff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux-gnu*) + version_type=linux + library_names_spec='${libname}${release}.so.$versuffix ${libname}${release}.so.$major $libname.so' + soname_spec='${libname}${release}.so.$major' + finish_cmds='PATH="$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + + if test -f /lib/ld.so.1; then + dynamic_linker='GNU ld.so' + else + # Only the GNU ld.so supports shared libraries on MkLinux. + case "$host_cpu" in + powerpc*) dynamic_linker=no ;; + *) dynamic_linker='Linux ld.so' ;; + esac + fi + ;; + +netbsd* | openbsd*) + version_type=sunos + library_names_spec='${libname}${release}.so.$versuffix' + finish_cmds='PATH="$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + ;; + +os2*) + libname_spec='$name' + library_names_spec='$libname.dll $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4*) + version_type=osf + soname_spec='${libname}${release}.so' + library_names_spec='${libname}${release}.so.$versuffix $libname.so' + shlibpath_var=LD_LIBRARY_PATH + ;; + +sco3.2v5*) + version_type=osf + soname_spec='${libname}${release}.so.$major' + library_names_spec='${libname}${release}.so.$versuffix ${libname}${release}.so.$major $libname.so' + shlibpath_var=LD_LIBRARY_PATH + ;; + +solaris2*) + version_type=linux + library_names_spec='${libname}${release}.so.$versuffix ${libname}${release}.so.$major $libname.so' + soname_spec='${libname}${release}.so.$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}.so.$versuffix' + finish_cmds='PATH="$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + ;; + +sysv4.2uw2*) + version_type=linux + library_names_spec='${libname}${release}.so.$versuffix ${libname}${release}.so.$major $libname.so' + soname_spec='${libname}${release}.so.$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}.so.$versuffix ${libname}${release}.so.$major $libname.so' + soname_spec='${libname}${release}.so.$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +echo "$ac_t$dynamic_linker" +test "$dynamic_linker" = no && can_build_shared=no + +# Report the final consequences. +echo "checking if libtool supports shared libraries... $can_build_shared" 1>&6 + +echo $ac_n "checking whether to build shared libraries... $ac_c" 1>&6 +test "$can_build_shared" = "no" && enable_shared=no + +# On AIX, shared libraries and static libraries use the same namespace, and +# are all built from PIC. +case "$host_os" in +aix*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds;\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; +esac + +echo "$ac_t$enable_shared" 1>&6 + +# Make sure either enable_shared or enable_static is yes. +test "$enable_shared" = yes || enable_static=yes + +echo "checking whether to build static libraries... $enable_static" 1>&6 + +echo $ac_n "checking for objdir... $ac_c" 1>&6 +rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + objdir=_libs +fi +rmdir .libs 2>/dev/null +echo "$ac_t$objdir" 1>&6 + +# Copy echo and quote the copy, instead of the original, because it is +# used later. +ltecho="$echo" + +# Now quote all the things that may contain metacharacters. +for var in ltecho old_CC old_CFLAGS old_CPPFLAGS old_LD old_NM old_RANLIB \ + old_LN_S AR CC LD LN_S NM reload_flag reload_cmds wl pic_flag \ + link_static_flag no_builtin_flag export_dynamic_flag_spec \ + libname_spec library_names_spec soname_spec RANLIB \ + old_archive_cmds old_archive_from_new_cmds old_postinstall_cmds \ + old_postuninstall_cmds archive_cmds postinstall_cmds postuninstall_cmds \ + allow_undefined_flag no_undefined_flag \ + finish_cmds finish_eval global_symbol_pipe \ + hardcode_libdir_flag_spec hardcode_libdir_separator; do + + case "$var" in + reload_cmds | old_archive_cmds | old_archive_from_new_cmds | \ + old_postinstall_cmds | old_postuninstall_cmds | archive_cmds | \ + postinstall_cmds | postuninstall_cmds | finish_cmds) + # Double-quote double-evaled strings. + eval "$var=\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\"\`" + ;; + *) + eval "$var=\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`" + ;; + esac +done + +ofile=libtool +trap "$rm $ofile; exit 1" 1 2 15 +echo creating $ofile +$rm $ofile +cat < $ofile +#! /bin/sh + +# libtool - Provide generalized library-building support services. +# Generated automatically by $PROGRAM - GNU $PACKAGE $VERSION +# NOTE: Changes made to this file will be lost: look at ltconfig or ltmain.sh. +# +# Copyright (C) 1996-1998 Free Software Foundation, Inc. +# Gordon Matzigkeit , 1996 +# +# This program 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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. + +# This program was configured as follows, +# on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# +# CC="$old_CC" CFLAGS="$old_CFLAGS" CPPFLAGS="$old_CPPFLAGS" \\ +# LD="$old_LD" NM="$old_NM" RANLIB="$old_RANLIB" LN_S="$old_LN_S" \\ +# $0$ltconfig_args +# +# Compiler and other test output produced by $progname, useful for +# debugging $progname, is in ./config.log if it exists. + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="sed -e s/^X//" + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +if test "\${CDPATH+set}" = set; then CDPATH=; export CDPATH; fi + +# An echo program that does not interpret backslashes. +echo="$ltecho" + +# The version of $progname that generated this script. +LTCONFIG_VERSION="$VERSION" + +# Shell to use when invoking shell scripts. +SHELL=${CONFIG_SHELL-/bin/sh} + +# Whether or not to build libtool libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build old-style libraries. +build_old_libs=$enable_static + +# The host system. +host_alias="$host_alias" +host="$host" + +# The archiver. +AR="$AR" + +# The default C compiler. +CC="$CC" + +# The linker used to build libraries. +LD="$LD" + +# Whether we need hard or soft links. +LN_S="$LN_S" + +# A BSD-compatible nm program. +NM="$NM" + +# The name of the directory that contains temporary libtool files. +objdir="$objdir" + +# How to create reloadable object files. +reload_flag="$reload_flag" +reload_cmds="$reload_cmds" + +# How to pass a linker flag through the compiler. +wl="$wl" + +# Additional compiler flags for building library objects. +pic_flag="$pic_flag" + +# Compiler flag to prevent dynamic linking. +link_static_flag="$link_static_flag" + +# Compiler flag to turn off builtin functions. +no_builtin_flag="$no_builtin_flag" + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec="$export_dynamic_flag_spec" + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec="$libname_spec" + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec="$library_names_spec" + +# The coded name of the library, if different from the real name. +soname_spec="$soname_spec" + +# Commands used to build and install an old-style archive. +RANLIB="$RANLIB" +old_archive_cmds="$old_archive_cmds" +old_postinstall_cmds="$old_postinstall_cmds" +old_postuninstall_cmds="$old_postuninstall_cmds" + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds="$old_archive_from_new_cmds" + +# Commands used to build and install a shared archive. +archive_cmds="$archive_cmds" +postinstall_cmds="$postinstall_cmds" +postuninstall_cmds="$postuninstall_cmds" + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag="$allow_undefined_flag" + +# Flag that forces no undefined symbols. +no_undefined_flag="$no_undefined_flag" + +# Commands used to finish a libtool library installation in a directory. +finish_cmds="$finish_cmds" + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval="$finish_eval" + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe="$global_symbol_pipe" + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec="$hardcode_libdir_flag_spec" + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator="$hardcode_libdir_separator" + +# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$hardcode_direct + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$hardcode_minus_L + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var + +EOF + +case "$host_os" in +aix3*) + cat <<\EOF >> $ofile +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "${COLLECT_NAMES+set}" != set; then + COLLECT_NAMES= + export COLLECT_NAMES +fi + +EOF + ;; +esac + +# Append the ltmain.sh script. +cat "$ltmain" >> $ofile || (rm -f $ofile; exit 1) + +chmod +x $ofile +exit 0 + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: diff --git a/lc-continuity/mk4/modimage/jpeg-6b/ltmain.sh b/lc-continuity/mk4/modimage/jpeg-6b/ltmain.sh new file mode 100644 index 0000000000000000000000000000000000000000..e9350b3fab0c4d1c26d3120d0caf7b823dcd0a5a --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/ltmain.sh @@ -0,0 +1,2453 @@ +# ltmain.sh - Provide generalized library-building support services. +# NOTE: Changing this file will not affect anything until you rerun ltconfig. +# +# Copyright (C) 1996-1998 Free Software Foundation, Inc. +# Gordon Matzigkeit , 1996 +# +# This program 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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. + +# The name of this program. +progname=`$echo "$0" | sed 's%^.*/%%'` +modename="$progname" + +# Constants. +PROGRAM=ltmain.sh +PACKAGE=libtool +VERSION=1.2 + +default_mode= +help="Try \`$progname --help' for more information." +magic="%%%MAGIC variable%%%" +mkdir="mkdir" +mv="mv -f" +rm="rm -f" + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='sed -e s/^X//' +sed_quote_subst='s/\([\\`\\"$\\\\]\)/\\\1/g' + +# NLS nuisances. +# Only set LANG and LC_ALL to C if already set. +# These must not be set unconditionally because not all systems understand +# e.g. LANG=C (notably SCO). +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LANG+set}" = set; then LANG=C; export LANG; fi + +if test "$LTCONFIG_VERSION" != "$VERSION"; then + echo "$modename: ltconfig version \`$LTCONFIG_VERSION' does not match $PROGRAM version \`$VERSION'" 1>&2 + echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit 1 +fi + +if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then + echo "$modename: not configured to build any kind of library" 1>&2 + echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit 1 +fi + +# Global variables. +mode=$default_mode +nonopt= +prev= +prevopt= +run= +show="$echo" +show_help= +execute_dlfiles= + +# Parse our command line options once, thoroughly. +while test $# -gt 0 +do + arg="$1" + shift + + case "$arg" in + -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;; + *) optarg= ;; + esac + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case "$prev" in + execute_dlfiles) + eval "$prev=\"\$$prev \$arg\"" + ;; + *) + eval "$prev=\$arg" + ;; + esac + + prev= + prevopt= + continue + fi + + # Have we seen a non-optional argument yet? + case "$arg" in + --help) + show_help=yes + ;; + + --version) + echo "$PROGRAM (GNU $PACKAGE) $VERSION" + exit 0 + ;; + + --dry-run | -n) + run=: + ;; + + --features) + echo "host: $host" + if test "$build_libtool_libs" = yes; then + echo "enable shared libraries" + else + echo "disable shared libraries" + fi + if test "$build_old_libs" = yes; then + echo "enable static libraries" + else + echo "disable static libraries" + fi + exit 0 + ;; + + --finish) mode="finish" ;; + + --mode) prevopt="--mode" prev=mode ;; + --mode=*) mode="$optarg" ;; + + --quiet | --silent) + show=: + ;; + + -dlopen) + prevopt="-dlopen" + prev=execute_dlfiles + ;; + + -*) + $echo "$modename: unrecognized option \`$arg'" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + + *) + nonopt="$arg" + break + ;; + esac +done + +if test -n "$prevopt"; then + $echo "$modename: option \`$prevopt' requires an argument" 1>&2 + $echo "$help" 1>&2 + exit 1 +fi + +if test -z "$show_help"; then + + # Infer the operation mode. + if test -z "$mode"; then + case "$nonopt" in + *cc | *++ | gcc* | *-gcc*) + mode=link + for arg + do + case "$arg" in + -c) + mode=compile + break + ;; + esac + done + ;; + *db | *dbx) + mode=execute + ;; + *install*|cp|mv) + mode=install + ;; + *rm) + mode=uninstall + ;; + *) + # If we have no mode, but dlfiles were specified, then do execute mode. + test -n "$execute_dlfiles" && mode=execute + + # Just use the default operation mode. + if test -z "$mode"; then + if test -n "$nonopt"; then + $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2 + else + $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2 + fi + fi + ;; + esac + fi + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$execute_dlfiles" && test "$mode" != execute; then + $echo "$modename: unrecognized option \`-dlopen'" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + # Change the help message to a mode-specific one. + generic_help="$help" + help="Try \`$modename --help --mode=$mode' for more information." + + # These modes are in order of execution frequency so that they run quickly. + case "$mode" in + # libtool compile mode + compile) + modename="$modename: compile" + # Get the compilation command and the source file. + base_compile= + lastarg= + srcfile="$nonopt" + suppress_output= + + for arg + do + # Accept any command-line options. + case "$arg" in + -o) + $echo "$modename: you cannot specify the output filename with \`-o'" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + + -static) + build_libtool_libs=no + build_old_libs=yes + continue + ;; + esac + + # Accept the current argument as the source file. + lastarg="$srcfile" + srcfile="$arg" + + # Aesthetically quote the previous argument. + + # Backslashify any backslashes, double quotes, and dollar signs. + # These are the only characters that are still specially + # interpreted inside of double-quoted scrings. + lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"` + + # Double-quote args containing other shell metacharacters. + # Many Bourne shells cannot handle close brackets correctly in scan + # sets, so we specify it separately. + case "$lastarg" in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + lastarg="\"$lastarg\"" + ;; + esac + + # Add the previous argument to base_compile. + if test -z "$base_compile"; then + base_compile="$lastarg" + else + base_compile="$base_compile $lastarg" + fi + done + + # Get the name of the library object. + libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'` + + # Recognize several different file suffixes. + xform='[cCFSfms]' + case "$libobj" in + *.ada) xform=ada ;; + *.adb) xform=adb ;; + *.ads) xform=ads ;; + *.asm) xform=asm ;; + *.c++) xform=c++ ;; + *.cc) xform=cc ;; + *.cpp) xform=cpp ;; + *.cxx) xform=cxx ;; + *.f90) xform=f90 ;; + *.for) xform=for ;; + esac + + libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"` + + case "$libobj" in + *.lo) obj=`$echo "X$libobj" | $Xsed -e 's/\.lo$/.o/'` ;; + *) + $echo "$modename: cannot determine name of library object from \`$srcfile'" 1>&2 + exit 1 + ;; + esac + + if test -z "$base_compile"; then + $echo "$modename: you must specify a compilation command" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + # Delete any leftover library objects. + if test "$build_old_libs" = yes; then + $run $rm $obj $libobj + trap "$run $rm $obj $libobj; exit 1" 1 2 15 + else + $run $rm $libobj + trap "$run $rm $libobj; exit 1" 1 2 15 + fi + + # Only build a PIC object if we are building libtool libraries. + if test "$build_libtool_libs" = yes; then + # Without this assignment, base_compile gets emptied. + fbsd_hideous_sh_bug=$base_compile + + # All platforms use -DPIC, to notify preprocessed assembler code. + $show "$base_compile$pic_flag -DPIC $srcfile" + if $run eval "$base_compile\$pic_flag -DPIC \$srcfile"; then : + else + test -n "$obj" && $run $rm $obj + exit 1 + fi + + # If we have no pic_flag, then copy the object into place and finish. + if test -z "$pic_flag"; then + $show "$LN_S $obj $libobj" + $run $LN_S $obj $libobj + exit $? + fi + + # Just move the object, then go on to compile the next one + $show "$mv $obj $libobj" + $run $mv $obj $libobj || exit 1 + + # Allow error messages only from the first compilation. + suppress_output=' >/dev/null 2>&1' + fi + + # Only build a position-dependent object if we build old libraries. + if test "$build_old_libs" = yes; then + # Suppress compiler output if we already did a PIC compilation. + $show "$base_compile $srcfile$suppress_output" + if $run eval "$base_compile \$srcfile$suppress_output"; then : + else + $run $rm $obj $libobj + exit 1 + fi + fi + + # Create an invalid libtool object if no PIC, so that we do not + # accidentally link it into a program. + if test "$build_libtool_libs" != yes; then + $show "echo timestamp > $libobj" + $run eval "echo timestamp > \$libobj" || exit $? + fi + + exit 0 + ;; + + # libtool link mode + link) + modename="$modename: link" + CC="$nonopt" + allow_undefined=yes + compile_command="$CC" + finalize_command="$CC" + + compile_shlibpath= + finalize_shlibpath= + deplibs= + dlfiles= + dlprefiles= + export_dynamic=no + hardcode_libdirs= + libobjs= + link_against_libtool_libs= + ltlibs= + objs= + prev= + prevarg= + release= + rpath= + perm_rpath= + temp_rpath= + vinfo= + + # We need to know -static, to get the right output filenames. + for arg + do + case "$arg" in + -all-static | -static) + if test "X$arg" = "X-all-static" && test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then + $echo "$modename: warning: complete static linking is impossible in this configuration" 1>&2 + fi + build_libtool_libs=no + build_old_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + for arg + do + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case "$prev" in + output) + compile_command="$compile_command @OUTPUT@" + finalize_command="$finalize_command @OUTPUT@" + ;; + esac + + case "$prev" in + dlfiles|dlprefiles) + case "$arg" in + *.la | *.lo) ;; # We handle these cases below. + *) + dlprefiles="$dlprefiles $arg" + test "$prev" = dlfiles && dlfiles="$dlfiles $arg" + prev= + ;; + esac + ;; + release) + release="-$arg" + prev= + continue + ;; + rpath) + rpath="$rpath $arg" + prev= + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi + + prevarg="$arg" + + case "$arg" in + -all-static) + if test -n "$link_static_flag"; then + compile_command="$compile_command $link_static_flag" + finalize_command="$finalize_command $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2 + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + if test "$export_dynamic" != yes; then + export_dynamic=yes + if test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + else + arg= + fi + + # Add the symbol object into the linking commands. + compile_command="$compile_command @SYMFILE@" + finalize_command="$finalize_command @SYMFILE@" + fi + ;; + + -L*) + dir=`$echo "X$arg" | $Xsed -e 's%^-L\(.*\)$%\1%'` + case "$dir" in + /* | [A-Za-z]:\\*) + # Add the corresponding hardcode_libdir_flag, if it is not identical. + ;; + *) + $echo "$modename: \`-L$dir' cannot specify a relative directory" 1>&2 + exit 1 + ;; + esac + deplibs="$deplibs $arg" + ;; + + -l*) deplibs="$deplibs $arg" ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -o) prev=output ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -static) + # If we have no pic_flag, then this is the same as -all-static. + if test -z "$pic_flag" && test -n "$link_static_flag"; then + compile_command="$compile_command $link_static_flag" + finalize_command="$finalize_command $link_static_flag" + fi + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + + # Some other compiler flag. + -* | +*) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case "$arg" in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + arg="\"$arg\"" + ;; + esac + ;; + + *.o | *.a) + # A standard object. + objs="$objs $arg" + ;; + + *.lo) + # A library object. + if test "$prev" = dlfiles; then + dlfiles="$dlfiles $arg" + if test "$build_libtool_libs" = yes; then + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + if test "$prev" = dlprefiles; then + # Preload the old-style object. + dlprefiles="$dlprefiles "`$echo "X$arg" | $Xsed -e 's/\.lo$/\.o/'` + prev= + fi + libobjs="$libobjs $arg" + ;; + + *.la) + # A libtool-controlled library. + + dlname= + libdir= + library_names= + old_library= + + # Check to see that this really is a libtool archive. + if (sed -e '2q' $arg | egrep '^# Generated by ltmain\.sh') >/dev/null 2>&1; then : + else + $echo "$modename: \`$arg' is not a valid libtool archive" 1>&2 + exit 1 + fi + + # If there is no directory component, then add one. + case "$arg" in + */* | *\\*) . $arg ;; + *) . ./$arg ;; + esac + + if test -z "$libdir"; then + $echo "$modename: \`$arg' contains no -rpath information" 1>&2 + exit 1 + fi + + # Get the name of the library we link against. + linklib= + for l in $old_library $library_names; do + linklib="$l" + done + + if test -z "$linklib"; then + $echo "$modename: cannot find name of link library for \`$arg'" 1>&2 + exit 1 + fi + + # Find the relevant object directory and library name. + name=`$echo "X$arg" | $Xsed -e 's%^.*/%%' -e 's/\.la$//' -e 's/^lib//'` + dir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` + if test "X$dir" = "X$arg"; then + dir="$objdir" + else + dir="$dir/$objdir" + fi + + # This library was specified with -dlopen. + if test "$prev" = dlfiles; then + dlfiles="$dlfiles $arg" + if test -z "$dlname"; then + # If there is no dlname, we need to preload. + prev=dlprefiles + else + # We should not create a dependency on this library, but we + # may need any libraries it requires. + compile_command="$compile_command$dependency_libs" + finalize_command="$finalize_command$dependency_libs" + prev= + continue + fi + fi + + # The library was specified with -dlpreopen. + if test "$prev" = dlprefiles; then + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + dlprefiles="$dlprefiles $dir/$old_library" + else + dlprefiles="$dlprefiles $dir/$linklib" + fi + prev= + fi + + if test "$build_libtool_libs" = yes && test -n "$library_names"; then + link_against_libtool_libs="$link_against_libtool_libs $arg" + if test -n "$shlibpath_var"; then + # Make sure the rpath contains only unique directories. + case "$temp_rpath " in + *" $dir "*) ;; + *) temp_rpath="$temp_rpath $dir" ;; + esac + fi + + # This is the magic to use -rpath. + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + # Put the magic libdir with the hardcode flag. + hardcode_libdirs="$libdir" + libdir="@HARDCODE_LIBDIRS@" + else + # Just accumulate the unique libdirs. + case "$hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator" in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + libdir= + fi + fi + + if test -n "$libdir"; then + eval flag=\"$hardcode_libdir_flag_spec\" + + compile_command="$compile_command $flag" + finalize_command="$finalize_command $flag" + fi + elif test -n "$runpath_var"; then + # Do the same for the permanent run path. + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$perm_rpath $libdir" ;; + esac + fi + + + case "$hardcode_action" in + immediate) + if test "$hardcode_direct" = no; then + compile_command="$compile_command $dir/$linklib" + elif test "$hardcode_minus_L" = no; then + compile_command="$compile_command -L$dir -l$name" + elif test "$hardcode_shlibpath_var" = no; then + compile_shlibpath="$compile_shlibpath$dir:" + compile_command="$compile_command -l$name" + fi + ;; + + relink) + # We need an absolute path. + case "$dir" in + /* | [A-Za-z]:\\*) ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2 + exit 1 + fi + dir="$absdir" + ;; + esac + + if test "$hardcode_direct" = yes; then + compile_command="$compile_command $dir/$linklib" + elif test "$hardcode_minus_L" = yes; then + compile_command="$compile_command -L$dir -l$name" + elif test "$hardcode_shlibpath_var" = yes; then + compile_shlibpath="$compile_shlibpath$dir:" + compile_command="$compile_command -l$name" + fi + ;; + + *) + $echo "$modename: \`$hardcode_action' is an unknown hardcode action" 1>&2 + exit 1 + ;; + esac + + # Finalize command for both is simple: just hardcode it. + if test "$hardcode_direct" = yes; then + finalize_command="$finalize_command $libdir/$linklib" + elif test "$hardcode_minus_L" = yes; then + finalize_command="$finalize_command -L$libdir -l$name" + elif test "$hardcode_shlibpath_var" = yes; then + finalize_shlibpath="$finalize_shlibpath$libdir:" + finalize_command="$finalize_command -l$name" + else + # We cannot seem to hardcode it, guess we'll fake it. + finalize_command="$finalize_command -L$libdir -l$name" + fi + else + # Transform directly to old archives if we don't build new libraries. + if test -n "$pic_flag" && test -z "$old_library"; then + $echo "$modename: cannot find static library for \`$arg'" 1>&2 + exit 1 + fi + + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test "$hardcode_direct" != unsupported; then + test -n "$old_library" && linklib="$old_library" + compile_command="$compile_command $dir/$linklib" + finalize_command="$finalize_command $dir/$linklib" + else + compile_command="$compile_command -L$dir -l$name" + finalize_command="$finalize_command -L$dir -l$name" + fi + fi + + # Add in any libraries that this one depends upon. + compile_command="$compile_command$dependency_libs" + finalize_command="$finalize_command$dependency_libs" + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case "$arg" in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + arg="\"$arg\"" + ;; + esac + ;; + esac + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + fi + done + + if test -n "$prev"; then + $echo "$modename: the \`$prevarg' option requires an argument" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + if test -n "$vinfo" && test -n "$release"; then + $echo "$modename: you cannot specify both \`-version-info' and \`-release'" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + oldlib= + oldobjs= + case "$output" in + "") + $echo "$modename: you must specify an output file" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + + */* | *\\*) + $echo "$modename: output file \`$output' must have no directory components" 1>&2 + exit 1 + ;; + + *.a) + # Now set the variables for building old libraries. + build_libtool_libs=no + build_old_libs=yes + oldlib="$output" + $show "$rm $oldlib" + $run $rm $oldlib + ;; + + *.la) + # Make sure we only generate libraries of the form `libNAME.la'. + case "$output" in + lib*) ;; + *) + $echo "$modename: libtool library \`$arg' must begin with \`lib'" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + esac + + name=`$echo "X$output" | $Xsed -e 's/\.la$//' -e 's/^lib//'` + eval libname=\"$libname_spec\" + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + current=0 + revision=0 + age=0 + + if test -n "$objs"; then + $echo "$modename: cannot build libtool library \`$output' from non-libtool objects:$objs" 2>&1 + exit 1 + fi + + # How the heck are we supposed to write a wrapper for a shared library? + if test -n "$link_against_libtool_libs"; then + $echo "$modename: libtool library \`$output' may not depend on uninstalled libraries:$link_against_libtool_libs" 1>&2 + exit 1 + fi + + if test -n "$dlfiles$dlprefiles"; then + $echo "$modename: warning: \`-dlopen' is ignored while creating libtool libraries" 1>&2 + # Nullify the symbol file. + compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` + fi + + if test -z "$rpath"; then + $echo "$modename: you must specify an installation directory with \`-rpath'" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + set dummy $rpath + if test $# -gt 2; then + $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2 + fi + install_libdir="$2" + + # Parse the version information argument. + IFS="${IFS= }"; save_ifs="$IFS"; IFS=':' + set dummy $vinfo + IFS="$save_ifs" + + if test -n "$5"; then + $echo "$modename: too many parameters to \`-version-info'" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + test -n "$2" && current="$2" + test -n "$3" && revision="$3" + test -n "$4" && age="$4" + + # Check that each of the things are valid numbers. + case "$current" in + 0 | [1-9] | [1-9][0-9]*) ;; + *) + $echo "$modename: CURRENT \`$current' is not a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit 1 + ;; + esac + + case "$revision" in + 0 | [1-9] | [1-9][0-9]*) ;; + *) + $echo "$modename: REVISION \`$revision' is not a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit 1 + ;; + esac + + case "$age" in + 0 | [1-9] | [1-9][0-9]*) ;; + *) + $echo "$modename: AGE \`$age' is not a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit 1 + ;; + esac + + if test $age -gt $current; then + $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit 1 + fi + + # Calculate the version variables. + version_vars="version_type current age revision" + case "$version_type" in + none) ;; + + linux) + version_vars="$version_vars major versuffix" + major=`expr $current - $age` + versuffix="$major.$age.$revision" + ;; + + osf) + version_vars="$version_vars versuffix verstring" + major=`expr $current - $age` + versuffix="$current.$age.$revision" + verstring="$versuffix" + + # Add in all the interfaces that we are compatible with. + loop=$age + while test $loop != 0; do + iface=`expr $current - $loop` + loop=`expr $loop - 1` + verstring="$verstring:${iface}.0" + done + + # Make executables depend on our current version. + verstring="$verstring:${current}.0" + ;; + + sunos) + version_vars="$version_vars major versuffix" + major="$current" + versuffix="$current.$revision" + ;; + + *) + $echo "$modename: unknown library version type \`$version_type'" 1>&2 + echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit 1 + ;; + esac + + # Create the output directory, or remove our outputs if we need to. + if test -d $objdir; then + $show "$rm $objdir/$output $objdir/$libname.* $objdir/${libname}${release}.*" + $run $rm $objdir/$output $objdir/$libname.* $objdir/${libname}${release}.* + else + $show "$mkdir $objdir" + $run $mkdir $objdir + status=$? + if test $status -eq 0 || test -d $objdir; then : + else + exit $status + fi + fi + + # Check to see if the archive will have undefined symbols. + if test "$allow_undefined" = yes; then + if test "$allow_undefined_flag" = unsupported; then + $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2 + build_libtool_libs=no + build_old_libs=yes + fi + else + # Don't allow undefined symbols. + allow_undefined_flag="$no_undefined_flag" + fi + + # Add libc to deplibs on all systems. + dependency_libs="$deplibs" + deplibs="$deplibs -lc" + + if test "$build_libtool_libs" = yes; then + # Get the real and link names of the library. + eval library_names=\"$library_names_spec\" + set dummy $library_names + realname="$2" + shift; shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + + lib="$objdir/$realname" + for link + do + linknames="$linknames $link" + done + + # Use standard objects if they are PIC. + test -z "$pic_flag" && libobjs=`$echo "X$libobjs " | $Xsed -e 's/\.lo /.o /g' -e 's/ $//g'` + + # Do each of the archive commands. + eval cmds=\"$archive_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS=';' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + + # Create links to the real library. + for linkname in $linknames; do + $show "(cd $objdir && $LN_S $realname $linkname)" + $run eval '(cd $objdir && $LN_S $realname $linkname)' || exit $? + done + + # If -export-dynamic was specified, set the dlname. + if test "$export_dynamic" = yes; then + # On all known operating systems, these are identical. + dlname="$soname" + fi + fi + + # Now set the variables for building old libraries. + oldlib="$objdir/$libname.a" + ;; + + *.lo | *.o) + if test -n "$link_against_libtool_libs"; then + $echo "$modename: error: cannot link libtool libraries into reloadable objects" 1>&2 + exit 1 + fi + + if test -n "$deplibs"; then + $echo "$modename: warning: \`-l' and \`-L' are ignored while creating objects" 1>&2 + fi + + if test -n "$dlfiles$dlprefiles"; then + $echo "$modename: warning: \`-dlopen' is ignored while creating objects" 1>&2 + # Nullify the symbol file. + compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` + fi + + if test -n "$rpath"; then + $echo "$modename: warning: \`-rpath' is ignored while creating objects" 1>&2 + fi + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored while creating objects" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored while creating objects" 1>&2 + fi + + case "$output" in + *.lo) + if test -n "$objs"; then + $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2 + exit 1 + fi + libobj="$output" + obj=`$echo "X$output" | $Xsed -e 's/\.lo$/.o/'` + ;; + *) + libobj= + obj="$output" + ;; + esac + + # Delete the old objects. + $run $rm $obj $libobj + + # Create the old-style object. + reload_objs="$objs"`$echo "X$libobjs " | $Xsed -e 's/[^ ]*\.a //g' -e 's/\.lo /.o /g' -e 's/ $//g'` + + output="$obj" + eval cmds=\"$reload_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS=';' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + + # Exit if we aren't doing a library object file. + test -z "$libobj" && exit 0 + + if test "$build_libtool_libs" != yes; then + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + $show "echo timestamp > $libobj" + $run eval "echo timestamp > $libobj" || exit $? + exit 0 + fi + + if test -n "$pic_flag"; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs" + output="$libobj" + eval cmds=\"$reload_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS=';' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + else + # Just create a symlink. + $show "$LN_S $obj $libobj" + $run $LN_S $obj $libobj || exit 1 + fi + + exit 0 + ;; + + *) + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored while linking programs" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored while creating objects" 1>&2 + fi + + if test -n "$rpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + # Put the magic libdir with the hardcode flag. + hardcode_libdirs="$libdir" + libdir="@HARDCODE_LIBDIRS@" + else + # Just accumulate the unique libdirs. + case "$hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator" in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + libdir= + fi + fi + + if test -n "$libdir"; then + eval flag=\"$hardcode_libdir_flag_spec\" + + compile_command="$compile_command $flag" + finalize_command="$finalize_command $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$perm_rpath $libdir" ;; + esac + fi + done + fi + + # Substitute the hardcoded libdirs into the compile commands. + if test -n "$hardcode_libdir_separator"; then + compile_command=`$echo "X$compile_command" | $Xsed -e "s%@HARDCODE_LIBDIRS@%$hardcode_libdirs%g"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@HARDCODE_LIBDIRS@%$hardcode_libdirs%g"` + fi + + if test -n "$libobjs" && test "$build_old_libs" = yes; then + # Transform all the library objects into standard objects. + compile_command=`$echo "X$compile_command " | $Xsed -e 's/\.lo /.o /g' -e 's/ $//'` + finalize_command=`$echo "X$finalize_command " | $Xsed -e 's/\.lo /.o /g' -e 's/ $//'` + fi + + if test "$export_dynamic" = yes && test -n "$NM" && test -n "$global_symbol_pipe"; then + dlsyms="${output}S.c" + else + dlsyms= + fi + + if test -n "$dlsyms"; then + # Add our own program objects to the preloaded list. + dlprefiles=`$echo "X$objs$dlprefiles " | $Xsed -e 's/\.lo /.o /g' -e 's/ $//'` + + # Discover the nlist of each of the dlfiles. + nlist="$objdir/${output}.nm" + + if test -d $objdir; then + $show "$rm $nlist ${nlist}T" + $run $rm "$nlist" "${nlist}T" + else + $show "$mkdir $objdir" + $run $mkdir $objdir + status=$? + if test $status -eq 0 || test -d $objdir; then : + else + exit $status + fi + fi + + for arg in $dlprefiles; do + $show "extracting global C symbols from \`$arg'" + $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" + done + + # Parse the name list into a source file. + $show "creating $objdir/$dlsyms" + if test -z "$run"; then + # Make sure we at least have an empty file. + test -f "$nlist" || : > "$nlist" + + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + wcout=`wc "$nlist" 2>/dev/null` + count=`echo "X$wcout" | $Xsed -e 's/^[ ]*\([0-9][0-9]*\).*$/\1/'` + (test "$count" -ge 0) 2>/dev/null || count=-1 + else + $rm "$nlist"T + count=-1 + fi + + case "$dlsyms" in + "") ;; + *.c) + $echo > "$objdir/$dlsyms" "\ +/* $dlsyms - symbol resolution table for \`$output' dlsym emulation. */ +/* Generated by $PROGRAM - GNU $PACKAGE $VERSION */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +/* Prevent the only kind of declaration conflicts we can make. */ +#define dld_preloaded_symbol_count some_other_symbol +#define dld_preloaded_symbols some_other_symbol + +/* External symbol declarations for the compiler. */\ +" + + if test -f "$nlist"; then + sed -e 's/^.* \(.*\)$/extern char \1;/' < "$nlist" >> "$objdir/$dlsyms" + else + echo '/* NONE */' >> "$objdir/$dlsyms" + fi + + $echo >> "$objdir/$dlsyms" "\ + +#undef dld_preloaded_symbol_count +#undef dld_preloaded_symbols + +#if defined (__STDC__) && __STDC__ +# define __ptr_t void * +#else +# define __ptr_t char * +#endif + +/* The number of symbols in dld_preloaded_symbols, -1 if unsorted. */ +int dld_preloaded_symbol_count = $count; + +/* The mapping between symbol names and symbols. */ +struct { + char *name; + __ptr_t address; +} +dld_preloaded_symbols[] = +{\ +" + + if test -f "$nlist"; then + sed 's/^\(.*\) \(.*\)$/ {"\1", (__ptr_t) \&\2},/' < "$nlist" >> "$objdir/$dlsyms" + fi + + $echo >> "$objdir/$dlsyms" "\ + {0, (__ptr_t) 0} +}; + +#ifdef __cplusplus +} +#endif\ +" + ;; + + *) + $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2 + exit 1 + ;; + esac + fi + + # Now compile the dynamic symbol file. + $show "(cd $objdir && $CC -c$no_builtin_flag \"$dlsyms\")" + $run eval '(cd $objdir && $CC -c$no_builtin_flag "$dlsyms")' || exit $? + + # Transform the symbol file into the correct name. + compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$objdir/${output}S.o%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$objdir/${output}S.o%"` + elif test "$export_dynamic" != yes; then + test -n "$dlfiles$dlprefiles" && $echo "$modename: warning: \`-dlopen' and \`-dlpreopen' are ignored without \`-export-dynamic'" 1>&2 + else + # We keep going just in case the user didn't refer to + # dld_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2 + + # Nullify the symbol file. + compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` + fi + + if test -z "$link_against_libtool_libs" || test "$build_libtool_libs" != yes; then + # Replace the output file specification. + compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + finalize_command=`$echo "X$finalize_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + + # We have no uninstalled library dependencies, so finalize right now. + $show "$compile_command" + $run eval "$compile_command" + exit $? + fi + + # Replace the output file specification. + compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$objdir/$output"'%g'` + finalize_command=`$echo "X$finalize_command" | $Xsed -e 's%@OUTPUT@%'"$objdir/$output"'T%g'` + + # Create the binary in the object directory, then wrap it. + if test -d $objdir; then : + else + $show "$mkdir $objdir" + $run $mkdir $objdir + status=$? + if test $status -eq 0 || test -d $objdir; then : + else + exit $status + fi + fi + + if test -n "$shlibpath_var"; then + # We should set the shlibpath_var + rpath= + for dir in $temp_rpath; do + case "$dir" in + /* | [A-Za-z]:\\*) + # Absolute path. + rpath="$rpath$dir:" + ;; + *) + # Relative path: add a thisdir entry. + rpath="$rpath\$thisdir/$dir:" + ;; + esac + done + temp_rpath="$rpath" + fi + + # Delete the old output file. + $run $rm $output + + if test -n "$compile_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + rpath="$rpath$dir:" + done + compile_command="$runpath_var=\"$rpath\$$runpath_var\" $compile_command" + finalize_command="$runpath_var=\"$rpath\$$runpath_var\" $finalize_command" + fi + + case "$hardcode_action" in + relink) + # AGH! Flame the AIX and HP-UX people for me, will ya? + $echo "$modename: warning: using a buggy system linker" 1>&2 + $echo "$modename: relinking will be required before \`$output' can be installed" 1>&2 + ;; + esac + + $show "$compile_command" + $run eval "$compile_command" || exit $? + + # Now create the wrapper script. + $show "creating $output" + + # Quote the finalize command for shipping. + finalize_command=`$echo "X$finalize_command" | $Xsed -e "$sed_quote_subst"` + + # Quote $echo for shipping. + qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"` + + # Only actually do things if our run command is non-null. + if test -z "$run"; then + $rm $output + trap "$rm $output; exit 1" 1 2 15 + + $echo > $output "\ +#! /bin/sh + +# $output - temporary wrapper script for $objdir/$output +# Generated by ltmain.sh - GNU $PACKAGE $VERSION +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of \``pwd`'. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='sed -e s/^X//' +sed_quote_subst='$sed_quote_subst' + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +if test \"\${CDPATH+set}\" = set; then CDPATH=; export CDPATH; fi + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variables: + link_against_libtool_libs='$link_against_libtool_libs' + finalize_command=\"$finalize_command\" +else + # When we are sourced in execute mode, \$file and \$echo are already set. + if test \"\$libtool_execute_magic\" = \"$magic\"; then : + else + echo=\"$qecho\" + file=\"\$0\" + fi\ +" + $echo >> $output "\ + + # Find the directory that this script lives in. + thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | sed -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + /* | [A-Za-z]:\\*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | sed -n 's/.*-> //p'\` + done + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" + + progdir=\"\$thisdir/$objdir\" + program='$output' + + if test -f \"\$progdir/\$program\"; then" + + # Export our shlibpath_var if we have one. + if test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $echo >> $output "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/:*\$//'\` + + export $shlibpath_var +" + fi + + $echo >> $output "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. + + # Export the path to the program. + PATH=\"\$progdir:\$PATH\" + export PATH + + exec \$program \${1+\"\$@\"} + + \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\" + exit 1 + fi + else + # The program doesn't exist. + \$echo \"\$0: error: \$progdir/\$program does not exist\" 1>&2 + \$echo \"This script is just a wrapper for \$program.\" 1>&2 + echo \"See the $PACKAGE documentation for more information.\" 1>&2 + exit 1 + fi +fi\ +" + chmod +x $output + fi + exit 0 + ;; + esac + + # See if we need to build an old-fashioned archive. + if test "$build_old_libs" = "yes"; then + # Transform .lo files to .o files. + oldobjs="$objs"`$echo "X$libobjs " | $Xsed -e 's/[^ ]*\.a //g' -e 's/\.lo /.o /g' -e 's/ $//g'` + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then + eval cmds=\"$old_archive_from_new_cmds\" + else + eval cmds=\"$old_archive_cmds\" + fi + IFS="${IFS= }"; save_ifs="$IFS"; IFS=';' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + + # Now create the libtool archive. + case "$output" in + *.la) + old_library= + test "$build_old_libs" = yes && old_library="$libname.a" + + $show "creating $output" + + # Only create the output if not a dry run. + if test -z "$run"; then + $echo > $output "\ +# $output - a libtool library file +# Generated by ltmain.sh - GNU $PACKAGE $VERSION + +# The name that we can dlopen(3). +dlname='$dlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Directory that this library needs to be installed in: +libdir='$install_libdir'\ +" + fi + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + $show "(cd $objdir && $LN_S ../$output $output)" + $run eval "(cd $objdir && $LN_S ../$output $output)" || exit 1 + ;; + esac + exit 0 + ;; + + # libtool install mode + install) + modename="$modename: install" + + # There may be an optional /bin/sh argument at the beginning of + # install_prog (especially on Windows NT). + if test "$nonopt" = "$SHELL"; then + # Aesthetically quote it. + arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"` + case "$arg" in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + arg="\"$arg\"" + ;; + esac + install_prog="$arg " + arg="$1" + shift + else + install_prog= + arg="$nonopt" + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case "$arg" in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + arg="\"$arg\"" + ;; + esac + install_prog="$install_prog$arg" + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir= + stripme= + for arg + do + if test -n "$dest"; then + files="$files $dest" + dest="$arg" + continue + fi + + case "$arg" in + -d) isdir=yes ;; + -f) prev="-f" ;; + -g) prev="-g" ;; + -m) prev="-m" ;; + -o) prev="-o" ;; + -s) + stripme=" -s" + continue + ;; + -*) ;; + + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + prev= + else + dest="$arg" + continue + fi + ;; + esac + + # Aesthetically quote the argument. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case "$arg" in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + arg="\"$arg\"" + ;; + esac + install_prog="$install_prog $arg" + done + + if test -z "$install_prog"; then + $echo "$modename: you must specify an install program" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + if test -n "$prev"; then + $echo "$modename: the \`$prev' option requires an argument" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + if test -z "$files"; then + if test -z "$dest"; then + $echo "$modename: no file or destination specified" 1>&2 + else + $echo "$modename: you must specify a destination" 1>&2 + fi + $echo "$help" 1>&2 + exit 1 + fi + + # Strip any trailing slash from the destination. + dest=`$echo "X$dest" | $Xsed -e 's%/$%%'` + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=yes + if test -n "$isdir"; then + destdir="$dest" + destname= + else + destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'` + test "X$destdir" = "X$dest" && destdir=. + destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'` + + # Not a directory, so check to see that there is only one file specified. + set dummy $files + if test $# -gt 2; then + $echo "$modename: \`$dest' is not a directory" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + fi + case "$destdir" in + /* | [A-Za-z]:\\*) ;; + *) + for file in $files; do + case "$file" in + *.lo) ;; + *) + $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case "$file" in + *.a) + # Do the static libraries later. + staticlibs="$staticlibs $file" + ;; + + *.la) + # Check to see that this really is a libtool archive. + if (sed -e '2q' $file | egrep '^# Generated by ltmain\.sh') >/dev/null 2>&1; then : + else + $echo "$modename: \`$file' is not a valid libtool archive" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + library_names= + old_library= + # If there is no directory component, then add one. + case "$file" in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) current_libdirs="$current_libdirs $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) future_libdirs="$future_libdirs $libdir" ;; + esac + fi + + dir="`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/" + test "X$dir" = "X$file/" && dir= + dir="$dir$objdir" + + # See the names of the shared library. + set dummy $library_names + if test -n "$2"; then + realname="$2" + shift + shift + + # Install the shared library and build the symlinks. + $show "$install_prog $dir/$realname $destdir/$realname" + $run eval "$install_prog $dir/$realname $destdir/$realname" || exit $? + test "X$dlname" = "X$realname" && dlname= + + if test $# -gt 0; then + # Delete the old symlinks. + rmcmd="$rm" + for linkname + do + rmcmd="$rmcmd $destdir/$linkname" + done + $show "$rmcmd" + $run $rmcmd + + # ... and create new ones. + for linkname + do + test "X$dlname" = "X$linkname" && dlname= + $show "(cd $destdir && $LN_S $realname $linkname)" + $run eval "(cd $destdir && $LN_S $realname $linkname)" + done + fi + + if test -n "$dlname"; then + # Install the dynamically-loadable library. + $show "$install_prog $dir/$dlname $destdir/$dlname" + $run eval "$install_prog $dir/$dlname $destdir/$dlname" || exit $? + fi + + # Do each command in the postinstall commands. + lib="$destdir/$realname" + eval cmds=\"$postinstall_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS=';' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + + # Install the pseudo-library for information purposes. + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + $show "$install_prog $file $destdir/$name" + $run eval "$install_prog $file $destdir/$name" || exit $? + + # Maybe install the static library, too. + test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + destfile="$destdir/$destfile" + fi + + # Deduce the name of the destination old-style object file. + case "$destfile" in + *.lo) + staticdest=`$echo "X$destfile" | $Xsed -e 's/\.lo$/\.o/'` + ;; + *.o) + staticdest="$destfile" + destfile= + ;; + *) + $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + esac + + # Install the libtool object if requested. + if test -n "$destfile"; then + $show "$install_prog $file $destfile" + $run eval "$install_prog $file $destfile" || exit $? + fi + + # Install the old object if enabled. + if test "$build_old_libs" = yes; then + # Deduce the name of the old-style object file. + staticobj=`$echo "X$file" | $Xsed -e 's/\.lo$/\.o/'` + + $show "$install_prog $staticobj $staticdest" + $run eval "$install_prog \$staticobj \$staticdest" || exit $? + fi + exit 0 + ;; + + *) + # Do a test to see if this is really a libtool program. + if (sed -e '4q' $file | egrep '^# Generated by ltmain\.sh') >/dev/null 2>&1; then + link_against_libtool_libs= + finalize_command= + + # If there is no directory component, then add one. + case "$file" in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Check the variables that should have been set. + if test -z "$link_against_libtool_libs" || test -z "$finalize_command"; then + $echo "$modename: invalid libtool wrapper script \`$file'" 1>&2 + exit 1 + fi + + finalize=yes + for lib in $link_against_libtool_libs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + # If there is no directory component, then add one. + case "$lib" in + */* | *\\*) . $lib ;; + *) . ./$lib ;; + esac + fi + libfile="$libdir/`$echo "X$lib" | $Xsed -e 's%^.*/%%g'`" + if test -z "$libdir"; then + $echo "$modename: warning: \`$lib' contains no -rpath information" 1>&2 + elif test -f "$libfile"; then : + else + $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2 + finalize=no + fi + done + + if test "$hardcode_action" = relink; then + if test "$finalize" = yes; then + $echo "$modename: warning: relinking \`$file' on behalf of your buggy system linker" 1>&2 + $show "$finalize_command" + if $run eval "$finalize_command"; then : + else + $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 + continue + fi + file="$objdir/$file"T + else + $echo "$modename: warning: cannot relink \`$file' on behalf of your buggy system linker" 1>&2 + fi + else + # Install the binary that we compiled earlier. + file=`$echo "X$file" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + $show "$install_prog$stripme $file $dest" + $run eval "$install_prog\$stripme \$file \$dest" || exit $? + ;; + esac + done + + for file in $staticlibs; do + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + + # Set up the ranlib parameters. + oldlib="$destdir/$name" + + $show "$install_prog $file $oldlib" + $run eval "$install_prog \$file \$oldlib" || exit $? + + # Do each command in the postinstall commands. + eval cmds=\"$old_postinstall_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS=';' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + done + + if test -n "$future_libdirs"; then + $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2 + fi + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + test -n "$run" && current_libdirs=" -n$current_libdirs" + exec $SHELL $0 --finish$current_libdirs + exit 1 + fi + + exit 0 + ;; + + # libtool finish mode + finish) + modename="$modename: finish" + libdirs="$nonopt" + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for dir + do + libdirs="$libdirs $dir" + done + + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + eval cmds=\"$finish_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS=';' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" + done + IFS="$save_ifs" + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $run eval "$cmds" + fi + done + fi + + echo "------------------------------------------------------------------------------" + echo "Libraries have been installed in:" + for libdir in $libdirs; do + echo " $libdir" + done + echo + echo "To link against installed libraries in a given directory, LIBDIR," + echo "you must use the \`-LLIBDIR' flag during linking." + echo + echo " You will also need to do one of the following:" + if test -n "$shlibpath_var"; then + echo " - add LIBDIR to the \`$shlibpath_var' environment variable" + echo " during execution" + fi + if test -n "$runpath_var"; then + echo " - add LIBDIR to the \`$runpath_var' environment variable" + echo " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + echo " - use the \`$flag' linker flag" + fi + if test -f /etc/ld.so.conf; then + echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" + fi + echo + echo "See any operating system documentation about shared libraries for" + echo "more information, such as the ld(1) and ld.so(8) manual pages." + echo "------------------------------------------------------------------------------" + exit 0 + ;; + + # libtool execute mode + execute) + modename="$modename: execute" + + # The first argument is the command name. + cmd="$nonopt" + if test -z "$cmd"; then + $echo "$modename: you must specify a COMMAND" 1>&2 + $echo "$help" + exit 1 + fi + + # Handle -dlopen flags immediately. + for file in $execute_dlfiles; do + if test -f "$file"; then : + else + $echo "$modename: \`$file' is not a file" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + dir= + case "$file" in + *.la) + # Check to see that this really is a libtool archive. + if (sed -e '2q' $file | egrep '^# Generated by ltmain\.sh') >/dev/null 2>&1; then : + else + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + # Read the libtool library. + dlname= + library_names= + + # If there is no directory component, then add one. + case "$file" in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'" + continue + fi + + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$file" && dir=. + + if test -f "$dir/$objdir/$dlname"; then + dir="$dir/$objdir" + else + $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2 + exit 1 + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$file" && dir=. + ;; + + *) + $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2 + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir="$absdir" + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic="$magic" + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case "$file" in + -*) ;; + *) + # Do a test to see if this is really a libtool program. + if (sed -e '4q' $file | egrep '^# Generated by ltmain\.sh') >/dev/null 2>&1; then + # If there is no directory component, then add one. + case "$file" in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Transform arg to wrapped name. + file="$progdir/$program" + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"` + args="$args \"$file\"" + done + + if test -z "$run"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + + # Now actually exec the command. + eval "exec \$cmd$args" + + $echo "$modename: cannot exec \$cmd$args" + exit 1 + else + # Display what would be done. + eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\"" + $echo "export $shlibpath_var" + $echo "$cmd$args" + exit 0 + fi + ;; + + # libtool uninstall mode + uninstall) + modename="$modename: uninstall" + rm="$nonopt" + files= + + for arg + do + case "$arg" in + -*) rm="$rm $arg" ;; + *) files="$files $arg" ;; + esac + done + + if test -z "$rm"; then + $echo "$modename: you must specify an RM program" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + for file in $files; do + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$file" && dir=. + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + + rmfiles="$file" + + case "$name" in + *.la) + # Possibly a libtool archive, so verify it. + if (sed -e '2q' $file | egrep '^# Generated by ltmain\.sh') >/dev/null 2>&1; then + . $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + rmfiles="$rmfiles $dir/$n" + test "X$n" = "X$dlname" && dlname= + done + test -n "$dlname" && rmfiles="$rmfiles $dir/$dlname" + test -n "$old_library" && rmfiles="$rmfiles $dir/$old_library" + + $show "$rm $rmfiles" + $run $rm $rmfiles + + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + eval cmds=\"$postuninstall_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS=';' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" + done + IFS="$save_ifs" + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + eval cmds=\"$old_postuninstall_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS=';' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" + done + IFS="$save_ifs" + fi + + # FIXME: should reinstall the best remaining shared library. + fi + ;; + + *.lo) + if test "$build_old_libs" = yes; then + oldobj=`$echo "X$name" | $Xsed -e 's/\.lo$/\.o/'` + rmfiles="$rmfiles $dir/$oldobj" + fi + $show "$rm $rmfiles" + $run $rm $rmfiles + ;; + + *) + $show "$rm $rmfiles" + $run $rm $rmfiles + ;; + esac + done + exit 0 + ;; + + "") + $echo "$modename: you must specify a MODE" 1>&2 + $echo "$generic_help" 1>&2 + exit 1 + ;; + esac + + $echo "$modename: invalid operation mode \`$mode'" 1>&2 + $echo "$generic_help" 1>&2 + exit 1 +fi # test -z "$show_help" + +# We need to display help for each of the modes. +case "$mode" in +"") $echo \ +"Usage: $modename [OPTION]... [MODE-ARG]... + +Provide generalized library-building support services. + +-n, --dry-run display commands without modifying any files + --features display configuration information and exit + --finish same as \`--mode=finish' + --help display this help message and exit + --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS] + --quiet same as \`--silent' + --silent don't print informational messages + --version print version information + +MODE must be one of the following: + + compile compile a source file into a libtool object + execute automatically set library path, then run a program + finish complete the installation of libtool libraries + install install libraries or executables + link create a library or an executable + uninstall remove libraries from an installed directory + +MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for +a more detailed description of MODE." + exit 0 + ;; + +compile) + $echo \ +"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +COMPILE-COMMAND is a command to be used in creating a \`standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix \`.c' with the +library object suffix, \`.lo'." + ;; + +execute) + $echo \ +"Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to \`-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + +finish) + $echo \ +"Usage: $modename [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the \`--dry-run' option if you just want to see what would be executed." + ;; + +install) + $echo \ +"Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the \`install' or \`cp' program. + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + +link) + $echo \ +"Usage: $modename [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to dld_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -static do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + +All other options (arguments beginning with \`-') are ignored. + +Every other argument is treated as a filename. Files ending in \`.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in \`.la', then a libtool library is created, only +library objects (\`.lo' files) may be specified, and \`-rpath' is required. + +If OUTPUT-FILE ends in \`.a', then a standard library is created using \`ar' +and \`ranlib'. + +If OUTPUT-FILE ends in \`.lo' or \`.o', then a reloadable object file is +created, otherwise an executable program is created." + ;; + +uninstall) + $echo +"Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + +*) + $echo "$modename: invalid operation mode \`$mode'" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; +esac + +echo +$echo "Try \`$modename --help' for more information about other modes." + +exit 0 + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: diff --git a/lc-continuity/mk4/modimage/jpeg-6b/makcjpeg.st b/lc-continuity/mk4/modimage/jpeg-6b/makcjpeg.st new file mode 100644 index 0000000000000000000000000000000000000000..fc72c898230a678fc3cb53560b196148112575fb --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/makcjpeg.st @@ -0,0 +1,38 @@ +; Project file for Independent JPEG Group's software +; +; This project file is for Atari ST/STE/TT systems using Pure C or Turbo C. +; Thanks to Frank Moehle (Frank.Moehle@arbi.informatik.uni-oldenburg.de), +; Dr. B. Setzepfandt (bernd@gina.uni-muenster.de), +; and Guido Vollbeding (guivol@esc.de). +; +; To use this file, rename it to cjpeg.prj. +; If you are using Turbo C, change filenames beginning with "pc..." to "tc..." +; Read installation instructions before trying to make the program! +; +; +; * * * Output file * * * +cjpeg.ttp +; +; * * * COMPILER OPTIONS * * * +.C[-P] ; absolute calls +.C[-M] ; and no string merging, folks +.C[-w-cln] ; no "constant is long" warnings +.C[-w-par] ; no "parameter xxxx unused" +.C[-w-rch] ; no "unreachable code" +.C[-wsig] ; warn if significant digits may be lost += +; * * * * List of modules * * * * +pcstart.o +cjpeg.c (cdjpeg.h,jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h,cderror.h,jversion.h) +cdjpeg.c (cdjpeg.h,jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h,cderror.h) +rdswitch.c (cdjpeg.h,jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h,cderror.h) +rdppm.c (cdjpeg.h,jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h,cderror.h) +rdgif.c (cdjpeg.h,jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h,cderror.h) +rdtarga.c (cdjpeg.h,jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h,cderror.h) +rdbmp.c (cdjpeg.h,jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h,cderror.h) +rdrle.c (cdjpeg.h,jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h,cderror.h) +libjpeg.lib ; built by libjpeg.prj +pcfltlib.lib ; floating point library +; the float library can be omitted if you've turned off DCT_FLOAT_SUPPORTED +pcstdlib.lib ; standard library +pcextlib.lib ; extended library diff --git a/lc-continuity/mk4/modimage/jpeg-6b/makdjpeg.st b/lc-continuity/mk4/modimage/jpeg-6b/makdjpeg.st new file mode 100644 index 0000000000000000000000000000000000000000..32267263110f08b16787f75aad7d167835cd718a --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/makdjpeg.st @@ -0,0 +1,38 @@ +; Project file for Independent JPEG Group's software +; +; This project file is for Atari ST/STE/TT systems using Pure C or Turbo C. +; Thanks to Frank Moehle (Frank.Moehle@arbi.informatik.uni-oldenburg.de), +; Dr. B. Setzepfandt (bernd@gina.uni-muenster.de), +; and Guido Vollbeding (guivol@esc.de). +; +; To use this file, rename it to djpeg.prj. +; If you are using Turbo C, change filenames beginning with "pc..." to "tc..." +; Read installation instructions before trying to make the program! +; +; +; * * * Output file * * * +djpeg.ttp +; +; * * * COMPILER OPTIONS * * * +.C[-P] ; absolute calls +.C[-M] ; and no string merging, folks +.C[-w-cln] ; no "constant is long" warnings +.C[-w-par] ; no "parameter xxxx unused" +.C[-w-rch] ; no "unreachable code" +.C[-wsig] ; warn if significant digits may be lost += +; * * * * List of modules * * * * +pcstart.o +djpeg.c (cdjpeg.h,jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h,cderror.h,jversion.h) +cdjpeg.c (cdjpeg.h,jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h,cderror.h) +rdcolmap.c (cdjpeg.h,jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h,cderror.h) +wrppm.c (cdjpeg.h,jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h,cderror.h) +wrgif.c (cdjpeg.h,jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h,cderror.h) +wrtarga.c (cdjpeg.h,jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h,cderror.h) +wrbmp.c (cdjpeg.h,jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h,cderror.h) +wrrle.c (cdjpeg.h,jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h,cderror.h) +libjpeg.lib ; built by libjpeg.prj +pcfltlib.lib ; floating point library +; the float library can be omitted if you've turned off DCT_FLOAT_SUPPORTED +pcstdlib.lib ; standard library +pcextlib.lib ; extended library diff --git a/lc-continuity/mk4/modimage/jpeg-6b/makeapps.ds b/lc-continuity/mk4/modimage/jpeg-6b/makeapps.ds new file mode 100644 index 0000000000000000000000000000000000000000..bedd038a3953e1d401c267e3942897a29c69b60a --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/makeapps.ds @@ -0,0 +1,828 @@ +# Microsoft Developer Studio Generated NMAKE File, Format Version 4.20 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +!IF "$(CFG)" == "" +CFG=cjpeg - Win32 +!MESSAGE No configuration specified. Defaulting to cjpeg - Win32. +!ENDIF + +!IF "$(CFG)" != "cjpeg - Win32" && "$(CFG)" != "djpeg - Win32" &&\ + "$(CFG)" != "jpegtran - Win32" && "$(CFG)" != "rdjpgcom - Win32" &&\ + "$(CFG)" != "wrjpgcom - Win32" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE on this makefile +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "apps.mak" CFG="cjpeg - Win32" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "cjpeg - Win32" (based on "Win32 (x86) Console Application") +!MESSAGE "djpeg - Win32" (based on "Win32 (x86) Console Application") +!MESSAGE "jpegtran - Win32" (based on "Win32 (x86) Console Application") +!MESSAGE "rdjpgcom - Win32" (based on "Win32 (x86) Console Application") +!MESSAGE "wrjpgcom - Win32" (based on "Win32 (x86) Console Application") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF +################################################################################ +# Begin Project +# PROP Target_Last_Scanned "cjpeg - Win32" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "cjpeg - Win32" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "cjpeg\Release" +# PROP BASE Intermediate_Dir "cjpeg\Release" +# PROP BASE Target_Dir "cjpeg" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "cjpeg\Release" +# PROP Intermediate_Dir "cjpeg\Release" +# PROP Target_Dir "cjpeg" +OUTDIR=.\cjpeg\Release +INTDIR=.\cjpeg\Release + +ALL : "$(OUTDIR)\cjpeg.exe" + +CLEAN : + -@erase "$(INTDIR)\cjpeg.obj" + -@erase "$(INTDIR)\rdppm.obj" + -@erase "$(INTDIR)\rdgif.obj" + -@erase "$(INTDIR)\rdtarga.obj" + -@erase "$(INTDIR)\rdrle.obj" + -@erase "$(INTDIR)\rdbmp.obj" + -@erase "$(INTDIR)\rdswitch.obj" + -@erase "$(INTDIR)\cdjpeg.obj" + -@erase "$(OUTDIR)\cjpeg.exe" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c +# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c +CPP_PROJ=/nologo /ML /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"\ + /Fp"$(INTDIR)/cjpeg.pch" /YX /Fo"$(INTDIR)/" /c +CPP_OBJS=.\cjpeg\Release/ +CPP_SBRS=.\. +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/cjpeg.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 Release\jpeg.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +LINK32_FLAGS=Release\jpeg.lib kernel32.lib user32.lib gdi32.lib winspool.lib\ + comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib\ + odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no\ + /pdb:"$(OUTDIR)/cjpeg.pdb" /machine:I386 /out:"$(OUTDIR)/cjpeg.exe" +LINK32_OBJS= \ + "$(INTDIR)\cjpeg.obj" \ + "$(INTDIR)\rdppm.obj" \ + "$(INTDIR)\rdgif.obj" \ + "$(INTDIR)\rdtarga.obj" \ + "$(INTDIR)\rdrle.obj" \ + "$(INTDIR)\rdbmp.obj" \ + "$(INTDIR)\rdswitch.obj" \ + "$(INTDIR)\cdjpeg.obj" \ + + +"$(OUTDIR)\cjpeg.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "djpeg - Win32" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "djpeg\Release" +# PROP BASE Intermediate_Dir "djpeg\Release" +# PROP BASE Target_Dir "djpeg" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "djpeg\Release" +# PROP Intermediate_Dir "djpeg\Release" +# PROP Target_Dir "djpeg" +OUTDIR=.\djpeg\Release +INTDIR=.\djpeg\Release + +ALL : "$(OUTDIR)\djpeg.exe" + +CLEAN : + -@erase "$(INTDIR)\djpeg.obj" + -@erase "$(INTDIR)\wrppm.obj" + -@erase "$(INTDIR)\wrgif.obj" + -@erase "$(INTDIR)\wrtarga.obj" + -@erase "$(INTDIR)\wrrle.obj" + -@erase "$(INTDIR)\wrbmp.obj" + -@erase "$(INTDIR)\rdcolmap.obj" + -@erase "$(INTDIR)\cdjpeg.obj" + -@erase "$(OUTDIR)\djpeg.exe" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c +# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c +CPP_PROJ=/nologo /ML /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"\ + /Fp"$(INTDIR)/djpeg.pch" /YX /Fo"$(INTDIR)/" /c +CPP_OBJS=.\djpeg\Release/ +CPP_SBRS=.\. +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/djpeg.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 Release\jpeg.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +LINK32_FLAGS=Release\jpeg.lib kernel32.lib user32.lib gdi32.lib winspool.lib\ + comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib\ + odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no\ + /pdb:"$(OUTDIR)/djpeg.pdb" /machine:I386 /out:"$(OUTDIR)/djpeg.exe" +LINK32_OBJS= \ + "$(INTDIR)\djpeg.obj" \ + "$(INTDIR)\wrppm.obj" \ + "$(INTDIR)\wrgif.obj" \ + "$(INTDIR)\wrtarga.obj" \ + "$(INTDIR)\wrrle.obj" \ + "$(INTDIR)\wrbmp.obj" \ + "$(INTDIR)\rdcolmap.obj" \ + "$(INTDIR)\cdjpeg.obj" \ + + +"$(OUTDIR)\djpeg.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "jpegtran - Win32" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "jpegtran\Release" +# PROP BASE Intermediate_Dir "jpegtran\Release" +# PROP BASE Target_Dir "jpegtran" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "jpegtran\Release" +# PROP Intermediate_Dir "jpegtran\Release" +# PROP Target_Dir "jpegtran" +OUTDIR=.\jpegtran\Release +INTDIR=.\jpegtran\Release + +ALL : "$(OUTDIR)\jpegtran.exe" + +CLEAN : + -@erase "$(INTDIR)\jpegtran.obj" + -@erase "$(INTDIR)\rdswitch.obj" + -@erase "$(INTDIR)\cdjpeg.obj" + -@erase "$(INTDIR)\transupp.obj" + -@erase "$(OUTDIR)\jpegtran.exe" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c +# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c +CPP_PROJ=/nologo /ML /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"\ + /Fp"$(INTDIR)/jpegtran.pch" /YX /Fo"$(INTDIR)/" /c +CPP_OBJS=.\jpegtran\Release/ +CPP_SBRS=.\. +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/jpegtran.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 Release\jpeg.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +LINK32_FLAGS=Release\jpeg.lib kernel32.lib user32.lib gdi32.lib winspool.lib\ + comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib\ + odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no\ + /pdb:"$(OUTDIR)/jpegtran.pdb" /machine:I386 /out:"$(OUTDIR)/jpegtran.exe" +LINK32_OBJS= \ + "$(INTDIR)\jpegtran.obj" \ + "$(INTDIR)\rdswitch.obj" \ + "$(INTDIR)\cdjpeg.obj" \ + "$(INTDIR)\transupp.obj" \ + + +"$(OUTDIR)\jpegtran.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "rdjpgcom - Win32" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "rdjpgcom\Release" +# PROP BASE Intermediate_Dir "rdjpgcom\Release" +# PROP BASE Target_Dir "rdjpgcom" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "rdjpgcom\Release" +# PROP Intermediate_Dir "rdjpgcom\Release" +# PROP Target_Dir "rdjpgcom" +OUTDIR=.\rdjpgcom\Release +INTDIR=.\rdjpgcom\Release + +ALL : "$(OUTDIR)\rdjpgcom.exe" + +CLEAN : + -@erase "$(INTDIR)\rdjpgcom.obj" + -@erase "$(OUTDIR)\rdjpgcom.exe" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c +# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c +CPP_PROJ=/nologo /ML /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"\ + /Fp"$(INTDIR)/rdjpgcom.pch" /YX /Fo"$(INTDIR)/" /c +CPP_OBJS=.\rdjpgcom\Release/ +CPP_SBRS=.\. +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/rdjpgcom.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 Release\jpeg.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +LINK32_FLAGS=Release\jpeg.lib kernel32.lib user32.lib gdi32.lib winspool.lib\ + comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib\ + odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no\ + /pdb:"$(OUTDIR)/rdjpgcom.pdb" /machine:I386 /out:"$(OUTDIR)/rdjpgcom.exe" +LINK32_OBJS= \ + "$(INTDIR)\rdjpgcom.obj" + +"$(OUTDIR)\rdjpgcom.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "wrjpgcom - Win32" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "wrjpgcom\Release" +# PROP BASE Intermediate_Dir "wrjpgcom\Release" +# PROP BASE Target_Dir "wrjpgcom" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "wrjpgcom\Release" +# PROP Intermediate_Dir "wrjpgcom\Release" +# PROP Target_Dir "wrjpgcom" +OUTDIR=.\wrjpgcom\Release +INTDIR=.\wrjpgcom\Release + +ALL : "$(OUTDIR)\wrjpgcom.exe" + +CLEAN : + -@erase "$(INTDIR)\wrjpgcom.obj" + -@erase "$(OUTDIR)\wrjpgcom.exe" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c +# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c +CPP_PROJ=/nologo /ML /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"\ + /Fp"$(INTDIR)/wrjpgcom.pch" /YX /Fo"$(INTDIR)/" /c +CPP_OBJS=.\wrjpgcom\Release/ +CPP_SBRS=.\. +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/wrjpgcom.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 Release\jpeg.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +LINK32_FLAGS=Release\jpeg.lib kernel32.lib user32.lib gdi32.lib winspool.lib\ + comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib\ + odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no\ + /pdb:"$(OUTDIR)/wrjpgcom.pdb" /machine:I386 /out:"$(OUTDIR)/wrjpgcom.exe" +LINK32_OBJS= \ + "$(INTDIR)\wrjpgcom.obj" + +"$(OUTDIR)\wrjpgcom.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ENDIF + +.c{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.c{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +################################################################################ +# Begin Target + +# Name "cjpeg - Win32" + +!IF "$(CFG)" == "cjpeg - Win32" + +!ENDIF + +################################################################################ +# Begin Source File + +SOURCE="cjpeg.c" +DEP_CPP_CJPEG=\ + "cdjpeg.h"\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jerror.h"\ + "cderror.h"\ + "jversion.h"\ + + +"$(INTDIR)\cjpeg.obj" : $(SOURCE) $(DEP_CPP_CJPEG) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="cdjpeg.c" +DEP_CPP_CDJPE=\ + "cdjpeg.h"\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jerror.h"\ + "cderror.h"\ + + +"$(INTDIR)\cdjpeg.obj" : $(SOURCE) $(DEP_CPP_CDJPE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="rdswitch.c" +DEP_CPP_RDSWI=\ + "cdjpeg.h"\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jerror.h"\ + "cderror.h"\ + + +"$(INTDIR)\rdswitch.obj" : $(SOURCE) $(DEP_CPP_RDSWI) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="rdppm.c" +DEP_CPP_RDPPM=\ + "cdjpeg.h"\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jerror.h"\ + "cderror.h"\ + + +"$(INTDIR)\rdppm.obj" : $(SOURCE) $(DEP_CPP_RDPPM) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="rdgif.c" +DEP_CPP_RDGIF=\ + "cdjpeg.h"\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jerror.h"\ + "cderror.h"\ + + +"$(INTDIR)\rdgif.obj" : $(SOURCE) $(DEP_CPP_RDGIF) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="rdtarga.c" +DEP_CPP_RDTAR=\ + "cdjpeg.h"\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jerror.h"\ + "cderror.h"\ + + +"$(INTDIR)\rdtarga.obj" : $(SOURCE) $(DEP_CPP_RDTAR) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="rdbmp.c" +DEP_CPP_RDBMP=\ + "cdjpeg.h"\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jerror.h"\ + "cderror.h"\ + + +"$(INTDIR)\rdbmp.obj" : $(SOURCE) $(DEP_CPP_RDBMP) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="rdrle.c" +DEP_CPP_RDRLE=\ + "cdjpeg.h"\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jerror.h"\ + "cderror.h"\ + + +"$(INTDIR)\rdrle.obj" : $(SOURCE) $(DEP_CPP_RDRLE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +# End Target +################################################################################ +# Begin Target + +# Name "djpeg - Win32" + +!IF "$(CFG)" == "djpeg - Win32" + +!ENDIF + +################################################################################ +# Begin Source File + +SOURCE="djpeg.c" +DEP_CPP_DJPEG=\ + "cdjpeg.h"\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jerror.h"\ + "cderror.h"\ + "jversion.h"\ + + +"$(INTDIR)\djpeg.obj" : $(SOURCE) $(DEP_CPP_DJPEG) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="cdjpeg.c" +DEP_CPP_CDJPE=\ + "cdjpeg.h"\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jerror.h"\ + "cderror.h"\ + + +"$(INTDIR)\cdjpeg.obj" : $(SOURCE) $(DEP_CPP_CDJPE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="rdcolmap.c" +DEP_CPP_RDCOL=\ + "cdjpeg.h"\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jerror.h"\ + "cderror.h"\ + + +"$(INTDIR)\rdcolmap.obj" : $(SOURCE) $(DEP_CPP_RDCOL) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="wrppm.c" +DEP_CPP_WRPPM=\ + "cdjpeg.h"\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jerror.h"\ + "cderror.h"\ + + +"$(INTDIR)\wrppm.obj" : $(SOURCE) $(DEP_CPP_WRPPM) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="wrgif.c" +DEP_CPP_WRGIF=\ + "cdjpeg.h"\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jerror.h"\ + "cderror.h"\ + + +"$(INTDIR)\wrgif.obj" : $(SOURCE) $(DEP_CPP_WRGIF) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="wrtarga.c" +DEP_CPP_WRTAR=\ + "cdjpeg.h"\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jerror.h"\ + "cderror.h"\ + + +"$(INTDIR)\wrtarga.obj" : $(SOURCE) $(DEP_CPP_WRTAR) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="wrbmp.c" +DEP_CPP_WRBMP=\ + "cdjpeg.h"\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jerror.h"\ + "cderror.h"\ + + +"$(INTDIR)\wrbmp.obj" : $(SOURCE) $(DEP_CPP_WRBMP) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="wrrle.c" +DEP_CPP_WRRLE=\ + "cdjpeg.h"\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jerror.h"\ + "cderror.h"\ + + +"$(INTDIR)\wrrle.obj" : $(SOURCE) $(DEP_CPP_WRRLE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +# End Target +################################################################################ +# Begin Target + +# Name "jpegtran - Win32" + +!IF "$(CFG)" == "jpegtran - Win32" + +!ENDIF + +################################################################################ +# Begin Source File + +SOURCE="jpegtran.c" +DEP_CPP_JPEGT=\ + "cdjpeg.h"\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jerror.h"\ + "cderror.h"\ + "transupp.h"\ + "jversion.h"\ + + +"$(INTDIR)\jpegtran.obj" : $(SOURCE) $(DEP_CPP_JPEGT) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="cdjpeg.c" +DEP_CPP_CDJPE=\ + "cdjpeg.h"\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jerror.h"\ + "cderror.h"\ + + +"$(INTDIR)\cdjpeg.obj" : $(SOURCE) $(DEP_CPP_CDJPE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="rdswitch.c" +DEP_CPP_RDSWI=\ + "cdjpeg.h"\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jerror.h"\ + "cderror.h"\ + + +"$(INTDIR)\rdswitch.obj" : $(SOURCE) $(DEP_CPP_RDSWI) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="transupp.c" +DEP_CPP_TRANS=\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jpegint.h"\ + "jerror.h"\ + "transupp.h"\ + + +"$(INTDIR)\transupp.obj" : $(SOURCE) $(DEP_CPP_TRANS) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +# End Target +################################################################################ +# Begin Target + +# Name "rdjpgcom - Win32" + +!IF "$(CFG)" == "rdjpgcom - Win32" + +!ENDIF + +################################################################################ +# Begin Source File + +SOURCE="rdjpgcom.c" +DEP_CPP_RDJPG=\ + "jinclude.h"\ + "jconfig.h"\ + + +"$(INTDIR)\rdjpgcom.obj" : $(SOURCE) $(DEP_CPP_RDJPG) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +# End Target +################################################################################ +# Begin Target + +# Name "wrjpgcom - Win32" + +!IF "$(CFG)" == "wrjpgcom - Win32" + +!ENDIF + +################################################################################ +# Begin Source File + +SOURCE="wrjpgcom.c" +DEP_CPP_WRJPG=\ + "jinclude.h"\ + "jconfig.h"\ + + +"$(INTDIR)\wrjpgcom.obj" : $(SOURCE) $(DEP_CPP_WRJPG) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +# End Target +# End Project +################################################################################ + diff --git a/lc-continuity/mk4/modimage/jpeg-6b/makefile.ansi b/lc-continuity/mk4/modimage/jpeg-6b/makefile.ansi new file mode 100644 index 0000000000000000000000000000000000000000..be835d8300d4584fcac5d1e5ce2c81ef5d179357 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/makefile.ansi @@ -0,0 +1,214 @@ +# Makefile for Independent JPEG Group's software + +# This makefile is suitable for Unix-like systems with ANSI-capable compilers. +# If you have a non-ANSI compiler, makefile.unix is a better starting point. + +# Read installation instructions before saying "make" !! + +# The name of your C compiler: +CC= cc + +# You may need to adjust these cc options: +CFLAGS= -O -xarch=v9a +# Generally, we recommend defining any configuration symbols in jconfig.h, +# NOT via -D switches here. + +# Link-time cc options: +LDFLAGS= + +# To link any special libraries, add the necessary -l commands here. +LDLIBS= + +# Put here the object file name for the correct system-dependent memory +# manager file. For Unix this is usually jmemnobs.o, but you may want +# to use jmemansi.o or jmemname.o if you have limited swap space. +SYSDEPMEM= jmemnobs.o + +# miscellaneous OS-dependent stuff +# linker +LN= $(CC) +# file deletion command +RM= rm -f +# library (.a) file creation command +AR= ar rc +# second step in .a creation (use "touch" if not needed) +AR2= ranlib + +# End of configurable options. + + +# source files: JPEG library proper +LIBSOURCES= jcapimin.c jcapistd.c jccoefct.c jccolor.c jcdctmgr.c jchuff.c \ + jcinit.c jcmainct.c jcmarker.c jcmaster.c jcomapi.c jcparam.c \ + jcphuff.c jcprepct.c jcsample.c jctrans.c jdapimin.c jdapistd.c \ + jdatadst.c jdatasrc.c jdcoefct.c jdcolor.c jddctmgr.c jdhuff.c \ + jdinput.c jdmainct.c jdmarker.c jdmaster.c jdmerge.c jdphuff.c \ + jdpostct.c jdsample.c jdtrans.c jerror.c jfdctflt.c jfdctfst.c \ + jfdctint.c jidctflt.c jidctfst.c jidctint.c jidctred.c jquant1.c \ + jquant2.c jutils.c jmemmgr.c +# memmgr back ends: compile only one of these into a working library +SYSDEPSOURCES= jmemansi.c jmemname.c jmemnobs.c jmemdos.c jmemmac.c +# source files: cjpeg/djpeg/jpegtran applications, also rdjpgcom/wrjpgcom +APPSOURCES= cjpeg.c djpeg.c jpegtran.c rdjpgcom.c wrjpgcom.c cdjpeg.c \ + rdcolmap.c rdswitch.c transupp.c rdppm.c wrppm.c rdgif.c wrgif.c \ + rdtarga.c wrtarga.c rdbmp.c wrbmp.c rdrle.c wrrle.c +SOURCES= $(LIBSOURCES) $(SYSDEPSOURCES) $(APPSOURCES) +# files included by source files +INCLUDES= jchuff.h jdhuff.h jdct.h jerror.h jinclude.h jmemsys.h jmorecfg.h \ + jpegint.h jpeglib.h jversion.h cdjpeg.h cderror.h transupp.h +# documentation, test, and support files +DOCS= README install.doc usage.doc cjpeg.1 djpeg.1 jpegtran.1 rdjpgcom.1 \ + wrjpgcom.1 wizard.doc example.c libjpeg.doc structure.doc \ + coderules.doc filelist.doc change.log +MKFILES= configure makefile.cfg makefile.ansi makefile.unix makefile.bcc \ + makefile.mc6 makefile.dj makefile.wat makefile.vc makelib.ds \ + makeapps.ds makeproj.mac makcjpeg.st makdjpeg.st makljpeg.st \ + maktjpeg.st makefile.manx makefile.sas makefile.mms makefile.vms \ + makvms.opt +CONFIGFILES= jconfig.cfg jconfig.bcc jconfig.mc6 jconfig.dj jconfig.wat \ + jconfig.vc jconfig.mac jconfig.st jconfig.manx jconfig.sas \ + jconfig.vms +CONFIGUREFILES= config.guess config.sub install-sh ltconfig ltmain.sh +OTHERFILES= jconfig.doc ckconfig.c ansi2knr.c ansi2knr.1 jmemdosa.asm +TESTFILES= testorig.jpg testimg.ppm testimg.bmp testimg.jpg testprog.jpg \ + testimgp.jpg +DISTFILES= $(DOCS) $(MKFILES) $(CONFIGFILES) $(SOURCES) $(INCLUDES) \ + $(CONFIGUREFILES) $(OTHERFILES) $(TESTFILES) +# library object files common to compression and decompression +COMOBJECTS= jcomapi.o jutils.o jerror.o jmemmgr.o $(SYSDEPMEM) +# compression library object files +CLIBOBJECTS= jcapimin.o jcapistd.o jctrans.o jcparam.o jdatadst.o jcinit.o \ + jcmaster.o jcmarker.o jcmainct.o jcprepct.o jccoefct.o jccolor.o \ + jcsample.o jchuff.o jcphuff.o jcdctmgr.o jfdctfst.o jfdctflt.o \ + jfdctint.o +# decompression library object files +DLIBOBJECTS= jdapimin.o jdapistd.o jdtrans.o jdatasrc.o jdmaster.o \ + jdinput.o jdmarker.o jdhuff.o jdphuff.o jdmainct.o jdcoefct.o \ + jdpostct.o jddctmgr.o jidctfst.o jidctflt.o jidctint.o jidctred.o \ + jdsample.o jdcolor.o jquant1.o jquant2.o jdmerge.o +# These objectfiles are included in libjpeg.a +LIBOBJECTS= $(CLIBOBJECTS) $(DLIBOBJECTS) $(COMOBJECTS) +# object files for sample applications (excluding library files) +COBJECTS= cjpeg.o rdppm.o rdgif.o rdtarga.o rdrle.o rdbmp.o rdswitch.o \ + cdjpeg.o +DOBJECTS= djpeg.o wrppm.o wrgif.o wrtarga.o wrrle.o wrbmp.o rdcolmap.o \ + cdjpeg.o +TROBJECTS= jpegtran.o rdswitch.o cdjpeg.o transupp.o + + +all: libjpeg.a cjpeg djpeg jpegtran rdjpgcom wrjpgcom + +libjpeg.a: $(LIBOBJECTS) + $(RM) libjpeg.a + $(AR) libjpeg.a $(LIBOBJECTS) + $(AR2) libjpeg.a + +cjpeg: $(COBJECTS) libjpeg.a + $(LN) $(LDFLAGS) -o cjpeg $(COBJECTS) libjpeg.a $(LDLIBS) + +djpeg: $(DOBJECTS) libjpeg.a + $(LN) $(LDFLAGS) -o djpeg $(DOBJECTS) libjpeg.a $(LDLIBS) + +jpegtran: $(TROBJECTS) libjpeg.a + $(LN) $(LDFLAGS) -o jpegtran $(TROBJECTS) libjpeg.a $(LDLIBS) + +rdjpgcom: rdjpgcom.o + $(LN) $(LDFLAGS) -o rdjpgcom rdjpgcom.o $(LDLIBS) + +wrjpgcom: wrjpgcom.o + $(LN) $(LDFLAGS) -o wrjpgcom wrjpgcom.o $(LDLIBS) + +jconfig.h: jconfig.doc + echo You must prepare a system-dependent jconfig.h file. + echo Please read the installation directions in install.doc. + exit 1 + +clean: + $(RM) *.o cjpeg djpeg jpegtran libjpeg.a rdjpgcom wrjpgcom + $(RM) core testout* + +test: cjpeg djpeg jpegtran + $(RM) testout* + ./djpeg -dct int -ppm -outfile testout.ppm testorig.jpg + ./djpeg -dct int -bmp -colors 256 -outfile testout.bmp testorig.jpg + ./cjpeg -dct int -outfile testout.jpg testimg.ppm + ./djpeg -dct int -ppm -outfile testoutp.ppm testprog.jpg + ./cjpeg -dct int -progressive -opt -outfile testoutp.jpg testimg.ppm + ./jpegtran -outfile testoutt.jpg testprog.jpg + cmp testimg.ppm testout.ppm + cmp testimg.bmp testout.bmp + cmp testimg.jpg testout.jpg + cmp testimg.ppm testoutp.ppm + cmp testimgp.jpg testoutp.jpg + cmp testorig.jpg testoutt.jpg + + +jcapimin.o: jcapimin.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcapistd.o: jcapistd.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jccoefct.o: jccoefct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jccolor.o: jccolor.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcdctmgr.o: jcdctmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jchuff.o: jchuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jchuff.h +jcinit.o: jcinit.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcmainct.o: jcmainct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcmarker.o: jcmarker.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcmaster.o: jcmaster.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcomapi.o: jcomapi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcparam.o: jcparam.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcphuff.o: jcphuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jchuff.h +jcprepct.o: jcprepct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcsample.o: jcsample.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jctrans.o: jctrans.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdapimin.o: jdapimin.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdapistd.o: jdapistd.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdatadst.o: jdatadst.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h +jdatasrc.o: jdatasrc.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h +jdcoefct.o: jdcoefct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdcolor.o: jdcolor.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jddctmgr.o: jddctmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jdhuff.o: jdhuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdhuff.h +jdinput.o: jdinput.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdmainct.o: jdmainct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdmarker.o: jdmarker.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdmaster.o: jdmaster.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdmerge.o: jdmerge.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdphuff.o: jdphuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdhuff.h +jdpostct.o: jdpostct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdsample.o: jdsample.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdtrans.o: jdtrans.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jerror.o: jerror.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jversion.h jerror.h +jfdctflt.o: jfdctflt.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jfdctfst.o: jfdctfst.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jfdctint.o: jfdctint.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jidctflt.o: jidctflt.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jidctfst.o: jidctfst.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jidctint.o: jidctint.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jidctred.o: jidctred.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jquant1.o: jquant1.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jquant2.o: jquant2.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jutils.o: jutils.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jmemmgr.o: jmemmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +jmemansi.o: jmemansi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +jmemname.o: jmemname.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +jmemnobs.o: jmemnobs.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +jmemdos.o: jmemdos.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +jmemmac.o: jmemmac.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +cjpeg.o: cjpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h jversion.h +djpeg.o: djpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h jversion.h +jpegtran.o: jpegtran.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h transupp.h jversion.h +rdjpgcom.o: rdjpgcom.c jinclude.h jconfig.h +wrjpgcom.o: wrjpgcom.c jinclude.h jconfig.h +cdjpeg.o: cdjpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdcolmap.o: rdcolmap.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdswitch.o: rdswitch.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +transupp.o: transupp.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h transupp.h +rdppm.o: rdppm.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +wrppm.o: wrppm.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdgif.o: rdgif.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +wrgif.o: wrgif.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdtarga.o: rdtarga.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +wrtarga.o: wrtarga.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdbmp.o: rdbmp.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +wrbmp.o: wrbmp.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdrle.o: rdrle.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +wrrle.o: wrrle.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h diff --git a/lc-continuity/mk4/modimage/jpeg-6b/makefile.bcc b/lc-continuity/mk4/modimage/jpeg-6b/makefile.bcc new file mode 100644 index 0000000000000000000000000000000000000000..a1cfcde669741ef8efc0eb88a9686dfd69ab95be --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/makefile.bcc @@ -0,0 +1,285 @@ +# Makefile for Independent JPEG Group's software + +# This makefile is suitable for Borland C on MS-DOS or OS/2. +# It works with Borland C++ for DOS, revision 3.0 or later, +# and has been tested with Borland C++ for OS/2. +# Watch out for optimization bugs in the OS/2 compilers --- see notes below! +# Thanks to Tom Wright and Ge' Weijers (original DOS) and +# Ken Porter (OS/2) for this file. + +# Read installation instructions before saying "make" !! + +# Are we under DOS or OS/2? +!if !$d(DOS) && !$d(OS2) +!if $d(__OS2__) +OS2=1 +!else +DOS=1 +!endif +!endif + +# The name of your C compiler: +CC= bcc + +# You may need to adjust these cc options: +!if $d(DOS) +CFLAGS= -O2 -mm -w-par -w-stu -w-ccc -w-rch +!else +CFLAGS= -O1 -w-par -w-stu -w-ccc -w-rch +!endif +# -O2 enables full code optimization (for pre-3.0 Borland C++, use -O -G -Z). +# -O2 is buggy in Borland OS/2 C++ revision 2.0, so use -O1 there for now. +# If you have Borland OS/2 C++ revision 1.0, use -O or no optimization at all. +# -mm selects medium memory model (near data, far code pointers; DOS only!) +# -w-par suppresses warnings about unused function parameters +# -w-stu suppresses warnings about incomplete structures +# -w-ccc suppresses warnings about compile-time-constant conditions +# -w-rch suppresses warnings about unreachable code +# Generally, we recommend defining any configuration symbols in jconfig.h, +# NOT via -D switches here. + +# Link-time cc options: +!if $d(DOS) +LDFLAGS= -mm +# memory model option here must match CFLAGS! +!else +LDFLAGS= +# -lai full-screen app +# -lc case-significant link +!endif + +# Put here the object file name for the correct system-dependent memory +# manager file. +# For DOS, we recommend jmemdos.c and jmemdosa.asm. +# For OS/2, we recommend jmemnobs.c (flat memory!) +# SYSDEPMEMLIB must list the same files with "+" signs for the librarian. +!if $d(DOS) +SYSDEPMEM= jmemdos.obj jmemdosa.obj +SYSDEPMEMLIB= +jmemdos.obj +jmemdosa.obj +!else +SYSDEPMEM= jmemnobs.obj +SYSDEPMEMLIB= +jmemnobs.obj +!endif + +# End of configurable options. + + +# source files: JPEG library proper +LIBSOURCES= jcapimin.c jcapistd.c jccoefct.c jccolor.c jcdctmgr.c jchuff.c \ + jcinit.c jcmainct.c jcmarker.c jcmaster.c jcomapi.c jcparam.c \ + jcphuff.c jcprepct.c jcsample.c jctrans.c jdapimin.c jdapistd.c \ + jdatadst.c jdatasrc.c jdcoefct.c jdcolor.c jddctmgr.c jdhuff.c \ + jdinput.c jdmainct.c jdmarker.c jdmaster.c jdmerge.c jdphuff.c \ + jdpostct.c jdsample.c jdtrans.c jerror.c jfdctflt.c jfdctfst.c \ + jfdctint.c jidctflt.c jidctfst.c jidctint.c jidctred.c jquant1.c \ + jquant2.c jutils.c jmemmgr.c +# memmgr back ends: compile only one of these into a working library +SYSDEPSOURCES= jmemansi.c jmemname.c jmemnobs.c jmemdos.c jmemmac.c +# source files: cjpeg/djpeg/jpegtran applications, also rdjpgcom/wrjpgcom +APPSOURCES= cjpeg.c djpeg.c jpegtran.c rdjpgcom.c wrjpgcom.c cdjpeg.c \ + rdcolmap.c rdswitch.c transupp.c rdppm.c wrppm.c rdgif.c wrgif.c \ + rdtarga.c wrtarga.c rdbmp.c wrbmp.c rdrle.c wrrle.c +SOURCES= $(LIBSOURCES) $(SYSDEPSOURCES) $(APPSOURCES) +# files included by source files +INCLUDES= jchuff.h jdhuff.h jdct.h jerror.h jinclude.h jmemsys.h jmorecfg.h \ + jpegint.h jpeglib.h jversion.h cdjpeg.h cderror.h transupp.h +# documentation, test, and support files +DOCS= README install.doc usage.doc cjpeg.1 djpeg.1 jpegtran.1 rdjpgcom.1 \ + wrjpgcom.1 wizard.doc example.c libjpeg.doc structure.doc \ + coderules.doc filelist.doc change.log +MKFILES= configure makefile.cfg makefile.ansi makefile.unix makefile.bcc \ + makefile.mc6 makefile.dj makefile.wat makefile.vc makelib.ds \ + makeapps.ds makeproj.mac makcjpeg.st makdjpeg.st makljpeg.st \ + maktjpeg.st makefile.manx makefile.sas makefile.mms makefile.vms \ + makvms.opt +CONFIGFILES= jconfig.cfg jconfig.bcc jconfig.mc6 jconfig.dj jconfig.wat \ + jconfig.vc jconfig.mac jconfig.st jconfig.manx jconfig.sas \ + jconfig.vms +CONFIGUREFILES= config.guess config.sub install-sh ltconfig ltmain.sh +OTHERFILES= jconfig.doc ckconfig.c ansi2knr.c ansi2knr.1 jmemdosa.asm +TESTFILES= testorig.jpg testimg.ppm testimg.bmp testimg.jpg testprog.jpg \ + testimgp.jpg +DISTFILES= $(DOCS) $(MKFILES) $(CONFIGFILES) $(SOURCES) $(INCLUDES) \ + $(CONFIGUREFILES) $(OTHERFILES) $(TESTFILES) +# library object files common to compression and decompression +COMOBJECTS= jcomapi.obj jutils.obj jerror.obj jmemmgr.obj $(SYSDEPMEM) +# compression library object files +CLIBOBJECTS= jcapimin.obj jcapistd.obj jctrans.obj jcparam.obj jdatadst.obj \ + jcinit.obj jcmaster.obj jcmarker.obj jcmainct.obj jcprepct.obj \ + jccoefct.obj jccolor.obj jcsample.obj jchuff.obj jcphuff.obj \ + jcdctmgr.obj jfdctfst.obj jfdctflt.obj jfdctint.obj +# decompression library object files +DLIBOBJECTS= jdapimin.obj jdapistd.obj jdtrans.obj jdatasrc.obj \ + jdmaster.obj jdinput.obj jdmarker.obj jdhuff.obj jdphuff.obj \ + jdmainct.obj jdcoefct.obj jdpostct.obj jddctmgr.obj jidctfst.obj \ + jidctflt.obj jidctint.obj jidctred.obj jdsample.obj jdcolor.obj \ + jquant1.obj jquant2.obj jdmerge.obj +# These objectfiles are included in libjpeg.lib +LIBOBJECTS= $(CLIBOBJECTS) $(DLIBOBJECTS) $(COMOBJECTS) +# object files for sample applications (excluding library files) +COBJECTS= cjpeg.obj rdppm.obj rdgif.obj rdtarga.obj rdrle.obj rdbmp.obj \ + rdswitch.obj cdjpeg.obj +DOBJECTS= djpeg.obj wrppm.obj wrgif.obj wrtarga.obj wrrle.obj wrbmp.obj \ + rdcolmap.obj cdjpeg.obj +TROBJECTS= jpegtran.obj rdswitch.obj cdjpeg.obj transupp.obj + + +all: libjpeg.lib cjpeg.exe djpeg.exe jpegtran.exe rdjpgcom.exe wrjpgcom.exe + +libjpeg.lib: $(LIBOBJECTS) + - del libjpeg.lib + tlib libjpeg.lib /E /C @&&| ++jcapimin.obj +jcapistd.obj +jctrans.obj +jcparam.obj +jdatadst.obj & ++jcinit.obj +jcmaster.obj +jcmarker.obj +jcmainct.obj +jcprepct.obj & ++jccoefct.obj +jccolor.obj +jcsample.obj +jchuff.obj +jcphuff.obj & ++jcdctmgr.obj +jfdctfst.obj +jfdctflt.obj +jfdctint.obj +jdapimin.obj & ++jdapistd.obj +jdtrans.obj +jdatasrc.obj +jdmaster.obj +jdinput.obj & ++jdmarker.obj +jdhuff.obj +jdphuff.obj +jdmainct.obj +jdcoefct.obj & ++jdpostct.obj +jddctmgr.obj +jidctfst.obj +jidctflt.obj +jidctint.obj & ++jidctred.obj +jdsample.obj +jdcolor.obj +jquant1.obj +jquant2.obj & ++jdmerge.obj +jcomapi.obj +jutils.obj +jerror.obj +jmemmgr.obj & +$(SYSDEPMEMLIB) +| + +cjpeg.exe: $(COBJECTS) libjpeg.lib + $(CC) $(LDFLAGS) -ecjpeg.exe $(COBJECTS) libjpeg.lib + +djpeg.exe: $(DOBJECTS) libjpeg.lib + $(CC) $(LDFLAGS) -edjpeg.exe $(DOBJECTS) libjpeg.lib + +jpegtran.exe: $(TROBJECTS) libjpeg.lib + $(CC) $(LDFLAGS) -ejpegtran.exe $(TROBJECTS) libjpeg.lib + +rdjpgcom.exe: rdjpgcom.c +!if $d(DOS) + $(CC) -ms -O rdjpgcom.c +!else + $(CC) $(CFLAGS) rdjpgcom.c +!endif + +# On DOS, wrjpgcom needs large model so it can malloc a 64K chunk +wrjpgcom.exe: wrjpgcom.c +!if $d(DOS) + $(CC) -ml -O wrjpgcom.c +!else + $(CC) $(CFLAGS) wrjpgcom.c +!endif + +# This "{}" syntax allows Borland Make to "batch" source files. +# In this way, each run of the compiler can build many modules. +.c.obj: + $(CC) $(CFLAGS) -c{ $<} + +jconfig.h: jconfig.doc + echo You must prepare a system-dependent jconfig.h file. + echo Please read the installation directions in install.doc. + exit 1 + +clean: + - del *.obj + - del libjpeg.lib + - del cjpeg.exe + - del djpeg.exe + - del jpegtran.exe + - del rdjpgcom.exe + - del wrjpgcom.exe + - del testout*.* + +test: cjpeg.exe djpeg.exe jpegtran.exe + - del testout*.* + djpeg -dct int -ppm -outfile testout.ppm testorig.jpg + djpeg -dct int -bmp -colors 256 -outfile testout.bmp testorig.jpg + cjpeg -dct int -outfile testout.jpg testimg.ppm + djpeg -dct int -ppm -outfile testoutp.ppm testprog.jpg + cjpeg -dct int -progressive -opt -outfile testoutp.jpg testimg.ppm + jpegtran -outfile testoutt.jpg testprog.jpg +!if $d(DOS) + fc /b testimg.ppm testout.ppm + fc /b testimg.bmp testout.bmp + fc /b testimg.jpg testout.jpg + fc /b testimg.ppm testoutp.ppm + fc /b testimgp.jpg testoutp.jpg + fc /b testorig.jpg testoutt.jpg +!else + echo n > n.tmp + comp testimg.ppm testout.ppm < n.tmp + comp testimg.bmp testout.bmp < n.tmp + comp testimg.jpg testout.jpg < n.tmp + comp testimg.ppm testoutp.ppm < n.tmp + comp testimgp.jpg testoutp.jpg < n.tmp + comp testorig.jpg testoutt.jpg < n.tmp + del n.tmp +!endif + + +jcapimin.obj: jcapimin.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcapistd.obj: jcapistd.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jccoefct.obj: jccoefct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jccolor.obj: jccolor.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcdctmgr.obj: jcdctmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jchuff.obj: jchuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jchuff.h +jcinit.obj: jcinit.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcmainct.obj: jcmainct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcmarker.obj: jcmarker.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcmaster.obj: jcmaster.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcomapi.obj: jcomapi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcparam.obj: jcparam.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcphuff.obj: jcphuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jchuff.h +jcprepct.obj: jcprepct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcsample.obj: jcsample.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jctrans.obj: jctrans.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdapimin.obj: jdapimin.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdapistd.obj: jdapistd.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdatadst.obj: jdatadst.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h +jdatasrc.obj: jdatasrc.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h +jdcoefct.obj: jdcoefct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdcolor.obj: jdcolor.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jddctmgr.obj: jddctmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jdhuff.obj: jdhuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdhuff.h +jdinput.obj: jdinput.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdmainct.obj: jdmainct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdmarker.obj: jdmarker.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdmaster.obj: jdmaster.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdmerge.obj: jdmerge.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdphuff.obj: jdphuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdhuff.h +jdpostct.obj: jdpostct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdsample.obj: jdsample.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdtrans.obj: jdtrans.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jerror.obj: jerror.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jversion.h jerror.h +jfdctflt.obj: jfdctflt.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jfdctfst.obj: jfdctfst.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jfdctint.obj: jfdctint.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jidctflt.obj: jidctflt.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jidctfst.obj: jidctfst.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jidctint.obj: jidctint.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jidctred.obj: jidctred.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jquant1.obj: jquant1.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jquant2.obj: jquant2.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jutils.obj: jutils.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jmemmgr.obj: jmemmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +jmemansi.obj: jmemansi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +jmemname.obj: jmemname.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +jmemnobs.obj: jmemnobs.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +jmemdos.obj: jmemdos.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +jmemmac.obj: jmemmac.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +cjpeg.obj: cjpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h jversion.h +djpeg.obj: djpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h jversion.h +jpegtran.obj: jpegtran.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h transupp.h jversion.h +rdjpgcom.obj: rdjpgcom.c jinclude.h jconfig.h +wrjpgcom.obj: wrjpgcom.c jinclude.h jconfig.h +cdjpeg.obj: cdjpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdcolmap.obj: rdcolmap.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdswitch.obj: rdswitch.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +transupp.obj: transupp.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h transupp.h +rdppm.obj: rdppm.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +wrppm.obj: wrppm.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdgif.obj: rdgif.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +wrgif.obj: wrgif.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdtarga.obj: rdtarga.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +wrtarga.obj: wrtarga.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdbmp.obj: rdbmp.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +wrbmp.obj: wrbmp.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdrle.obj: rdrle.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +wrrle.obj: wrrle.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +jmemdosa.obj: jmemdosa.asm + tasm /mx jmemdosa.asm diff --git a/lc-continuity/mk4/modimage/jpeg-6b/makefile.cfg b/lc-continuity/mk4/modimage/jpeg-6b/makefile.cfg new file mode 100644 index 0000000000000000000000000000000000000000..f25e42e3e66d90997777a6671db3b18ab72166fe --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/makefile.cfg @@ -0,0 +1,319 @@ +# Makefile for Independent JPEG Group's software + +# makefile.cfg is edited by configure to produce a custom Makefile. + +# Read installation instructions before saying "make" !! + +# For compiling with source and object files in different directories. +srcdir = @srcdir@ +VPATH = @srcdir@ + +# Where to install the programs and man pages. +prefix = @prefix@ +exec_prefix = @exec_prefix@ +bindir = $(exec_prefix)/bin +libdir = $(exec_prefix)/lib +includedir = $(prefix)/include +binprefix = +manprefix = +manext = 1 +mandir = $(prefix)/man/man$(manext) + +# The name of your C compiler: +CC= @CC@ + +# You may need to adjust these cc options: +CFLAGS= @CFLAGS@ @CPPFLAGS@ @INCLUDEFLAGS@ +# Generally, we recommend defining any configuration symbols in jconfig.h, +# NOT via -D switches here. +# However, any special defines for ansi2knr.c may be included here: +ANSI2KNRFLAGS= @ANSI2KNRFLAGS@ + +# Link-time cc options: +LDFLAGS= @LDFLAGS@ + +# To link any special libraries, add the necessary -l commands here. +LDLIBS= @LIBS@ + +# If using GNU libtool, LIBTOOL references it; if not, LIBTOOL is empty. +LIBTOOL = @LIBTOOL@ +# $(O) expands to "lo" if using libtool, plain "o" if not. +# Similarly, $(A) expands to "la" or "a". +O = @O@ +A = @A@ + +# Library version ID; libtool uses this for the shared library version number. +# Note: we suggest this match the macro of the same name in jpeglib.h. +JPEG_LIB_VERSION = @JPEG_LIB_VERSION@ + +# Put here the object file name for the correct system-dependent memory +# manager file. For Unix this is usually jmemnobs.o, but you may want +# to use jmemansi.o or jmemname.o if you have limited swap space. +SYSDEPMEM= @MEMORYMGR@ + +# miscellaneous OS-dependent stuff +SHELL= /bin/sh +# linker +LN= @LN@ +# file deletion command +RM= rm -f +# directory creation command +MKDIR= mkdir +# library (.a) file creation command +AR= ar rc +# second step in .a creation (use "touch" if not needed) +AR2= @RANLIB@ +# installation program +INSTALL= @INSTALL@ +INSTALL_PROGRAM= @INSTALL_PROGRAM@ +INSTALL_LIB= @INSTALL_LIB@ +INSTALL_DATA= @INSTALL_DATA@ + +# End of configurable options. + + +# source files: JPEG library proper +LIBSOURCES= jcapimin.c jcapistd.c jccoefct.c jccolor.c jcdctmgr.c jchuff.c \ + jcinit.c jcmainct.c jcmarker.c jcmaster.c jcomapi.c jcparam.c \ + jcphuff.c jcprepct.c jcsample.c jctrans.c jdapimin.c jdapistd.c \ + jdatadst.c jdatasrc.c jdcoefct.c jdcolor.c jddctmgr.c jdhuff.c \ + jdinput.c jdmainct.c jdmarker.c jdmaster.c jdmerge.c jdphuff.c \ + jdpostct.c jdsample.c jdtrans.c jerror.c jfdctflt.c jfdctfst.c \ + jfdctint.c jidctflt.c jidctfst.c jidctint.c jidctred.c jquant1.c \ + jquant2.c jutils.c jmemmgr.c +# memmgr back ends: compile only one of these into a working library +SYSDEPSOURCES= jmemansi.c jmemname.c jmemnobs.c jmemdos.c jmemmac.c +# source files: cjpeg/djpeg/jpegtran applications, also rdjpgcom/wrjpgcom +APPSOURCES= cjpeg.c djpeg.c jpegtran.c rdjpgcom.c wrjpgcom.c cdjpeg.c \ + rdcolmap.c rdswitch.c transupp.c rdppm.c wrppm.c rdgif.c wrgif.c \ + rdtarga.c wrtarga.c rdbmp.c wrbmp.c rdrle.c wrrle.c +SOURCES= $(LIBSOURCES) $(SYSDEPSOURCES) $(APPSOURCES) +# files included by source files +INCLUDES= jchuff.h jdhuff.h jdct.h jerror.h jinclude.h jmemsys.h jmorecfg.h \ + jpegint.h jpeglib.h jversion.h cdjpeg.h cderror.h transupp.h +# documentation, test, and support files +DOCS= README install.doc usage.doc cjpeg.1 djpeg.1 jpegtran.1 rdjpgcom.1 \ + wrjpgcom.1 wizard.doc example.c libjpeg.doc structure.doc \ + coderules.doc filelist.doc change.log +MKFILES= configure makefile.cfg makefile.ansi makefile.unix makefile.bcc \ + makefile.mc6 makefile.dj makefile.wat makefile.vc makelib.ds \ + makeapps.ds makeproj.mac makcjpeg.st makdjpeg.st makljpeg.st \ + maktjpeg.st makefile.manx makefile.sas makefile.mms makefile.vms \ + makvms.opt +CONFIGFILES= jconfig.cfg jconfig.bcc jconfig.mc6 jconfig.dj jconfig.wat \ + jconfig.vc jconfig.mac jconfig.st jconfig.manx jconfig.sas \ + jconfig.vms +CONFIGUREFILES= config.guess config.sub install-sh ltconfig ltmain.sh +OTHERFILES= jconfig.doc ckconfig.c ansi2knr.c ansi2knr.1 jmemdosa.asm +TESTFILES= testorig.jpg testimg.ppm testimg.bmp testimg.jpg testprog.jpg \ + testimgp.jpg +DISTFILES= $(DOCS) $(MKFILES) $(CONFIGFILES) $(SOURCES) $(INCLUDES) \ + $(CONFIGUREFILES) $(OTHERFILES) $(TESTFILES) +# library object files common to compression and decompression +COMOBJECTS= jcomapi.$(O) jutils.$(O) jerror.$(O) jmemmgr.$(O) $(SYSDEPMEM) +# compression library object files +CLIBOBJECTS= jcapimin.$(O) jcapistd.$(O) jctrans.$(O) jcparam.$(O) \ + jdatadst.$(O) jcinit.$(O) jcmaster.$(O) jcmarker.$(O) jcmainct.$(O) \ + jcprepct.$(O) jccoefct.$(O) jccolor.$(O) jcsample.$(O) jchuff.$(O) \ + jcphuff.$(O) jcdctmgr.$(O) jfdctfst.$(O) jfdctflt.$(O) \ + jfdctint.$(O) +# decompression library object files +DLIBOBJECTS= jdapimin.$(O) jdapistd.$(O) jdtrans.$(O) jdatasrc.$(O) \ + jdmaster.$(O) jdinput.$(O) jdmarker.$(O) jdhuff.$(O) jdphuff.$(O) \ + jdmainct.$(O) jdcoefct.$(O) jdpostct.$(O) jddctmgr.$(O) \ + jidctfst.$(O) jidctflt.$(O) jidctint.$(O) jidctred.$(O) \ + jdsample.$(O) jdcolor.$(O) jquant1.$(O) jquant2.$(O) jdmerge.$(O) +# These objectfiles are included in libjpeg.a +LIBOBJECTS= $(CLIBOBJECTS) $(DLIBOBJECTS) $(COMOBJECTS) +# object files for sample applications (excluding library files) +COBJECTS= cjpeg.$(O) rdppm.$(O) rdgif.$(O) rdtarga.$(O) rdrle.$(O) \ + rdbmp.$(O) rdswitch.$(O) cdjpeg.$(O) +DOBJECTS= djpeg.$(O) wrppm.$(O) wrgif.$(O) wrtarga.$(O) wrrle.$(O) \ + wrbmp.$(O) rdcolmap.$(O) cdjpeg.$(O) +TROBJECTS= jpegtran.$(O) rdswitch.$(O) cdjpeg.$(O) transupp.$(O) + + +all: @A2K_DEPS@ libjpeg.$(A) cjpeg djpeg jpegtran rdjpgcom wrjpgcom + +# Special compilation rules to support ansi2knr and libtool. +.SUFFIXES: .lo .la + +# How to compile with libtool. +@COM_LT@.c.lo: +@COM_LT@ $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c $(srcdir)/$*.c + +# How to use ansi2knr, when not using libtool. +@COM_A2K@.c.o: +@COM_A2K@ ./ansi2knr $(srcdir)/$*.c knr/$*.c +@COM_A2K@ $(CC) $(CFLAGS) -c knr/$*.c +@COM_A2K@ $(RM) knr/$*.c + +# How to use ansi2knr AND libtool. +@COM_A2K@.c.lo: +@COM_A2K@ ./ansi2knr $(srcdir)/$*.c knr/$*.c +@COM_A2K@ $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c knr/$*.c +@COM_A2K@ $(RM) knr/$*.c + +ansi2knr: ansi2knr.c + $(CC) $(CFLAGS) $(ANSI2KNRFLAGS) -o ansi2knr $(srcdir)/ansi2knr.c + $(MKDIR) knr + +# the library: + +# without libtool: +libjpeg.a: @A2K_DEPS@ $(LIBOBJECTS) + $(RM) libjpeg.a + $(AR) libjpeg.a $(LIBOBJECTS) + $(AR2) libjpeg.a + +# with libtool: +libjpeg.la: @A2K_DEPS@ $(LIBOBJECTS) + $(LIBTOOL) --mode=link $(CC) -o libjpeg.la $(LIBOBJECTS) \ + -rpath $(libdir) -version-info $(JPEG_LIB_VERSION) + +# sample programs: + +cjpeg: $(COBJECTS) libjpeg.$(A) + $(LN) $(LDFLAGS) -o cjpeg $(COBJECTS) libjpeg.$(A) $(LDLIBS) + +djpeg: $(DOBJECTS) libjpeg.$(A) + $(LN) $(LDFLAGS) -o djpeg $(DOBJECTS) libjpeg.$(A) $(LDLIBS) + +jpegtran: $(TROBJECTS) libjpeg.$(A) + $(LN) $(LDFLAGS) -o jpegtran $(TROBJECTS) libjpeg.$(A) $(LDLIBS) + +rdjpgcom: rdjpgcom.$(O) + $(LN) $(LDFLAGS) -o rdjpgcom rdjpgcom.$(O) $(LDLIBS) + +wrjpgcom: wrjpgcom.$(O) + $(LN) $(LDFLAGS) -o wrjpgcom wrjpgcom.$(O) $(LDLIBS) + +# Installation rules: + +install: cjpeg djpeg jpegtran rdjpgcom wrjpgcom @FORCE_INSTALL_LIB@ + $(INSTALL_PROGRAM) cjpeg $(bindir)/$(binprefix)cjpeg + $(INSTALL_PROGRAM) djpeg $(bindir)/$(binprefix)djpeg + $(INSTALL_PROGRAM) jpegtran $(bindir)/$(binprefix)jpegtran + $(INSTALL_PROGRAM) rdjpgcom $(bindir)/$(binprefix)rdjpgcom + $(INSTALL_PROGRAM) wrjpgcom $(bindir)/$(binprefix)wrjpgcom + $(INSTALL_DATA) $(srcdir)/cjpeg.1 $(mandir)/$(manprefix)cjpeg.$(manext) + $(INSTALL_DATA) $(srcdir)/djpeg.1 $(mandir)/$(manprefix)djpeg.$(manext) + $(INSTALL_DATA) $(srcdir)/jpegtran.1 $(mandir)/$(manprefix)jpegtran.$(manext) + $(INSTALL_DATA) $(srcdir)/rdjpgcom.1 $(mandir)/$(manprefix)rdjpgcom.$(manext) + $(INSTALL_DATA) $(srcdir)/wrjpgcom.1 $(mandir)/$(manprefix)wrjpgcom.$(manext) + +install-lib: libjpeg.$(A) install-headers + $(INSTALL_LIB) libjpeg.$(A) $(libdir)/$(binprefix)libjpeg.$(A) + +install-headers: jconfig.h + $(INSTALL_DATA) jconfig.h $(includedir)/jconfig.h + $(INSTALL_DATA) $(srcdir)/jpeglib.h $(includedir)/jpeglib.h + $(INSTALL_DATA) $(srcdir)/jmorecfg.h $(includedir)/jmorecfg.h + $(INSTALL_DATA) $(srcdir)/jerror.h $(includedir)/jerror.h + +clean: + $(RM) *.o *.lo libjpeg.a libjpeg.la + $(RM) cjpeg djpeg jpegtran rdjpgcom wrjpgcom + $(RM) ansi2knr core testout* config.log config.status + $(RM) -r knr .libs _libs + +distclean: clean + $(RM) Makefile jconfig.h libtool config.cache + +test: cjpeg djpeg jpegtran + $(RM) testout* + ./djpeg -dct int -ppm -outfile testout.ppm $(srcdir)/testorig.jpg + ./djpeg -dct int -bmp -colors 256 -outfile testout.bmp $(srcdir)/testorig.jpg + ./cjpeg -dct int -outfile testout.jpg $(srcdir)/testimg.ppm + ./djpeg -dct int -ppm -outfile testoutp.ppm $(srcdir)/testprog.jpg + ./cjpeg -dct int -progressive -opt -outfile testoutp.jpg $(srcdir)/testimg.ppm + ./jpegtran -outfile testoutt.jpg $(srcdir)/testprog.jpg + cmp $(srcdir)/testimg.ppm testout.ppm + cmp $(srcdir)/testimg.bmp testout.bmp + cmp $(srcdir)/testimg.jpg testout.jpg + cmp $(srcdir)/testimg.ppm testoutp.ppm + cmp $(srcdir)/testimgp.jpg testoutp.jpg + cmp $(srcdir)/testorig.jpg testoutt.jpg + +check: test + +# Mistake catcher: + +jconfig.h: jconfig.doc + echo You must prepare a system-dependent jconfig.h file. + echo Please read the installation directions in install.doc. + exit 1 + +# GNU Make likes to know which target names are not really files to be made: +.PHONY: all install install-lib install-headers clean distclean test check + + +jcapimin.$(O): jcapimin.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcapistd.$(O): jcapistd.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jccoefct.$(O): jccoefct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jccolor.$(O): jccolor.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcdctmgr.$(O): jcdctmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jchuff.$(O): jchuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jchuff.h +jcinit.$(O): jcinit.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcmainct.$(O): jcmainct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcmarker.$(O): jcmarker.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcmaster.$(O): jcmaster.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcomapi.$(O): jcomapi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcparam.$(O): jcparam.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcphuff.$(O): jcphuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jchuff.h +jcprepct.$(O): jcprepct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcsample.$(O): jcsample.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jctrans.$(O): jctrans.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdapimin.$(O): jdapimin.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdapistd.$(O): jdapistd.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdatadst.$(O): jdatadst.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h +jdatasrc.$(O): jdatasrc.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h +jdcoefct.$(O): jdcoefct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdcolor.$(O): jdcolor.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jddctmgr.$(O): jddctmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jdhuff.$(O): jdhuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdhuff.h +jdinput.$(O): jdinput.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdmainct.$(O): jdmainct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdmarker.$(O): jdmarker.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdmaster.$(O): jdmaster.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdmerge.$(O): jdmerge.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdphuff.$(O): jdphuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdhuff.h +jdpostct.$(O): jdpostct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdsample.$(O): jdsample.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdtrans.$(O): jdtrans.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jerror.$(O): jerror.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jversion.h jerror.h +jfdctflt.$(O): jfdctflt.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jfdctfst.$(O): jfdctfst.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jfdctint.$(O): jfdctint.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jidctflt.$(O): jidctflt.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jidctfst.$(O): jidctfst.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jidctint.$(O): jidctint.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jidctred.$(O): jidctred.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jquant1.$(O): jquant1.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jquant2.$(O): jquant2.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jutils.$(O): jutils.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jmemmgr.$(O): jmemmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +jmemansi.$(O): jmemansi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +jmemname.$(O): jmemname.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +jmemnobs.$(O): jmemnobs.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +jmemdos.$(O): jmemdos.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +jmemmac.$(O): jmemmac.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +cjpeg.$(O): cjpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h jversion.h +djpeg.$(O): djpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h jversion.h +jpegtran.$(O): jpegtran.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h transupp.h jversion.h +rdjpgcom.$(O): rdjpgcom.c jinclude.h jconfig.h +wrjpgcom.$(O): wrjpgcom.c jinclude.h jconfig.h +cdjpeg.$(O): cdjpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdcolmap.$(O): rdcolmap.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdswitch.$(O): rdswitch.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +transupp.$(O): transupp.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h transupp.h +rdppm.$(O): rdppm.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +wrppm.$(O): wrppm.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdgif.$(O): rdgif.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +wrgif.$(O): wrgif.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdtarga.$(O): rdtarga.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +wrtarga.$(O): wrtarga.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdbmp.$(O): rdbmp.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +wrbmp.$(O): wrbmp.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdrle.$(O): rdrle.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +wrrle.$(O): wrrle.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h diff --git a/lc-continuity/mk4/modimage/jpeg-6b/makefile.dj b/lc-continuity/mk4/modimage/jpeg-6b/makefile.dj new file mode 100644 index 0000000000000000000000000000000000000000..f766d25e38a7d76ea0007a0243a4340be5b78140 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/makefile.dj @@ -0,0 +1,220 @@ +# Makefile for Independent JPEG Group's software + +# This makefile is for DJGPP (Delorie's GNU C port on MS-DOS), v2.0 or later. +# Thanks to Frank J. Donahoe for this version. + +# Read installation instructions before saying "make" !! + +# The name of your C compiler: +CC= gcc + +# You may need to adjust these cc options: +CFLAGS= -O2 -Wall -I. +# Generally, we recommend defining any configuration symbols in jconfig.h, +# NOT via -D switches here. + +# Link-time cc options: +LDFLAGS= -s + +# To link any special libraries, add the necessary -l commands here. +LDLIBS= + +# Put here the object file name for the correct system-dependent memory +# manager file. For DJGPP this is usually jmemnobs.o, but you could +# use jmemname.o if you want to use named temp files instead of swap space. +SYSDEPMEM= jmemnobs.o + +# miscellaneous OS-dependent stuff +# linker +LN= $(CC) +# file deletion command +RM= del +# library (.a) file creation command +AR= ar rc +# second step in .a creation (use "touch" if not needed) +AR2= ranlib + +# End of configurable options. + + +# source files: JPEG library proper +LIBSOURCES= jcapimin.c jcapistd.c jccoefct.c jccolor.c jcdctmgr.c jchuff.c \ + jcinit.c jcmainct.c jcmarker.c jcmaster.c jcomapi.c jcparam.c \ + jcphuff.c jcprepct.c jcsample.c jctrans.c jdapimin.c jdapistd.c \ + jdatadst.c jdatasrc.c jdcoefct.c jdcolor.c jddctmgr.c jdhuff.c \ + jdinput.c jdmainct.c jdmarker.c jdmaster.c jdmerge.c jdphuff.c \ + jdpostct.c jdsample.c jdtrans.c jerror.c jfdctflt.c jfdctfst.c \ + jfdctint.c jidctflt.c jidctfst.c jidctint.c jidctred.c jquant1.c \ + jquant2.c jutils.c jmemmgr.c +# memmgr back ends: compile only one of these into a working library +SYSDEPSOURCES= jmemansi.c jmemname.c jmemnobs.c jmemdos.c jmemmac.c +# source files: cjpeg/djpeg/jpegtran applications, also rdjpgcom/wrjpgcom +APPSOURCES= cjpeg.c djpeg.c jpegtran.c rdjpgcom.c wrjpgcom.c cdjpeg.c \ + rdcolmap.c rdswitch.c transupp.c rdppm.c wrppm.c rdgif.c wrgif.c \ + rdtarga.c wrtarga.c rdbmp.c wrbmp.c rdrle.c wrrle.c +SOURCES= $(LIBSOURCES) $(SYSDEPSOURCES) $(APPSOURCES) +# files included by source files +INCLUDES= jchuff.h jdhuff.h jdct.h jerror.h jinclude.h jmemsys.h jmorecfg.h \ + jpegint.h jpeglib.h jversion.h cdjpeg.h cderror.h transupp.h +# documentation, test, and support files +DOCS= README install.doc usage.doc cjpeg.1 djpeg.1 jpegtran.1 rdjpgcom.1 \ + wrjpgcom.1 wizard.doc example.c libjpeg.doc structure.doc \ + coderules.doc filelist.doc change.log +MKFILES= configure makefile.cfg makefile.ansi makefile.unix makefile.bcc \ + makefile.mc6 makefile.dj makefile.wat makefile.vc makelib.ds \ + makeapps.ds makeproj.mac makcjpeg.st makdjpeg.st makljpeg.st \ + maktjpeg.st makefile.manx makefile.sas makefile.mms makefile.vms \ + makvms.opt +CONFIGFILES= jconfig.cfg jconfig.bcc jconfig.mc6 jconfig.dj jconfig.wat \ + jconfig.vc jconfig.mac jconfig.st jconfig.manx jconfig.sas \ + jconfig.vms +CONFIGUREFILES= config.guess config.sub install-sh ltconfig ltmain.sh +OTHERFILES= jconfig.doc ckconfig.c ansi2knr.c ansi2knr.1 jmemdosa.asm +TESTFILES= testorig.jpg testimg.ppm testimg.bmp testimg.jpg testprog.jpg \ + testimgp.jpg +DISTFILES= $(DOCS) $(MKFILES) $(CONFIGFILES) $(SOURCES) $(INCLUDES) \ + $(CONFIGUREFILES) $(OTHERFILES) $(TESTFILES) +# library object files common to compression and decompression +COMOBJECTS= jcomapi.o jutils.o jerror.o jmemmgr.o $(SYSDEPMEM) +# compression library object files +CLIBOBJECTS= jcapimin.o jcapistd.o jctrans.o jcparam.o jdatadst.o jcinit.o \ + jcmaster.o jcmarker.o jcmainct.o jcprepct.o jccoefct.o jccolor.o \ + jcsample.o jchuff.o jcphuff.o jcdctmgr.o jfdctfst.o jfdctflt.o \ + jfdctint.o +# decompression library object files +DLIBOBJECTS= jdapimin.o jdapistd.o jdtrans.o jdatasrc.o jdmaster.o \ + jdinput.o jdmarker.o jdhuff.o jdphuff.o jdmainct.o jdcoefct.o \ + jdpostct.o jddctmgr.o jidctfst.o jidctflt.o jidctint.o jidctred.o \ + jdsample.o jdcolor.o jquant1.o jquant2.o jdmerge.o +# These objectfiles are included in libjpeg.a +LIBOBJECTS= $(CLIBOBJECTS) $(DLIBOBJECTS) $(COMOBJECTS) +# object files for sample applications (excluding library files) +COBJECTS= cjpeg.o rdppm.o rdgif.o rdtarga.o rdrle.o rdbmp.o rdswitch.o \ + cdjpeg.o +DOBJECTS= djpeg.o wrppm.o wrgif.o wrtarga.o wrrle.o wrbmp.o rdcolmap.o \ + cdjpeg.o +TROBJECTS= jpegtran.o rdswitch.o cdjpeg.o transupp.o + + +all: libjpeg.a cjpeg.exe djpeg.exe jpegtran.exe rdjpgcom.exe wrjpgcom.exe + +libjpeg.a: $(LIBOBJECTS) + $(RM) libjpeg.a + $(AR) libjpeg.a $(LIBOBJECTS) + $(AR2) libjpeg.a + +cjpeg.exe: $(COBJECTS) libjpeg.a + $(LN) $(LDFLAGS) -o cjpeg.exe $(COBJECTS) libjpeg.a $(LDLIBS) + +djpeg.exe: $(DOBJECTS) libjpeg.a + $(LN) $(LDFLAGS) -o djpeg.exe $(DOBJECTS) libjpeg.a $(LDLIBS) + +jpegtran.exe: $(TROBJECTS) libjpeg.a + $(LN) $(LDFLAGS) -o jpegtran.exe $(TROBJECTS) libjpeg.a $(LDLIBS) + +rdjpgcom.exe: rdjpgcom.o + $(LN) $(LDFLAGS) -o rdjpgcom.exe rdjpgcom.o $(LDLIBS) + +wrjpgcom.exe: wrjpgcom.o + $(LN) $(LDFLAGS) -o wrjpgcom.exe wrjpgcom.o $(LDLIBS) + +jconfig.h: jconfig.doc + echo You must prepare a system-dependent jconfig.h file. + echo Please read the installation directions in install.doc. + exit 1 + +clean: + $(RM) *.o + $(RM) cjpeg.exe + $(RM) djpeg.exe + $(RM) jpegtran.exe + $(RM) rdjpgcom.exe + $(RM) wrjpgcom.exe + $(RM) libjpeg.a + $(RM) testout*.* + +test: cjpeg.exe djpeg.exe jpegtran.exe + $(RM) testout*.* + ./djpeg -dct int -ppm -outfile testout.ppm testorig.jpg + ./djpeg -dct int -bmp -colors 256 -outfile testout.bmp testorig.jpg + ./cjpeg -dct int -outfile testout.jpg testimg.ppm + ./djpeg -dct int -ppm -outfile testoutp.ppm testprog.jpg + ./cjpeg -dct int -progressive -opt -outfile testoutp.jpg testimg.ppm + ./jpegtran -outfile testoutt.jpg testprog.jpg + fc /b testimg.ppm testout.ppm + fc /b testimg.bmp testout.bmp + fc /b testimg.jpg testout.jpg + fc /b testimg.ppm testoutp.ppm + fc /b testimgp.jpg testoutp.jpg + fc /b testorig.jpg testoutt.jpg + + +jcapimin.o: jcapimin.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcapistd.o: jcapistd.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jccoefct.o: jccoefct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jccolor.o: jccolor.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcdctmgr.o: jcdctmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jchuff.o: jchuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jchuff.h +jcinit.o: jcinit.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcmainct.o: jcmainct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcmarker.o: jcmarker.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcmaster.o: jcmaster.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcomapi.o: jcomapi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcparam.o: jcparam.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcphuff.o: jcphuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jchuff.h +jcprepct.o: jcprepct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcsample.o: jcsample.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jctrans.o: jctrans.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdapimin.o: jdapimin.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdapistd.o: jdapistd.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdatadst.o: jdatadst.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h +jdatasrc.o: jdatasrc.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h +jdcoefct.o: jdcoefct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdcolor.o: jdcolor.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jddctmgr.o: jddctmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jdhuff.o: jdhuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdhuff.h +jdinput.o: jdinput.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdmainct.o: jdmainct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdmarker.o: jdmarker.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdmaster.o: jdmaster.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdmerge.o: jdmerge.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdphuff.o: jdphuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdhuff.h +jdpostct.o: jdpostct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdsample.o: jdsample.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdtrans.o: jdtrans.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jerror.o: jerror.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jversion.h jerror.h +jfdctflt.o: jfdctflt.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jfdctfst.o: jfdctfst.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jfdctint.o: jfdctint.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jidctflt.o: jidctflt.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jidctfst.o: jidctfst.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jidctint.o: jidctint.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jidctred.o: jidctred.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jquant1.o: jquant1.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jquant2.o: jquant2.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jutils.o: jutils.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jmemmgr.o: jmemmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +jmemansi.o: jmemansi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +jmemname.o: jmemname.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +jmemnobs.o: jmemnobs.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +jmemdos.o: jmemdos.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +jmemmac.o: jmemmac.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +cjpeg.o: cjpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h jversion.h +djpeg.o: djpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h jversion.h +jpegtran.o: jpegtran.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h transupp.h jversion.h +rdjpgcom.o: rdjpgcom.c jinclude.h jconfig.h +wrjpgcom.o: wrjpgcom.c jinclude.h jconfig.h +cdjpeg.o: cdjpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdcolmap.o: rdcolmap.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdswitch.o: rdswitch.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +transupp.o: transupp.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h transupp.h +rdppm.o: rdppm.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +wrppm.o: wrppm.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdgif.o: rdgif.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +wrgif.o: wrgif.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdtarga.o: rdtarga.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +wrtarga.o: wrtarga.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdbmp.o: rdbmp.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +wrbmp.o: wrbmp.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdrle.o: rdrle.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +wrrle.o: wrrle.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h diff --git a/lc-continuity/mk4/modimage/jpeg-6b/makefile.manx b/lc-continuity/mk4/modimage/jpeg-6b/makefile.manx new file mode 100644 index 0000000000000000000000000000000000000000..4cb42d17ca1d29fa0ff7e436b89bda46587a520b --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/makefile.manx @@ -0,0 +1,214 @@ +# Makefile for Independent JPEG Group's software + +# This makefile is for Amiga systems using Manx Aztec C ver 5.x. +# Thanks to D.J. James (djjames@cup.portal.com) for this version. + +# Read installation instructions before saying "make" !! + +# The name of your C compiler: +CC= cc + +# You may need to adjust these cc options: +# Uncomment for generic 68000 code (will work on any Amiga) +ARCHFLAGS= -sn + +# Uncomment for 68020/68030 code (faster, but won't run on 68000 CPU) +#ARCHFLAGS= -c2 + +CFLAGS= -MC -MD $(ARCHFLAGS) -spfam -r4 + +# Link-time cc options: +LDFLAGS= -g + +# To link any special libraries, add the necessary -l commands here. +LDLIBS= -lml -lcl + +# Put here the object file name for the correct system-dependent memory +# manager file. For Amiga we recommend jmemname.o. +SYSDEPMEM= jmemname.o + +# miscellaneous OS-dependent stuff +# linker +LN= ln +# file deletion command +RM= delete quiet +# library (.lib) file creation command +AR= lb + +# End of configurable options. + + +# source files: JPEG library proper +LIBSOURCES= jcapimin.c jcapistd.c jccoefct.c jccolor.c jcdctmgr.c jchuff.c \ + jcinit.c jcmainct.c jcmarker.c jcmaster.c jcomapi.c jcparam.c \ + jcphuff.c jcprepct.c jcsample.c jctrans.c jdapimin.c jdapistd.c \ + jdatadst.c jdatasrc.c jdcoefct.c jdcolor.c jddctmgr.c jdhuff.c \ + jdinput.c jdmainct.c jdmarker.c jdmaster.c jdmerge.c jdphuff.c \ + jdpostct.c jdsample.c jdtrans.c jerror.c jfdctflt.c jfdctfst.c \ + jfdctint.c jidctflt.c jidctfst.c jidctint.c jidctred.c jquant1.c \ + jquant2.c jutils.c jmemmgr.c +# memmgr back ends: compile only one of these into a working library +SYSDEPSOURCES= jmemansi.c jmemname.c jmemnobs.c jmemdos.c jmemmac.c +# source files: cjpeg/djpeg/jpegtran applications, also rdjpgcom/wrjpgcom +APPSOURCES= cjpeg.c djpeg.c jpegtran.c rdjpgcom.c wrjpgcom.c cdjpeg.c \ + rdcolmap.c rdswitch.c transupp.c rdppm.c wrppm.c rdgif.c wrgif.c \ + rdtarga.c wrtarga.c rdbmp.c wrbmp.c rdrle.c wrrle.c +SOURCES= $(LIBSOURCES) $(SYSDEPSOURCES) $(APPSOURCES) +# files included by source files +INCLUDES= jchuff.h jdhuff.h jdct.h jerror.h jinclude.h jmemsys.h jmorecfg.h \ + jpegint.h jpeglib.h jversion.h cdjpeg.h cderror.h transupp.h +# documentation, test, and support files +DOCS= README install.doc usage.doc cjpeg.1 djpeg.1 jpegtran.1 rdjpgcom.1 \ + wrjpgcom.1 wizard.doc example.c libjpeg.doc structure.doc \ + coderules.doc filelist.doc change.log +MKFILES= configure makefile.cfg makefile.ansi makefile.unix makefile.bcc \ + makefile.mc6 makefile.dj makefile.wat makefile.vc makelib.ds \ + makeapps.ds makeproj.mac makcjpeg.st makdjpeg.st makljpeg.st \ + maktjpeg.st makefile.manx makefile.sas makefile.mms makefile.vms \ + makvms.opt +CONFIGFILES= jconfig.cfg jconfig.bcc jconfig.mc6 jconfig.dj jconfig.wat \ + jconfig.vc jconfig.mac jconfig.st jconfig.manx jconfig.sas \ + jconfig.vms +CONFIGUREFILES= config.guess config.sub install-sh ltconfig ltmain.sh +OTHERFILES= jconfig.doc ckconfig.c ansi2knr.c ansi2knr.1 jmemdosa.asm +TESTFILES= testorig.jpg testimg.ppm testimg.bmp testimg.jpg testprog.jpg \ + testimgp.jpg +DISTFILES= $(DOCS) $(MKFILES) $(CONFIGFILES) $(SOURCES) $(INCLUDES) \ + $(CONFIGUREFILES) $(OTHERFILES) $(TESTFILES) +# library object files common to compression and decompression +COMOBJECTS= jcomapi.o jutils.o jerror.o jmemmgr.o $(SYSDEPMEM) +# compression library object files +CLIBOBJECTS= jcapimin.o jcapistd.o jctrans.o jcparam.o jdatadst.o jcinit.o \ + jcmaster.o jcmarker.o jcmainct.o jcprepct.o jccoefct.o jccolor.o \ + jcsample.o jchuff.o jcphuff.o jcdctmgr.o jfdctfst.o jfdctflt.o \ + jfdctint.o +# decompression library object files +DLIBOBJECTS= jdapimin.o jdapistd.o jdtrans.o jdatasrc.o jdmaster.o \ + jdinput.o jdmarker.o jdhuff.o jdphuff.o jdmainct.o jdcoefct.o \ + jdpostct.o jddctmgr.o jidctfst.o jidctflt.o jidctint.o jidctred.o \ + jdsample.o jdcolor.o jquant1.o jquant2.o jdmerge.o +# These objectfiles are included in libjpeg.lib +LIBOBJECTS= $(CLIBOBJECTS) $(DLIBOBJECTS) $(COMOBJECTS) +# object files for sample applications (excluding library files) +COBJECTS= cjpeg.o rdppm.o rdgif.o rdtarga.o rdrle.o rdbmp.o rdswitch.o \ + cdjpeg.o +DOBJECTS= djpeg.o wrppm.o wrgif.o wrtarga.o wrrle.o wrbmp.o rdcolmap.o \ + cdjpeg.o +TROBJECTS= jpegtran.o rdswitch.o cdjpeg.o transupp.o + + +all: libjpeg.lib cjpeg djpeg jpegtran rdjpgcom wrjpgcom + +libjpeg.lib: $(LIBOBJECTS) + -$(RM) libjpeg.lib + $(AR) libjpeg.lib $(LIBOBJECTS) + +cjpeg: $(COBJECTS) libjpeg.lib + $(LN) $(LDFLAGS) -o cjpeg $(COBJECTS) libjpeg.lib $(LDLIBS) + +djpeg: $(DOBJECTS) libjpeg.lib + $(LN) $(LDFLAGS) -o djpeg $(DOBJECTS) libjpeg.lib $(LDLIBS) + +jpegtran: $(TROBJECTS) libjpeg.lib + $(LN) $(LDFLAGS) -o jpegtran $(TROBJECTS) libjpeg.lib $(LDLIBS) + +rdjpgcom: rdjpgcom.o + $(LN) $(LDFLAGS) -o rdjpgcom rdjpgcom.o $(LDLIBS) + +wrjpgcom: wrjpgcom.o + $(LN) $(LDFLAGS) -o wrjpgcom wrjpgcom.o $(LDLIBS) + +jconfig.h: jconfig.doc + echo You must prepare a system-dependent jconfig.h file. + echo Please read the installation directions in install.doc. + exit 1 + +clean: + -$(RM) *.o cjpeg djpeg jpegtran libjpeg.lib rdjpgcom wrjpgcom + -$(RM) core testout*.* + +test: cjpeg djpeg jpegtran + -$(RM) testout*.* + djpeg -dct int -ppm -outfile testout.ppm testorig.jpg + djpeg -dct int -bmp -colors 256 -outfile testout.bmp testorig.jpg + cjpeg -dct int -outfile testout.jpg testimg.ppm + djpeg -dct int -ppm -outfile testoutp.ppm testprog.jpg + cjpeg -dct int -progressive -opt -outfile testoutp.jpg testimg.ppm + jpegtran -outfile testoutt.jpg testprog.jpg + cmp testimg.ppm testout.ppm + cmp testimg.bmp testout.bmp + cmp testimg.jpg testout.jpg + cmp testimg.ppm testoutp.ppm + cmp testimgp.jpg testoutp.jpg + cmp testorig.jpg testoutt.jpg + + +jcapimin.o: jcapimin.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcapistd.o: jcapistd.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jccoefct.o: jccoefct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jccolor.o: jccolor.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcdctmgr.o: jcdctmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jchuff.o: jchuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jchuff.h +jcinit.o: jcinit.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcmainct.o: jcmainct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcmarker.o: jcmarker.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcmaster.o: jcmaster.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcomapi.o: jcomapi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcparam.o: jcparam.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcphuff.o: jcphuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jchuff.h +jcprepct.o: jcprepct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcsample.o: jcsample.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jctrans.o: jctrans.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdapimin.o: jdapimin.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdapistd.o: jdapistd.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdatadst.o: jdatadst.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h +jdatasrc.o: jdatasrc.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h +jdcoefct.o: jdcoefct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdcolor.o: jdcolor.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jddctmgr.o: jddctmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jdhuff.o: jdhuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdhuff.h +jdinput.o: jdinput.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdmainct.o: jdmainct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdmarker.o: jdmarker.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdmaster.o: jdmaster.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdmerge.o: jdmerge.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdphuff.o: jdphuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdhuff.h +jdpostct.o: jdpostct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdsample.o: jdsample.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdtrans.o: jdtrans.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jerror.o: jerror.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jversion.h jerror.h +jfdctflt.o: jfdctflt.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jfdctfst.o: jfdctfst.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jfdctint.o: jfdctint.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jidctflt.o: jidctflt.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jidctfst.o: jidctfst.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jidctint.o: jidctint.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jidctred.o: jidctred.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jquant1.o: jquant1.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jquant2.o: jquant2.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jutils.o: jutils.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jmemmgr.o: jmemmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +jmemansi.o: jmemansi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +jmemname.o: jmemname.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +jmemnobs.o: jmemnobs.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +jmemdos.o: jmemdos.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +jmemmac.o: jmemmac.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +cjpeg.o: cjpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h jversion.h +djpeg.o: djpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h jversion.h +jpegtran.o: jpegtran.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h transupp.h jversion.h +rdjpgcom.o: rdjpgcom.c jinclude.h jconfig.h +wrjpgcom.o: wrjpgcom.c jinclude.h jconfig.h +cdjpeg.o: cdjpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdcolmap.o: rdcolmap.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdswitch.o: rdswitch.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +transupp.o: transupp.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h transupp.h +rdppm.o: rdppm.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +wrppm.o: wrppm.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdgif.o: rdgif.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +wrgif.o: wrgif.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdtarga.o: rdtarga.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +wrtarga.o: wrtarga.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdbmp.o: rdbmp.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +wrbmp.o: wrbmp.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdrle.o: rdrle.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +wrrle.o: wrrle.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h diff --git a/lc-continuity/mk4/modimage/jpeg-6b/makefile.mc6 b/lc-continuity/mk4/modimage/jpeg-6b/makefile.mc6 new file mode 100644 index 0000000000000000000000000000000000000000..6aff054646a3aaa93d94c11f0193d58461643a54 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/makefile.mc6 @@ -0,0 +1,249 @@ +# Makefile for Independent JPEG Group's software + +# This makefile is for Microsoft C for MS-DOS, version 6.00A and up. +# Use NMAKE, not Microsoft's brain-damaged MAKE. +# Thanks to Alan Wright and Chris Turner of Olivetti Research Ltd. + +# Read installation instructions before saying "nmake" !! + +# You may need to adjust these compiler options: +CFLAGS = -AM -Oecigt -Gs -W3 +# -AM medium memory model (or use -AS for small model, if you remove features) +# -Oecigt -Gs maximum safe optimisation (-Ol has bugs in MSC 6.00A) +# -W3 warning level 3 +# You might also want to add -G2 if you have an 80286, etc. +# Generally, we recommend defining any configuration symbols in jconfig.h, +# NOT via -D switches here. + +# Jan-Herman Buining suggests the following switches for MS C 8.0 and a 486: +# CFLAGS = /AM /f- /FPi87 /G3 /Gs /Gy /Ob1 /Oc /Oe /Og /Oi /Ol /On /Oo /Ot \ +# /OV4 /W3 +# except for jquant1.c, which must be compiled with /Oo- to avoid a compiler +# crash. + +# Ingar Steinsland suggests the following switches when building +# a 16-bit Windows DLL: +# CFLAGS = -ALw -Gsw -Zpe -W3 -O2 -Zi -Zd + +# Put here the object file name for the correct system-dependent memory +# manager file. For DOS, we recommend jmemdos.c and jmemdosa.asm. +# (But not for Windows; see install.doc if you use this makefile for Windows.) +SYSDEPMEM= jmemdos.obj jmemdosa.obj +# SYSDEPMEMLIB must list the same files with "+" signs for the librarian. +SYSDEPMEMLIB= +jmemdos.obj +jmemdosa.obj + +# End of configurable options. + + +# source files: JPEG library proper +LIBSOURCES= jcapimin.c jcapistd.c jccoefct.c jccolor.c jcdctmgr.c jchuff.c \ + jcinit.c jcmainct.c jcmarker.c jcmaster.c jcomapi.c jcparam.c \ + jcphuff.c jcprepct.c jcsample.c jctrans.c jdapimin.c jdapistd.c \ + jdatadst.c jdatasrc.c jdcoefct.c jdcolor.c jddctmgr.c jdhuff.c \ + jdinput.c jdmainct.c jdmarker.c jdmaster.c jdmerge.c jdphuff.c \ + jdpostct.c jdsample.c jdtrans.c jerror.c jfdctflt.c jfdctfst.c \ + jfdctint.c jidctflt.c jidctfst.c jidctint.c jidctred.c jquant1.c \ + jquant2.c jutils.c jmemmgr.c +# memmgr back ends: compile only one of these into a working library +SYSDEPSOURCES= jmemansi.c jmemname.c jmemnobs.c jmemdos.c jmemmac.c +# source files: cjpeg/djpeg/jpegtran applications, also rdjpgcom/wrjpgcom +APPSOURCES= cjpeg.c djpeg.c jpegtran.c rdjpgcom.c wrjpgcom.c cdjpeg.c \ + rdcolmap.c rdswitch.c transupp.c rdppm.c wrppm.c rdgif.c wrgif.c \ + rdtarga.c wrtarga.c rdbmp.c wrbmp.c rdrle.c wrrle.c +SOURCES= $(LIBSOURCES) $(SYSDEPSOURCES) $(APPSOURCES) +# files included by source files +INCLUDES= jchuff.h jdhuff.h jdct.h jerror.h jinclude.h jmemsys.h jmorecfg.h \ + jpegint.h jpeglib.h jversion.h cdjpeg.h cderror.h transupp.h +# documentation, test, and support files +DOCS= README install.doc usage.doc cjpeg.1 djpeg.1 jpegtran.1 rdjpgcom.1 \ + wrjpgcom.1 wizard.doc example.c libjpeg.doc structure.doc \ + coderules.doc filelist.doc change.log +MKFILES= configure makefile.cfg makefile.ansi makefile.unix makefile.bcc \ + makefile.mc6 makefile.dj makefile.wat makefile.vc makelib.ds \ + makeapps.ds makeproj.mac makcjpeg.st makdjpeg.st makljpeg.st \ + maktjpeg.st makefile.manx makefile.sas makefile.mms makefile.vms \ + makvms.opt +CONFIGFILES= jconfig.cfg jconfig.bcc jconfig.mc6 jconfig.dj jconfig.wat \ + jconfig.vc jconfig.mac jconfig.st jconfig.manx jconfig.sas \ + jconfig.vms +CONFIGUREFILES= config.guess config.sub install-sh ltconfig ltmain.sh +OTHERFILES= jconfig.doc ckconfig.c ansi2knr.c ansi2knr.1 jmemdosa.asm +TESTFILES= testorig.jpg testimg.ppm testimg.bmp testimg.jpg testprog.jpg \ + testimgp.jpg +DISTFILES= $(DOCS) $(MKFILES) $(CONFIGFILES) $(SOURCES) $(INCLUDES) \ + $(CONFIGUREFILES) $(OTHERFILES) $(TESTFILES) +# library object files common to compression and decompression +COMOBJECTS= jcomapi.obj jutils.obj jerror.obj jmemmgr.obj $(SYSDEPMEM) +# compression library object files +CLIBOBJECTS= jcapimin.obj jcapistd.obj jctrans.obj jcparam.obj jdatadst.obj \ + jcinit.obj jcmaster.obj jcmarker.obj jcmainct.obj jcprepct.obj \ + jccoefct.obj jccolor.obj jcsample.obj jchuff.obj jcphuff.obj \ + jcdctmgr.obj jfdctfst.obj jfdctflt.obj jfdctint.obj +# decompression library object files +DLIBOBJECTS= jdapimin.obj jdapistd.obj jdtrans.obj jdatasrc.obj \ + jdmaster.obj jdinput.obj jdmarker.obj jdhuff.obj jdphuff.obj \ + jdmainct.obj jdcoefct.obj jdpostct.obj jddctmgr.obj jidctfst.obj \ + jidctflt.obj jidctint.obj jidctred.obj jdsample.obj jdcolor.obj \ + jquant1.obj jquant2.obj jdmerge.obj +# These objectfiles are included in libjpeg.lib +LIBOBJECTS= $(CLIBOBJECTS) $(DLIBOBJECTS) $(COMOBJECTS) +# object files for sample applications (excluding library files) +COBJECTS= cjpeg.obj rdppm.obj rdgif.obj rdtarga.obj rdrle.obj rdbmp.obj \ + rdswitch.obj cdjpeg.obj +DOBJECTS= djpeg.obj wrppm.obj wrgif.obj wrtarga.obj wrrle.obj wrbmp.obj \ + rdcolmap.obj cdjpeg.obj +TROBJECTS= jpegtran.obj rdswitch.obj cdjpeg.obj transupp.obj + +# need linker response file because file list > 128 chars +RFILE = libjpeg.ans + + +all: libjpeg.lib cjpeg.exe djpeg.exe jpegtran.exe rdjpgcom.exe wrjpgcom.exe + +libjpeg.lib: $(LIBOBJECTS) $(RFILE) + del libjpeg.lib + lib @$(RFILE) + +# linker response file for building libjpeg.lib +$(RFILE) : makefile + del $(RFILE) + echo libjpeg.lib >$(RFILE) +# silly want-to-create-it prompt: + echo y >>$(RFILE) + echo +jcapimin.obj +jcapistd.obj +jctrans.obj +jcparam.obj & >>$(RFILE) + echo +jdatadst.obj +jcinit.obj +jcmaster.obj +jcmarker.obj & >>$(RFILE) + echo +jcmainct.obj +jcprepct.obj +jccoefct.obj & >>$(RFILE) + echo +jccolor.obj +jcsample.obj +jchuff.obj +jcphuff.obj & >>$(RFILE) + echo +jcdctmgr.obj +jfdctfst.obj +jfdctflt.obj & >>$(RFILE) + echo +jfdctint.obj +jdapimin.obj +jdapistd.obj & >>$(RFILE) + echo +jdtrans.obj +jdatasrc.obj +jdmaster.obj +jdinput.obj & >>$(RFILE) + echo +jdmarker.obj +jdhuff.obj +jdphuff.obj +jdmainct.obj & >>$(RFILE) + echo +jdcoefct.obj +jdpostct.obj +jddctmgr.obj & >>$(RFILE) + echo +jidctfst.obj +jidctflt.obj +jidctint.obj & >>$(RFILE) + echo +jidctred.obj +jdsample.obj +jdcolor.obj +jquant1.obj & >>$(RFILE) + echo +jquant2.obj +jdmerge.obj +jcomapi.obj +jutils.obj & >>$(RFILE) + echo +jerror.obj +jmemmgr.obj & >>$(RFILE) + echo $(SYSDEPMEMLIB) ; >>$(RFILE) + +cjpeg.exe: $(COBJECTS) libjpeg.lib + echo $(COBJECTS) >cjpeg.lst + link /STACK:4096 /EXEPACK @cjpeg.lst, cjpeg.exe, , libjpeg.lib, ; + del cjpeg.lst + +djpeg.exe: $(DOBJECTS) libjpeg.lib + echo $(DOBJECTS) >djpeg.lst + link /STACK:4096 /EXEPACK @djpeg.lst, djpeg.exe, , libjpeg.lib, ; + del djpeg.lst + +jpegtran.exe: $(TROBJECTS) libjpeg.lib + link /STACK:4096 /EXEPACK $(TROBJECTS), jpegtran.exe, , libjpeg.lib, ; + +rdjpgcom.exe: rdjpgcom.c + $(CC) -AS -O -W3 rdjpgcom.c + +# wrjpgcom needs large model so it can malloc a 64K chunk +wrjpgcom.exe: wrjpgcom.c + $(CC) -AL -O -W3 wrjpgcom.c + +jconfig.h: jconfig.doc + echo You must prepare a system-dependent jconfig.h file. + echo Please read the installation directions in install.doc. + exit 1 + +clean: + del *.obj + del libjpeg.lib + del cjpeg.exe + del djpeg.exe + del jpegtran.exe + del rdjpgcom.exe + del wrjpgcom.exe + del testout*.* + +test: cjpeg.exe djpeg.exe jpegtran.exe + del testout*.* + djpeg -dct int -ppm -outfile testout.ppm testorig.jpg + djpeg -dct int -bmp -colors 256 -outfile testout.bmp testorig.jpg + cjpeg -dct int -outfile testout.jpg testimg.ppm + djpeg -dct int -ppm -outfile testoutp.ppm testprog.jpg + cjpeg -dct int -progressive -opt -outfile testoutp.jpg testimg.ppm + jpegtran -outfile testoutt.jpg testprog.jpg + fc /b testimg.ppm testout.ppm + fc /b testimg.bmp testout.bmp + fc /b testimg.jpg testout.jpg + fc /b testimg.ppm testoutp.ppm + fc /b testimgp.jpg testoutp.jpg + fc /b testorig.jpg testoutt.jpg + + +jcapimin.obj: jcapimin.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcapistd.obj: jcapistd.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jccoefct.obj: jccoefct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jccolor.obj: jccolor.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcdctmgr.obj: jcdctmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jchuff.obj: jchuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jchuff.h +jcinit.obj: jcinit.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcmainct.obj: jcmainct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcmarker.obj: jcmarker.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcmaster.obj: jcmaster.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcomapi.obj: jcomapi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcparam.obj: jcparam.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcphuff.obj: jcphuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jchuff.h +jcprepct.obj: jcprepct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcsample.obj: jcsample.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jctrans.obj: jctrans.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdapimin.obj: jdapimin.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdapistd.obj: jdapistd.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdatadst.obj: jdatadst.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h +jdatasrc.obj: jdatasrc.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h +jdcoefct.obj: jdcoefct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdcolor.obj: jdcolor.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jddctmgr.obj: jddctmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jdhuff.obj: jdhuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdhuff.h +jdinput.obj: jdinput.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdmainct.obj: jdmainct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdmarker.obj: jdmarker.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdmaster.obj: jdmaster.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdmerge.obj: jdmerge.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdphuff.obj: jdphuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdhuff.h +jdpostct.obj: jdpostct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdsample.obj: jdsample.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdtrans.obj: jdtrans.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jerror.obj: jerror.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jversion.h jerror.h +jfdctflt.obj: jfdctflt.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jfdctfst.obj: jfdctfst.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jfdctint.obj: jfdctint.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jidctflt.obj: jidctflt.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jidctfst.obj: jidctfst.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jidctint.obj: jidctint.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jidctred.obj: jidctred.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jquant1.obj: jquant1.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jquant2.obj: jquant2.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jutils.obj: jutils.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jmemmgr.obj: jmemmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +jmemansi.obj: jmemansi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +jmemname.obj: jmemname.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +jmemnobs.obj: jmemnobs.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +jmemdos.obj: jmemdos.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +jmemmac.obj: jmemmac.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +cjpeg.obj: cjpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h jversion.h +djpeg.obj: djpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h jversion.h +jpegtran.obj: jpegtran.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h transupp.h jversion.h +rdjpgcom.obj: rdjpgcom.c jinclude.h jconfig.h +wrjpgcom.obj: wrjpgcom.c jinclude.h jconfig.h +cdjpeg.obj: cdjpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdcolmap.obj: rdcolmap.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdswitch.obj: rdswitch.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +transupp.obj: transupp.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h transupp.h +rdppm.obj: rdppm.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +wrppm.obj: wrppm.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdgif.obj: rdgif.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +wrgif.obj: wrgif.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdtarga.obj: rdtarga.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +wrtarga.obj: wrtarga.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdbmp.obj: rdbmp.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +wrbmp.obj: wrbmp.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdrle.obj: rdrle.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +wrrle.obj: wrrle.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +jmemdosa.obj : jmemdosa.asm + masm /mx $*; diff --git a/lc-continuity/mk4/modimage/jpeg-6b/makefile.mms b/lc-continuity/mk4/modimage/jpeg-6b/makefile.mms new file mode 100644 index 0000000000000000000000000000000000000000..cf130e5b9f33058eae3f84ba380fd596d6afdeeb --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/makefile.mms @@ -0,0 +1,218 @@ +# Makefile for Independent JPEG Group's software + +# This makefile is for use with MMS on Digital VMS systems. +# Thanks to Rick Dyson (dyson@iowasp.physics.uiowa.edu) +# and Tim Bell (tbell@netcom.com) for their help. + +# Read installation instructions before saying "MMS" !! + +# You may need to adjust these cc options: +CFLAGS= $(CFLAGS) /NoDebug /Optimize +# Generally, we recommend defining any configuration symbols in jconfig.h, +# NOT via /Define switches here. +.ifdef ALPHA +OPT= +.else +OPT= ,Sys$Disk:[]MAKVMS.OPT/Option +.endif + +# Put here the object file name for the correct system-dependent memory +# manager file. For Unix this is usually jmemnobs.o, but you may want +# to use jmemansi.o or jmemname.o if you have limited swap space. +SYSDEPMEM= jmemnobs.obj + +# End of configurable options. + + +# source files: JPEG library proper +LIBSOURCES= jcapimin.c jcapistd.c jccoefct.c jccolor.c jcdctmgr.c jchuff.c \ + jcinit.c jcmainct.c jcmarker.c jcmaster.c jcomapi.c jcparam.c \ + jcphuff.c jcprepct.c jcsample.c jctrans.c jdapimin.c jdapistd.c \ + jdatadst.c jdatasrc.c jdcoefct.c jdcolor.c jddctmgr.c jdhuff.c \ + jdinput.c jdmainct.c jdmarker.c jdmaster.c jdmerge.c jdphuff.c \ + jdpostct.c jdsample.c jdtrans.c jerror.c jfdctflt.c jfdctfst.c \ + jfdctint.c jidctflt.c jidctfst.c jidctint.c jidctred.c jquant1.c \ + jquant2.c jutils.c jmemmgr.c +# memmgr back ends: compile only one of these into a working library +SYSDEPSOURCES= jmemansi.c jmemname.c jmemnobs.c jmemdos.c jmemmac.c +# source files: cjpeg/djpeg/jpegtran applications, also rdjpgcom/wrjpgcom +APPSOURCES= cjpeg.c djpeg.c jpegtran.c rdjpgcom.c wrjpgcom.c cdjpeg.c \ + rdcolmap.c rdswitch.c transupp.c rdppm.c wrppm.c rdgif.c wrgif.c \ + rdtarga.c wrtarga.c rdbmp.c wrbmp.c rdrle.c wrrle.c +SOURCES= $(LIBSOURCES) $(SYSDEPSOURCES) $(APPSOURCES) +# files included by source files +INCLUDES= jchuff.h jdhuff.h jdct.h jerror.h jinclude.h jmemsys.h jmorecfg.h \ + jpegint.h jpeglib.h jversion.h cdjpeg.h cderror.h transupp.h +# documentation, test, and support files +DOCS= README install.doc usage.doc cjpeg.1 djpeg.1 jpegtran.1 rdjpgcom.1 \ + wrjpgcom.1 wizard.doc example.c libjpeg.doc structure.doc \ + coderules.doc filelist.doc change.log +MKFILES= configure makefile.cfg makefile.ansi makefile.unix makefile.bcc \ + makefile.mc6 makefile.dj makefile.wat makefile.vc makelib.ds \ + makeapps.ds makeproj.mac makcjpeg.st makdjpeg.st makljpeg.st \ + maktjpeg.st makefile.manx makefile.sas makefile.mms makefile.vms \ + makvms.opt +CONFIGFILES= jconfig.cfg jconfig.bcc jconfig.mc6 jconfig.dj jconfig.wat \ + jconfig.vc jconfig.mac jconfig.st jconfig.manx jconfig.sas \ + jconfig.vms +CONFIGUREFILES= config.guess config.sub install-sh ltconfig ltmain.sh +OTHERFILES= jconfig.doc ckconfig.c ansi2knr.c ansi2knr.1 jmemdosa.asm +TESTFILES= testorig.jpg testimg.ppm testimg.bmp testimg.jpg testprog.jpg \ + testimgp.jpg +DISTFILES= $(DOCS) $(MKFILES) $(CONFIGFILES) $(SOURCES) $(INCLUDES) \ + $(CONFIGUREFILES) $(OTHERFILES) $(TESTFILES) +# library object files common to compression and decompression +COMOBJECTS= jcomapi.obj jutils.obj jerror.obj jmemmgr.obj $(SYSDEPMEM) +# compression library object files +CLIBOBJECTS= jcapimin.obj jcapistd.obj jctrans.obj jcparam.obj jdatadst.obj \ + jcinit.obj jcmaster.obj jcmarker.obj jcmainct.obj jcprepct.obj \ + jccoefct.obj jccolor.obj jcsample.obj jchuff.obj jcphuff.obj \ + jcdctmgr.obj jfdctfst.obj jfdctflt.obj jfdctint.obj +# decompression library object files +DLIBOBJECTS= jdapimin.obj jdapistd.obj jdtrans.obj jdatasrc.obj \ + jdmaster.obj jdinput.obj jdmarker.obj jdhuff.obj jdphuff.obj \ + jdmainct.obj jdcoefct.obj jdpostct.obj jddctmgr.obj jidctfst.obj \ + jidctflt.obj jidctint.obj jidctred.obj jdsample.obj jdcolor.obj \ + jquant1.obj jquant2.obj jdmerge.obj +# These objectfiles are included in libjpeg.olb +LIBOBJECTS= $(CLIBOBJECTS) $(DLIBOBJECTS) $(COMOBJECTS) +# object files for sample applications (excluding library files) +COBJECTS= cjpeg.obj rdppm.obj rdgif.obj rdtarga.obj rdrle.obj rdbmp.obj \ + rdswitch.obj cdjpeg.obj +DOBJECTS= djpeg.obj wrppm.obj wrgif.obj wrtarga.obj wrrle.obj wrbmp.obj \ + rdcolmap.obj cdjpeg.obj +TROBJECTS= jpegtran.obj rdswitch.obj cdjpeg.obj transupp.obj +# objectfile lists with commas --- what a crock +COBJLIST= cjpeg.obj,rdppm.obj,rdgif.obj,rdtarga.obj,rdrle.obj,rdbmp.obj,\ + rdswitch.obj,cdjpeg.obj +DOBJLIST= djpeg.obj,wrppm.obj,wrgif.obj,wrtarga.obj,wrrle.obj,wrbmp.obj,\ + rdcolmap.obj,cdjpeg.obj +TROBJLIST= jpegtran.obj,rdswitch.obj,cdjpeg.obj,transupp.obj +LIBOBJLIST= jcapimin.obj,jcapistd.obj,jctrans.obj,jcparam.obj,jdatadst.obj,\ + jcinit.obj,jcmaster.obj,jcmarker.obj,jcmainct.obj,jcprepct.obj,\ + jccoefct.obj,jccolor.obj,jcsample.obj,jchuff.obj,jcphuff.obj,\ + jcdctmgr.obj,jfdctfst.obj,jfdctflt.obj,jfdctint.obj,jdapimin.obj,\ + jdapistd.obj,jdtrans.obj,jdatasrc.obj,jdmaster.obj,jdinput.obj,\ + jdmarker.obj,jdhuff.obj,jdphuff.obj,jdmainct.obj,jdcoefct.obj,\ + jdpostct.obj,jddctmgr.obj,jidctfst.obj,jidctflt.obj,jidctint.obj,\ + jidctred.obj,jdsample.obj,jdcolor.obj,jquant1.obj,jquant2.obj,\ + jdmerge.obj,jcomapi.obj,jutils.obj,jerror.obj,jmemmgr.obj,$(SYSDEPMEM) + + +.first + @- Define /NoLog Sys Sys$Library + +ALL : libjpeg.olb cjpeg.exe djpeg.exe jpegtran.exe rdjpgcom.exe wrjpgcom.exe + @ Continue + +libjpeg.olb : $(LIBOBJECTS) + Library /Create libjpeg.olb $(LIBOBJLIST) + +cjpeg.exe : $(COBJECTS) libjpeg.olb + $(LINK) $(LFLAGS) /Executable = cjpeg.exe $(COBJLIST),libjpeg.olb/Library$(OPT) + +djpeg.exe : $(DOBJECTS) libjpeg.olb + $(LINK) $(LFLAGS) /Executable = djpeg.exe $(DOBJLIST),libjpeg.olb/Library$(OPT) + +jpegtran.exe : $(TROBJECTS) libjpeg.olb + $(LINK) $(LFLAGS) /Executable = jpegtran.exe $(TROBJLIST),libjpeg.olb/Library$(OPT) + +rdjpgcom.exe : rdjpgcom.obj + $(LINK) $(LFLAGS) /Executable = rdjpgcom.exe rdjpgcom.obj$(OPT) + +wrjpgcom.exe : wrjpgcom.obj + $(LINK) $(LFLAGS) /Executable = wrjpgcom.exe wrjpgcom.obj$(OPT) + +jconfig.h : jconfig.vms + @- Copy jconfig.vms jconfig.h + +clean : + @- Set Protection = Owner:RWED *.*;-1 + @- Set Protection = Owner:RWED *.OBJ + - Purge /NoLog /NoConfirm *.* + - Delete /NoLog /NoConfirm *.OBJ; + +test : cjpeg.exe djpeg.exe jpegtran.exe + mcr sys$disk:[]djpeg -dct int -ppm -outfile testout.ppm testorig.jpg + mcr sys$disk:[]djpeg -dct int -bmp -colors 256 -outfile testout.bmp testorig.jpg + mcr sys$disk:[]cjpeg -dct int -outfile testout.jpg testimg.ppm + mcr sys$disk:[]djpeg -dct int -ppm -outfile testoutp.ppm testprog.jpg + mcr sys$disk:[]cjpeg -dct int -progressive -opt -outfile testoutp.jpg testimg.ppm + mcr sys$disk:[]jpegtran -outfile testoutt.jpg testprog.jpg + - Backup /Compare/Log testimg.ppm testout.ppm + - Backup /Compare/Log testimg.bmp testout.bmp + - Backup /Compare/Log testimg.jpg testout.jpg + - Backup /Compare/Log testimg.ppm testoutp.ppm + - Backup /Compare/Log testimgp.jpg testoutp.jpg + - Backup /Compare/Log testorig.jpg testoutt.jpg + + +jcapimin.obj : jcapimin.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcapistd.obj : jcapistd.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jccoefct.obj : jccoefct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jccolor.obj : jccolor.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcdctmgr.obj : jcdctmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jchuff.obj : jchuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jchuff.h +jcinit.obj : jcinit.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcmainct.obj : jcmainct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcmarker.obj : jcmarker.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcmaster.obj : jcmaster.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcomapi.obj : jcomapi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcparam.obj : jcparam.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcphuff.obj : jcphuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jchuff.h +jcprepct.obj : jcprepct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcsample.obj : jcsample.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jctrans.obj : jctrans.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdapimin.obj : jdapimin.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdapistd.obj : jdapistd.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdatadst.obj : jdatadst.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h +jdatasrc.obj : jdatasrc.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h +jdcoefct.obj : jdcoefct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdcolor.obj : jdcolor.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jddctmgr.obj : jddctmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jdhuff.obj : jdhuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdhuff.h +jdinput.obj : jdinput.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdmainct.obj : jdmainct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdmarker.obj : jdmarker.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdmaster.obj : jdmaster.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdmerge.obj : jdmerge.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdphuff.obj : jdphuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdhuff.h +jdpostct.obj : jdpostct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdsample.obj : jdsample.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdtrans.obj : jdtrans.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jerror.obj : jerror.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jversion.h jerror.h +jfdctflt.obj : jfdctflt.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jfdctfst.obj : jfdctfst.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jfdctint.obj : jfdctint.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jidctflt.obj : jidctflt.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jidctfst.obj : jidctfst.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jidctint.obj : jidctint.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jidctred.obj : jidctred.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jquant1.obj : jquant1.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jquant2.obj : jquant2.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jutils.obj : jutils.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jmemmgr.obj : jmemmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +jmemansi.obj : jmemansi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +jmemname.obj : jmemname.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +jmemnobs.obj : jmemnobs.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +jmemdos.obj : jmemdos.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +jmemmac.obj : jmemmac.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +cjpeg.obj : cjpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h jversion.h +djpeg.obj : djpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h jversion.h +jpegtran.obj : jpegtran.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h transupp.h jversion.h +rdjpgcom.obj : rdjpgcom.c jinclude.h jconfig.h +wrjpgcom.obj : wrjpgcom.c jinclude.h jconfig.h +cdjpeg.obj : cdjpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdcolmap.obj : rdcolmap.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdswitch.obj : rdswitch.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +transupp.obj : transupp.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h transupp.h +rdppm.obj : rdppm.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +wrppm.obj : wrppm.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdgif.obj : rdgif.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +wrgif.obj : wrgif.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdtarga.obj : rdtarga.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +wrtarga.obj : wrtarga.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdbmp.obj : rdbmp.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +wrbmp.obj : wrbmp.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdrle.obj : rdrle.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +wrrle.obj : wrrle.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h diff --git a/lc-continuity/mk4/modimage/jpeg-6b/makefile.sas b/lc-continuity/mk4/modimage/jpeg-6b/makefile.sas new file mode 100644 index 0000000000000000000000000000000000000000..f296faf069d701dac8f4eeb486754a008e9a71d0 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/makefile.sas @@ -0,0 +1,252 @@ +# Makefile for Independent JPEG Group's software + +# This makefile is for Amiga systems using SAS C 6.0 and up. +# Thanks to Ed Hanway, Mark Rinfret, and Jim Zepeda. + +# Read installation instructions before saying "make" !! + +# The name of your C compiler: +CC= sc + +# You may need to adjust these cc options: +# Uncomment the following lines for generic 680x0 version +ARCHFLAGS= cpu=any +SUFFIX= + +# Uncomment the following lines for 68030-only version +#ARCHFLAGS= cpu=68030 +#SUFFIX=.030 + +CFLAGS= nostackcheck data=near parms=register optimize $(ARCHFLAGS) \ + ignore=104 ignore=304 ignore=306 +# ignore=104 disables warnings for mismatched const qualifiers +# ignore=304 disables warnings for variables being optimized out +# ignore=306 disables warnings for the inlining of functions +# Generally, we recommend defining any configuration symbols in jconfig.h, +# NOT via define switches here. + +# Link-time cc options: +LDFLAGS= SC SD ND BATCH + +# To link any special libraries, add the necessary commands here. +LDLIBS= LIB:scm.lib LIB:sc.lib + +# Put here the object file name for the correct system-dependent memory +# manager file. For Amiga we recommend jmemname.o. +SYSDEPMEM= jmemname.o + +# miscellaneous OS-dependent stuff +# linker +LN= slink +# file deletion command +RM= delete quiet +# library (.lib) file creation command +AR= oml + +# End of configurable options. + + +# source files: JPEG library proper +LIBSOURCES= jcapimin.c jcapistd.c jccoefct.c jccolor.c jcdctmgr.c jchuff.c \ + jcinit.c jcmainct.c jcmarker.c jcmaster.c jcomapi.c jcparam.c \ + jcphuff.c jcprepct.c jcsample.c jctrans.c jdapimin.c jdapistd.c \ + jdatadst.c jdatasrc.c jdcoefct.c jdcolor.c jddctmgr.c jdhuff.c \ + jdinput.c jdmainct.c jdmarker.c jdmaster.c jdmerge.c jdphuff.c \ + jdpostct.c jdsample.c jdtrans.c jerror.c jfdctflt.c jfdctfst.c \ + jfdctint.c jidctflt.c jidctfst.c jidctint.c jidctred.c jquant1.c \ + jquant2.c jutils.c jmemmgr.c +# memmgr back ends: compile only one of these into a working library +SYSDEPSOURCES= jmemansi.c jmemname.c jmemnobs.c jmemdos.c jmemmac.c +# source files: cjpeg/djpeg/jpegtran applications, also rdjpgcom/wrjpgcom +APPSOURCES= cjpeg.c djpeg.c jpegtran.c rdjpgcom.c wrjpgcom.c cdjpeg.c \ + rdcolmap.c rdswitch.c transupp.c rdppm.c wrppm.c rdgif.c wrgif.c \ + rdtarga.c wrtarga.c rdbmp.c wrbmp.c rdrle.c wrrle.c +SOURCES= $(LIBSOURCES) $(SYSDEPSOURCES) $(APPSOURCES) +# files included by source files +INCLUDES= jchuff.h jdhuff.h jdct.h jerror.h jinclude.h jmemsys.h jmorecfg.h \ + jpegint.h jpeglib.h jversion.h cdjpeg.h cderror.h transupp.h +# documentation, test, and support files +DOCS= README install.doc usage.doc cjpeg.1 djpeg.1 jpegtran.1 rdjpgcom.1 \ + wrjpgcom.1 wizard.doc example.c libjpeg.doc structure.doc \ + coderules.doc filelist.doc change.log +MKFILES= configure makefile.cfg makefile.ansi makefile.unix makefile.bcc \ + makefile.mc6 makefile.dj makefile.wat makefile.vc makelib.ds \ + makeapps.ds makeproj.mac makcjpeg.st makdjpeg.st makljpeg.st \ + maktjpeg.st makefile.manx makefile.sas makefile.mms makefile.vms \ + makvms.opt +CONFIGFILES= jconfig.cfg jconfig.bcc jconfig.mc6 jconfig.dj jconfig.wat \ + jconfig.vc jconfig.mac jconfig.st jconfig.manx jconfig.sas \ + jconfig.vms +CONFIGUREFILES= config.guess config.sub install-sh ltconfig ltmain.sh +OTHERFILES= jconfig.doc ckconfig.c ansi2knr.c ansi2knr.1 jmemdosa.asm +TESTFILES= testorig.jpg testimg.ppm testimg.bmp testimg.jpg testprog.jpg \ + testimgp.jpg +DISTFILES= $(DOCS) $(MKFILES) $(CONFIGFILES) $(SOURCES) $(INCLUDES) \ + $(CONFIGUREFILES) $(OTHERFILES) $(TESTFILES) +# library object files common to compression and decompression +COMOBJECTS= jcomapi.o jutils.o jerror.o jmemmgr.o $(SYSDEPMEM) +# compression library object files +CLIBOBJECTS= jcapimin.o jcapistd.o jctrans.o jcparam.o jdatadst.o jcinit.o \ + jcmaster.o jcmarker.o jcmainct.o jcprepct.o jccoefct.o jccolor.o \ + jcsample.o jchuff.o jcphuff.o jcdctmgr.o jfdctfst.o jfdctflt.o \ + jfdctint.o +# decompression library object files +DLIBOBJECTS= jdapimin.o jdapistd.o jdtrans.o jdatasrc.o jdmaster.o \ + jdinput.o jdmarker.o jdhuff.o jdphuff.o jdmainct.o jdcoefct.o \ + jdpostct.o jddctmgr.o jidctfst.o jidctflt.o jidctint.o jidctred.o \ + jdsample.o jdcolor.o jquant1.o jquant2.o jdmerge.o +# These objectfiles are included in libjpeg.lib +LIBOBJECTS= $(CLIBOBJECTS) $(DLIBOBJECTS) $(COMOBJECTS) +# object files for sample applications (excluding library files) +COBJECTS= cjpeg.o rdppm.o rdgif.o rdtarga.o rdrle.o rdbmp.o rdswitch.o \ + cdjpeg.o +DOBJECTS= djpeg.o wrppm.o wrgif.o wrtarga.o wrrle.o wrbmp.o rdcolmap.o \ + cdjpeg.o +TROBJECTS= jpegtran.o rdswitch.o cdjpeg.o transupp.o + + +all: libjpeg.lib cjpeg$(SUFFIX) djpeg$(SUFFIX) jpegtran$(SUFFIX) rdjpgcom$(SUFFIX) wrjpgcom$(SUFFIX) + +# note: do several AR steps to avoid command line length limitations + +libjpeg.lib: $(LIBOBJECTS) + -$(RM) libjpeg.lib + $(AR) libjpeg.lib r $(CLIBOBJECTS) + $(AR) libjpeg.lib r $(DLIBOBJECTS) + $(AR) libjpeg.lib r $(COMOBJECTS) + +cjpeg$(SUFFIX): $(COBJECTS) libjpeg.lib + $(LN) + +# You may want to adjust these compiler options: +CFLAGS= $(cflags) $(cdebug) $(cvars) -I. +# Generally, we recommend defining any configuration symbols in jconfig.h, +# NOT via -D switches here. + +# Link-time options: +LDFLAGS= $(ldebug) $(conlflags) + +# To link any special libraries, add the necessary commands here. +LDLIBS= $(conlibs) + +# Put here the object file name for the correct system-dependent memory +# manager file. For NT we suggest jmemnobs.obj, which expects the OS to +# provide adequate virtual memory. +SYSDEPMEM= jmemnobs.obj + +# miscellaneous OS-dependent stuff +# file deletion command +RM= del + +# End of configurable options. + + +# source files: JPEG library proper +LIBSOURCES= jcapimin.c jcapistd.c jccoefct.c jccolor.c jcdctmgr.c jchuff.c \ + jcinit.c jcmainct.c jcmarker.c jcmaster.c jcomapi.c jcparam.c \ + jcphuff.c jcprepct.c jcsample.c jctrans.c jdapimin.c jdapistd.c \ + jdatadst.c jdatasrc.c jdcoefct.c jdcolor.c jddctmgr.c jdhuff.c \ + jdinput.c jdmainct.c jdmarker.c jdmaster.c jdmerge.c jdphuff.c \ + jdpostct.c jdsample.c jdtrans.c jerror.c jfdctflt.c jfdctfst.c \ + jfdctint.c jidctflt.c jidctfst.c jidctint.c jidctred.c jquant1.c \ + jquant2.c jutils.c jmemmgr.c +# memmgr back ends: compile only one of these into a working library +SYSDEPSOURCES= jmemansi.c jmemname.c jmemnobs.c jmemdos.c jmemmac.c +# source files: cjpeg/djpeg/jpegtran applications, also rdjpgcom/wrjpgcom +APPSOURCES= cjpeg.c djpeg.c jpegtran.c rdjpgcom.c wrjpgcom.c cdjpeg.c \ + rdcolmap.c rdswitch.c transupp.c rdppm.c wrppm.c rdgif.c wrgif.c \ + rdtarga.c wrtarga.c rdbmp.c wrbmp.c rdrle.c wrrle.c +SOURCES= $(LIBSOURCES) $(SYSDEPSOURCES) $(APPSOURCES) +# files included by source files +INCLUDES= jchuff.h jdhuff.h jdct.h jerror.h jinclude.h jmemsys.h jmorecfg.h \ + jpegint.h jpeglib.h jversion.h cdjpeg.h cderror.h transupp.h +# documentation, test, and support files +DOCS= README install.doc usage.doc cjpeg.1 djpeg.1 jpegtran.1 rdjpgcom.1 \ + wrjpgcom.1 wizard.doc example.c libjpeg.doc structure.doc \ + coderules.doc filelist.doc change.log +MKFILES= configure makefile.cfg makefile.ansi makefile.unix makefile.bcc \ + makefile.mc6 makefile.dj makefile.wat makefile.vc makelib.ds \ + makeapps.ds makeproj.mac makcjpeg.st makdjpeg.st makljpeg.st \ + maktjpeg.st makefile.manx makefile.sas makefile.mms makefile.vms \ + makvms.opt +CONFIGFILES= jconfig.cfg jconfig.bcc jconfig.mc6 jconfig.dj jconfig.wat \ + jconfig.vc jconfig.mac jconfig.st jconfig.manx jconfig.sas \ + jconfig.vms +CONFIGUREFILES= config.guess config.sub install-sh ltconfig ltmain.sh +OTHERFILES= jconfig.doc ckconfig.c ansi2knr.c ansi2knr.1 jmemdosa.asm +TESTFILES= testorig.jpg testimg.ppm testimg.bmp testimg.jpg testprog.jpg \ + testimgp.jpg +DISTFILES= $(DOCS) $(MKFILES) $(CONFIGFILES) $(SOURCES) $(INCLUDES) \ + $(CONFIGUREFILES) $(OTHERFILES) $(TESTFILES) +# library object files common to compression and decompression +COMOBJECTS= jcomapi.obj jutils.obj jerror.obj jmemmgr.obj $(SYSDEPMEM) +# compression library object files +CLIBOBJECTS= jcapimin.obj jcapistd.obj jctrans.obj jcparam.obj jdatadst.obj \ + jcinit.obj jcmaster.obj jcmarker.obj jcmainct.obj jcprepct.obj \ + jccoefct.obj jccolor.obj jcsample.obj jchuff.obj jcphuff.obj \ + jcdctmgr.obj jfdctfst.obj jfdctflt.obj jfdctint.obj +# decompression library object files +DLIBOBJECTS= jdapimin.obj jdapistd.obj jdtrans.obj jdatasrc.obj \ + jdmaster.obj jdinput.obj jdmarker.obj jdhuff.obj jdphuff.obj \ + jdmainct.obj jdcoefct.obj jdpostct.obj jddctmgr.obj jidctfst.obj \ + jidctflt.obj jidctint.obj jidctred.obj jdsample.obj jdcolor.obj \ + jquant1.obj jquant2.obj jdmerge.obj +# These objectfiles are included in libjpeg.lib +LIBOBJECTS= $(CLIBOBJECTS) $(DLIBOBJECTS) $(COMOBJECTS) +# object files for sample applications (excluding library files) +COBJECTS= cjpeg.obj rdppm.obj rdgif.obj rdtarga.obj rdrle.obj rdbmp.obj \ + rdswitch.obj cdjpeg.obj +DOBJECTS= djpeg.obj wrppm.obj wrgif.obj wrtarga.obj wrrle.obj wrbmp.obj \ + rdcolmap.obj cdjpeg.obj +TROBJECTS= jpegtran.obj rdswitch.obj cdjpeg.obj transupp.obj + +# Template command for compiling .c to .obj +.c.obj: + $(cc) $(CFLAGS) $*.c + + +all: libjpeg.lib cjpeg.exe djpeg.exe jpegtran.exe rdjpgcom.exe wrjpgcom.exe + +libjpeg.lib: $(LIBOBJECTS) + $(RM) libjpeg.lib + lib -out:libjpeg.lib $(LIBOBJECTS) + +cjpeg.exe: $(COBJECTS) libjpeg.lib + $(link) $(LDFLAGS) -out:cjpeg.exe $(COBJECTS) libjpeg.lib $(LDLIBS) + +djpeg.exe: $(DOBJECTS) libjpeg.lib + $(link) $(LDFLAGS) -out:djpeg.exe $(DOBJECTS) libjpeg.lib $(LDLIBS) + +jpegtran.exe: $(TROBJECTS) libjpeg.lib + $(link) $(LDFLAGS) -out:jpegtran.exe $(TROBJECTS) libjpeg.lib $(LDLIBS) + +rdjpgcom.exe: rdjpgcom.obj + $(link) $(LDFLAGS) -out:rdjpgcom.exe rdjpgcom.obj $(LDLIBS) + +wrjpgcom.exe: wrjpgcom.obj + $(link) $(LDFLAGS) -out:wrjpgcom.exe wrjpgcom.obj $(LDLIBS) + + +clean: + $(RM) *.obj *.exe libjpeg.lib + $(RM) testout* + +test: cjpeg.exe djpeg.exe jpegtran.exe + $(RM) testout* + .\djpeg -dct int -ppm -outfile testout.ppm testorig.jpg + .\djpeg -dct int -bmp -colors 256 -outfile testout.bmp testorig.jpg + .\cjpeg -dct int -outfile testout.jpg testimg.ppm + .\djpeg -dct int -ppm -outfile testoutp.ppm testprog.jpg + .\cjpeg -dct int -progressive -opt -outfile testoutp.jpg testimg.ppm + .\jpegtran -outfile testoutt.jpg testprog.jpg + fc /b testimg.ppm testout.ppm + fc /b testimg.bmp testout.bmp + fc /b testimg.jpg testout.jpg + fc /b testimg.ppm testoutp.ppm + fc /b testimgp.jpg testoutp.jpg + fc /b testorig.jpg testoutt.jpg + + +jcapimin.obj: jcapimin.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcapistd.obj: jcapistd.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jccoefct.obj: jccoefct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jccolor.obj: jccolor.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcdctmgr.obj: jcdctmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jchuff.obj: jchuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jchuff.h +jcinit.obj: jcinit.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcmainct.obj: jcmainct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcmarker.obj: jcmarker.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcmaster.obj: jcmaster.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcomapi.obj: jcomapi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcparam.obj: jcparam.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcphuff.obj: jcphuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jchuff.h +jcprepct.obj: jcprepct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcsample.obj: jcsample.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jctrans.obj: jctrans.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdapimin.obj: jdapimin.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdapistd.obj: jdapistd.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdatadst.obj: jdatadst.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h +jdatasrc.obj: jdatasrc.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h +jdcoefct.obj: jdcoefct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdcolor.obj: jdcolor.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jddctmgr.obj: jddctmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jdhuff.obj: jdhuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdhuff.h +jdinput.obj: jdinput.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdmainct.obj: jdmainct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdmarker.obj: jdmarker.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdmaster.obj: jdmaster.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdmerge.obj: jdmerge.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdphuff.obj: jdphuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdhuff.h +jdpostct.obj: jdpostct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdsample.obj: jdsample.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdtrans.obj: jdtrans.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jerror.obj: jerror.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jversion.h jerror.h +jfdctflt.obj: jfdctflt.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jfdctfst.obj: jfdctfst.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jfdctint.obj: jfdctint.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jidctflt.obj: jidctflt.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jidctfst.obj: jidctfst.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jidctint.obj: jidctint.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jidctred.obj: jidctred.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jquant1.obj: jquant1.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jquant2.obj: jquant2.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jutils.obj: jutils.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jmemmgr.obj: jmemmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +jmemansi.obj: jmemansi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +jmemname.obj: jmemname.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +jmemnobs.obj: jmemnobs.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +jmemdos.obj: jmemdos.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +jmemmac.obj: jmemmac.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +cjpeg.obj: cjpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h jversion.h +djpeg.obj: djpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h jversion.h +jpegtran.obj: jpegtran.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h transupp.h jversion.h +rdjpgcom.obj: rdjpgcom.c jinclude.h jconfig.h +wrjpgcom.obj: wrjpgcom.c jinclude.h jconfig.h +cdjpeg.obj: cdjpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdcolmap.obj: rdcolmap.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdswitch.obj: rdswitch.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +transupp.obj: transupp.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h transupp.h +rdppm.obj: rdppm.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +wrppm.obj: wrppm.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdgif.obj: rdgif.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +wrgif.obj: wrgif.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdtarga.obj: rdtarga.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +wrtarga.obj: wrtarga.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdbmp.obj: rdbmp.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +wrbmp.obj: wrbmp.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdrle.obj: rdrle.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +wrrle.obj: wrrle.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h diff --git a/lc-continuity/mk4/modimage/jpeg-6b/makefile.vms b/lc-continuity/mk4/modimage/jpeg-6b/makefile.vms new file mode 100644 index 0000000000000000000000000000000000000000..a42358d05ca9a61a4f99d4211b0ee82359632219 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/makefile.vms @@ -0,0 +1,142 @@ +$! Makefile for Independent JPEG Group's software +$! +$! This is a command procedure for Digital VMS systems that do not have MMS. +$! It builds the JPEG software by brute force, recompiling everything whether +$! or not it is necessary. It then runs the basic self-test. +$! Thanks to Rick Dyson (dyson@iowasp.physics.uiowa.edu) +$! and Tim Bell (tbell@netcom.com) for their help. +$! +$! Read installation instructions before running this!! +$! +$ If F$Mode () .eqs. "INTERACTIVE" +$ Then +$ VERIFY = F$Verify (0) +$ Else +$ VERIFY = F$Verify (1) +$ EndIf +$ On Control_Y Then GoTo End +$ On Error Then GoTo End +$ +$ If F$GetSyi ("HW_MODEL") .gt. 1023 +$ Then +$ OPT = "" +$ Else +$ OPT = ",Sys$Disk:[]makvms.opt/Option" +$ EndIf +$ +$ DoCompile := CC /NoDebug /Optimize /NoList +$! +$ DoCompile jcapimin.c +$ DoCompile jcapistd.c +$ DoCompile jctrans.c +$ DoCompile jcparam.c +$ DoCompile jdatadst.c +$ DoCompile jcinit.c +$ DoCompile jcmaster.c +$ DoCompile jcmarker.c +$ DoCompile jcmainct.c +$ DoCompile jcprepct.c +$ DoCompile jccoefct.c +$ DoCompile jccolor.c +$ DoCompile jcsample.c +$ DoCompile jchuff.c +$ DoCompile jcphuff.c +$ DoCompile jcdctmgr.c +$ DoCompile jfdctfst.c +$ DoCompile jfdctflt.c +$ DoCompile jfdctint.c +$ DoCompile jdapimin.c +$ DoCompile jdapistd.c +$ DoCompile jdtrans.c +$ DoCompile jdatasrc.c +$ DoCompile jdmaster.c +$ DoCompile jdinput.c +$ DoCompile jdmarker.c +$ DoCompile jdhuff.c +$ DoCompile jdphuff.c +$ DoCompile jdmainct.c +$ DoCompile jdcoefct.c +$ DoCompile jdpostct.c +$ DoCompile jddctmgr.c +$ DoCompile jidctfst.c +$ DoCompile jidctflt.c +$ DoCompile jidctint.c +$ DoCompile jidctred.c +$ DoCompile jdsample.c +$ DoCompile jdcolor.c +$ DoCompile jquant1.c +$ DoCompile jquant2.c +$ DoCompile jdmerge.c +$ DoCompile jcomapi.c +$ DoCompile jutils.c +$ DoCompile jerror.c +$ DoCompile jmemmgr.c +$ DoCompile jmemnobs.c +$! +$ Library /Create libjpeg.olb jcapimin.obj,jcapistd.obj,jctrans.obj, - + jcparam.obj,jdatadst.obj,jcinit.obj,jcmaster.obj,jcmarker.obj, - + jcmainct.obj,jcprepct.obj,jccoefct.obj,jccolor.obj,jcsample.obj, - + jchuff.obj,jcphuff.obj,jcdctmgr.obj,jfdctfst.obj,jfdctflt.obj, - + jfdctint.obj,jdapimin.obj,jdapistd.obj,jdtrans.obj,jdatasrc.obj, - + jdmaster.obj,jdinput.obj,jdmarker.obj,jdhuff.obj,jdphuff.obj, - + jdmainct.obj,jdcoefct.obj,jdpostct.obj,jddctmgr.obj,jidctfst.obj, - + jidctflt.obj,jidctint.obj,jidctred.obj,jdsample.obj,jdcolor.obj, - + jquant1.obj,jquant2.obj,jdmerge.obj,jcomapi.obj,jutils.obj, - + jerror.obj,jmemmgr.obj,jmemnobs.obj +$! +$ DoCompile cjpeg.c +$ DoCompile rdppm.c +$ DoCompile rdgif.c +$ DoCompile rdtarga.c +$ DoCompile rdrle.c +$ DoCompile rdbmp.c +$ DoCompile rdswitch.c +$ DoCompile cdjpeg.c +$! +$ Link /NoMap /Executable = cjpeg.exe cjpeg.obj,rdppm.obj,rdgif.obj, - + rdtarga.obj,rdrle.obj,rdbmp.obj,rdswitch.obj,cdjpeg.obj,libjpeg.olb/Library'OPT' +$! +$ DoCompile djpeg.c +$ DoCompile wrppm.c +$ DoCompile wrgif.c +$ DoCompile wrtarga.c +$ DoCompile wrrle.c +$ DoCompile wrbmp.c +$ DoCompile rdcolmap.c +$ DoCompile cdjpeg.c +$! +$ Link /NoMap /Executable = djpeg.exe djpeg.obj,wrppm.obj,wrgif.obj, - + wrtarga.obj,wrrle.obj,wrbmp.obj,rdcolmap.obj,cdjpeg.obj,libjpeg.olb/Library'OPT' +$! +$ DoCompile jpegtran.c +$ DoCompile rdswitch.c +$ DoCompile cdjpeg.c +$ DoCompile transupp.c +$! +$ Link /NoMap /Executable = jpegtran.exe jpegtran.obj,rdswitch.obj, - + cdjpeg.obj,transupp.obj,libjpeg.olb/Library'OPT' +$! +$ DoCompile rdjpgcom.c +$ Link /NoMap /Executable = rdjpgcom.exe rdjpgcom.obj'OPT' +$! +$ DoCompile wrjpgcom.c +$ Link /NoMap /Executable = wrjpgcom.exe wrjpgcom.obj'OPT' +$! +$! Run the self-test +$! +$ mcr sys$disk:[]djpeg -dct int -ppm -outfile testout.ppm testorig.jpg +$ mcr sys$disk:[]djpeg -dct int -bmp -colors 256 -outfile testout.bmp testorig.jpg +$ mcr sys$disk:[]cjpeg -dct int -outfile testout.jpg testimg.ppm +$ mcr sys$disk:[]djpeg -dct int -ppm -outfile testoutp.ppm testprog.jpg +$ mcr sys$disk:[]cjpeg -dct int -progressive -opt -outfile testoutp.jpg testimg.ppm +$ mcr sys$disk:[]jpegtran -outfile testoutt.jpg testprog.jpg +$ Backup /Compare/Log testimg.ppm testout.ppm +$ Backup /Compare/Log testimg.bmp testout.bmp +$ Backup /Compare/Log testimg.jpg testout.jpg +$ Backup /Compare/Log testimg.ppm testoutp.ppm +$ Backup /Compare/Log testimgp.jpg testoutp.jpg +$ Backup /Compare/Log testorig.jpg testoutt.jpg +$! +$End: +$ If Verify Then Set Verify +$ Exit diff --git a/lc-continuity/mk4/modimage/jpeg-6b/makefile.wat b/lc-continuity/mk4/modimage/jpeg-6b/makefile.wat new file mode 100644 index 0000000000000000000000000000000000000000..d953e466f8c76d9f5dfa78b36d63c567604be088 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/makefile.wat @@ -0,0 +1,233 @@ +# Makefile for Independent JPEG Group's software + +# This makefile is suitable for Watcom C/C++ 10.0 on MS-DOS (using +# dos4g extender), OS/2, and Windows NT console mode. +# Thanks to Janos Haide, jhaide@btrvtech.com. + +# Read installation instructions before saying "wmake" !! + +# Uncomment line for desired system +SYSTEM=DOS +#SYSTEM=OS2 +#SYSTEM=NT + +# The name of your C compiler: +CC= wcl386 + +# You may need to adjust these cc options: +CFLAGS= -4r -ort -wx -zq -bt=$(SYSTEM) +# Caution: avoid -ol or -ox; these generate bad code with 10.0 or 10.0a. +# Generally, we recommend defining any configuration symbols in jconfig.h, +# NOT via -D switches here. + +# Link-time cc options: +!ifeq SYSTEM DOS +LDFLAGS= -zq -l=dos4g +!else ifeq SYSTEM OS2 +LDFLAGS= -zq -l=os2v2 +!else ifeq SYSTEM NT +LDFLAGS= -zq -l=nt +!endif + +# Put here the object file name for the correct system-dependent memory +# manager file. jmemnobs should work fine for dos4g or OS/2 environment. +SYSDEPMEM= jmemnobs.obj + +# End of configurable options. + + +# source files: JPEG library proper +LIBSOURCES= jcapimin.c jcapistd.c jccoefct.c jccolor.c jcdctmgr.c jchuff.c & + jcinit.c jcmainct.c jcmarker.c jcmaster.c jcomapi.c jcparam.c & + jcphuff.c jcprepct.c jcsample.c jctrans.c jdapimin.c jdapistd.c & + jdatadst.c jdatasrc.c jdcoefct.c jdcolor.c jddctmgr.c jdhuff.c & + jdinput.c jdmainct.c jdmarker.c jdmaster.c jdmerge.c jdphuff.c & + jdpostct.c jdsample.c jdtrans.c jerror.c jfdctflt.c jfdctfst.c & + jfdctint.c jidctflt.c jidctfst.c jidctint.c jidctred.c jquant1.c & + jquant2.c jutils.c jmemmgr.c +# memmgr back ends: compile only one of these into a working library +SYSDEPSOURCES= jmemansi.c jmemname.c jmemnobs.c jmemdos.c jmemmac.c +# source files: cjpeg/djpeg/jpegtran applications, also rdjpgcom/wrjpgcom +APPSOURCES= cjpeg.c djpeg.c jpegtran.c rdjpgcom.c wrjpgcom.c cdjpeg.c & + rdcolmap.c rdswitch.c transupp.c rdppm.c wrppm.c rdgif.c wrgif.c & + rdtarga.c wrtarga.c rdbmp.c wrbmp.c rdrle.c wrrle.c +SOURCES= $(LIBSOURCES) $(SYSDEPSOURCES) $(APPSOURCES) +# files included by source files +INCLUDES= jchuff.h jdhuff.h jdct.h jerror.h jinclude.h jmemsys.h jmorecfg.h & + jpegint.h jpeglib.h jversion.h cdjpeg.h cderror.h transupp.h +# documentation, test, and support files +DOCS= README install.doc usage.doc cjpeg.1 djpeg.1 jpegtran.1 rdjpgcom.1 & + wrjpgcom.1 wizard.doc example.c libjpeg.doc structure.doc & + coderules.doc filelist.doc change.log +MKFILES= configure makefile.cfg makefile.ansi makefile.unix makefile.bcc & + makefile.mc6 makefile.dj makefile.wat makefile.vc makelib.ds & + makeapps.ds makeproj.mac makcjpeg.st makdjpeg.st makljpeg.st & + maktjpeg.st makefile.manx makefile.sas makefile.mms makefile.vms & + makvms.opt +CONFIGFILES= jconfig.cfg jconfig.bcc jconfig.mc6 jconfig.dj jconfig.wat & + jconfig.vc jconfig.mac jconfig.st jconfig.manx jconfig.sas & + jconfig.vms +CONFIGUREFILES= config.guess config.sub install-sh ltconfig ltmain.sh +OTHERFILES= jconfig.doc ckconfig.c ansi2knr.c ansi2knr.1 jmemdosa.asm +TESTFILES= testorig.jpg testimg.ppm testimg.bmp testimg.jpg testprog.jpg & + testimgp.jpg +DISTFILES= $(DOCS) $(MKFILES) $(CONFIGFILES) $(SOURCES) $(INCLUDES) & + $(CONFIGUREFILES) $(OTHERFILES) $(TESTFILES) +# library object files common to compression and decompression +COMOBJECTS= jcomapi.obj jutils.obj jerror.obj jmemmgr.obj $(SYSDEPMEM) +# compression library object files +CLIBOBJECTS= jcapimin.obj jcapistd.obj jctrans.obj jcparam.obj jdatadst.obj & + jcinit.obj jcmaster.obj jcmarker.obj jcmainct.obj jcprepct.obj & + jccoefct.obj jccolor.obj jcsample.obj jchuff.obj jcphuff.obj & + jcdctmgr.obj jfdctfst.obj jfdctflt.obj jfdctint.obj +# decompression library object files +DLIBOBJECTS= jdapimin.obj jdapistd.obj jdtrans.obj jdatasrc.obj & + jdmaster.obj jdinput.obj jdmarker.obj jdhuff.obj jdphuff.obj & + jdmainct.obj jdcoefct.obj jdpostct.obj jddctmgr.obj jidctfst.obj & + jidctflt.obj jidctint.obj jidctred.obj jdsample.obj jdcolor.obj & + jquant1.obj jquant2.obj jdmerge.obj +# These objectfiles are included in libjpeg.lib +LIBOBJECTS= $(CLIBOBJECTS) $(DLIBOBJECTS) $(COMOBJECTS) +# object files for sample applications (excluding library files) +COBJECTS= cjpeg.obj rdppm.obj rdgif.obj rdtarga.obj rdrle.obj rdbmp.obj & + rdswitch.obj cdjpeg.obj +DOBJECTS= djpeg.obj wrppm.obj wrgif.obj wrtarga.obj wrrle.obj wrbmp.obj & + rdcolmap.obj cdjpeg.obj +TROBJECTS= jpegtran.obj rdswitch.obj cdjpeg.obj transupp.obj + + +all: libjpeg.lib cjpeg.exe djpeg.exe jpegtran.exe rdjpgcom.exe wrjpgcom.exe + +libjpeg.lib: $(LIBOBJECTS) + - del libjpeg.lib + * wlib -n libjpeg.lib $(LIBOBJECTS) + +cjpeg.exe: $(COBJECTS) libjpeg.lib + $(CC) $(LDFLAGS) $(COBJECTS) libjpeg.lib + +djpeg.exe: $(DOBJECTS) libjpeg.lib + $(CC) $(LDFLAGS) $(DOBJECTS) libjpeg.lib + +jpegtran.exe: $(TROBJECTS) libjpeg.lib + $(CC) $(LDFLAGS) $(TROBJECTS) libjpeg.lib + +rdjpgcom.exe: rdjpgcom.c + $(CC) $(CFLAGS) $(LDFLAGS) rdjpgcom.c + +wrjpgcom.exe: wrjpgcom.c + $(CC) $(CFLAGS) $(LDFLAGS) wrjpgcom.c + +.c.obj: + $(CC) $(CFLAGS) -c $< + +jconfig.h: jconfig.doc + echo You must prepare a system-dependent jconfig.h file. + echo Please read the installation directions in install.doc. + exit 1 + +clean: .SYMBOLIC + - del *.obj + - del libjpeg.lib + - del cjpeg.exe + - del djpeg.exe + - del jpegtran.exe + - del rdjpgcom.exe + - del wrjpgcom.exe + - del testout*.* + +test: cjpeg.exe djpeg.exe jpegtran.exe .SYMBOLIC + - del testout*.* + djpeg -dct int -ppm -outfile testout.ppm testorig.jpg + djpeg -dct int -bmp -colors 256 -outfile testout.bmp testorig.jpg + cjpeg -dct int -outfile testout.jpg testimg.ppm + djpeg -dct int -ppm -outfile testoutp.ppm testprog.jpg + cjpeg -dct int -progressive -opt -outfile testoutp.jpg testimg.ppm + jpegtran -outfile testoutt.jpg testprog.jpg +!ifeq SYSTEM DOS + fc /b testimg.ppm testout.ppm + fc /b testimg.bmp testout.bmp + fc /b testimg.jpg testout.jpg + fc /b testimg.ppm testoutp.ppm + fc /b testimgp.jpg testoutp.jpg + fc /b testorig.jpg testoutt.jpg +!else + echo n > n.tmp + comp testimg.ppm testout.ppm < n.tmp + comp testimg.bmp testout.bmp < n.tmp + comp testimg.jpg testout.jpg < n.tmp + comp testimg.ppm testoutp.ppm < n.tmp + comp testimgp.jpg testoutp.jpg < n.tmp + comp testorig.jpg testoutt.jpg < n.tmp + del n.tmp +!endif + + +jcapimin.obj: jcapimin.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcapistd.obj: jcapistd.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jccoefct.obj: jccoefct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jccolor.obj: jccolor.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcdctmgr.obj: jcdctmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jchuff.obj: jchuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jchuff.h +jcinit.obj: jcinit.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcmainct.obj: jcmainct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcmarker.obj: jcmarker.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcmaster.obj: jcmaster.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcomapi.obj: jcomapi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcparam.obj: jcparam.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcphuff.obj: jcphuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jchuff.h +jcprepct.obj: jcprepct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcsample.obj: jcsample.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jctrans.obj: jctrans.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdapimin.obj: jdapimin.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdapistd.obj: jdapistd.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdatadst.obj: jdatadst.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h +jdatasrc.obj: jdatasrc.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h +jdcoefct.obj: jdcoefct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdcolor.obj: jdcolor.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jddctmgr.obj: jddctmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jdhuff.obj: jdhuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdhuff.h +jdinput.obj: jdinput.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdmainct.obj: jdmainct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdmarker.obj: jdmarker.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdmaster.obj: jdmaster.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdmerge.obj: jdmerge.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdphuff.obj: jdphuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdhuff.h +jdpostct.obj: jdpostct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdsample.obj: jdsample.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdtrans.obj: jdtrans.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jerror.obj: jerror.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jversion.h jerror.h +jfdctflt.obj: jfdctflt.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jfdctfst.obj: jfdctfst.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jfdctint.obj: jfdctint.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jidctflt.obj: jidctflt.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jidctfst.obj: jidctfst.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jidctint.obj: jidctint.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jidctred.obj: jidctred.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h +jquant1.obj: jquant1.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jquant2.obj: jquant2.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jutils.obj: jutils.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jmemmgr.obj: jmemmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +jmemansi.obj: jmemansi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +jmemname.obj: jmemname.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +jmemnobs.obj: jmemnobs.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +jmemdos.obj: jmemdos.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +jmemmac.obj: jmemmac.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h +cjpeg.obj: cjpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h jversion.h +djpeg.obj: djpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h jversion.h +jpegtran.obj: jpegtran.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h transupp.h jversion.h +rdjpgcom.obj: rdjpgcom.c jinclude.h jconfig.h +wrjpgcom.obj: wrjpgcom.c jinclude.h jconfig.h +cdjpeg.obj: cdjpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdcolmap.obj: rdcolmap.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdswitch.obj: rdswitch.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +transupp.obj: transupp.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h transupp.h +rdppm.obj: rdppm.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +wrppm.obj: wrppm.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdgif.obj: rdgif.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +wrgif.obj: wrgif.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdtarga.obj: rdtarga.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +wrtarga.obj: wrtarga.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdbmp.obj: rdbmp.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +wrbmp.obj: wrbmp.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +rdrle.obj: rdrle.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h +wrrle.obj: wrrle.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h diff --git a/lc-continuity/mk4/modimage/jpeg-6b/makelib.ds b/lc-continuity/mk4/modimage/jpeg-6b/makelib.ds new file mode 100644 index 0000000000000000000000000000000000000000..c7ad36d09e4e603f1c23a979acf5ad2a9f238376 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/makelib.ds @@ -0,0 +1,1046 @@ +# Microsoft Developer Studio Generated NMAKE File, Format Version 4.20 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +!IF "$(CFG)" == "" +CFG=jpeg - Win32 +!MESSAGE No configuration specified. Defaulting to jpeg - Win32. +!ENDIF + +!IF "$(CFG)" != "jpeg - Win32" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE on this makefile +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "jpeg.mak" CFG="jpeg - Win32" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "jpeg - Win32" (based on "Win32 (x86) Static Library") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF +################################################################################ +# Begin Project +# PROP Target_Last_Scanned "jpeg - Win32" +CPP=cl.exe + +!IF "$(CFG)" == "jpeg - Win32" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +OUTDIR=.\Release +INTDIR=.\Release + +ALL : "$(OUTDIR)\jpeg.lib" + +CLEAN : + -@erase "$(INTDIR)\jcapimin.obj" + -@erase "$(INTDIR)\jcapistd.obj" + -@erase "$(INTDIR)\jctrans.obj" + -@erase "$(INTDIR)\jcparam.obj" + -@erase "$(INTDIR)\jdatadst.obj" + -@erase "$(INTDIR)\jcinit.obj" + -@erase "$(INTDIR)\jcmaster.obj" + -@erase "$(INTDIR)\jcmarker.obj" + -@erase "$(INTDIR)\jcmainct.obj" + -@erase "$(INTDIR)\jcprepct.obj" + -@erase "$(INTDIR)\jccoefct.obj" + -@erase "$(INTDIR)\jccolor.obj" + -@erase "$(INTDIR)\jcsample.obj" + -@erase "$(INTDIR)\jchuff.obj" + -@erase "$(INTDIR)\jcphuff.obj" + -@erase "$(INTDIR)\jcdctmgr.obj" + -@erase "$(INTDIR)\jfdctfst.obj" + -@erase "$(INTDIR)\jfdctflt.obj" + -@erase "$(INTDIR)\jfdctint.obj" + -@erase "$(INTDIR)\jdapimin.obj" + -@erase "$(INTDIR)\jdapistd.obj" + -@erase "$(INTDIR)\jdtrans.obj" + -@erase "$(INTDIR)\jdatasrc.obj" + -@erase "$(INTDIR)\jdmaster.obj" + -@erase "$(INTDIR)\jdinput.obj" + -@erase "$(INTDIR)\jdmarker.obj" + -@erase "$(INTDIR)\jdhuff.obj" + -@erase "$(INTDIR)\jdphuff.obj" + -@erase "$(INTDIR)\jdmainct.obj" + -@erase "$(INTDIR)\jdcoefct.obj" + -@erase "$(INTDIR)\jdpostct.obj" + -@erase "$(INTDIR)\jddctmgr.obj" + -@erase "$(INTDIR)\jidctfst.obj" + -@erase "$(INTDIR)\jidctflt.obj" + -@erase "$(INTDIR)\jidctint.obj" + -@erase "$(INTDIR)\jidctred.obj" + -@erase "$(INTDIR)\jdsample.obj" + -@erase "$(INTDIR)\jdcolor.obj" + -@erase "$(INTDIR)\jquant1.obj" + -@erase "$(INTDIR)\jquant2.obj" + -@erase "$(INTDIR)\jdmerge.obj" + -@erase "$(INTDIR)\jcomapi.obj" + -@erase "$(INTDIR)\jutils.obj" + -@erase "$(INTDIR)\jerror.obj" + -@erase "$(INTDIR)\jmemmgr.obj" + -@erase "$(INTDIR)\jmemnobs.obj" + -@erase "$(OUTDIR)\jpeg.lib" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +CPP_PROJ=/nologo /ML /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\ + /Fp"$(INTDIR)/jpeg.pch" /YX /Fo"$(INTDIR)/" /c +CPP_OBJS=.\Release/ +CPP_SBRS=.\. +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/jpeg.bsc" +BSC32_SBRS= \ + +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo +LIB32_FLAGS=/nologo /out:"$(OUTDIR)/jpeg.lib" +LIB32_OBJS= \ + "$(INTDIR)\jcapimin.obj" \ + "$(INTDIR)\jcapistd.obj" \ + "$(INTDIR)\jctrans.obj" \ + "$(INTDIR)\jcparam.obj" \ + "$(INTDIR)\jdatadst.obj" \ + "$(INTDIR)\jcinit.obj" \ + "$(INTDIR)\jcmaster.obj" \ + "$(INTDIR)\jcmarker.obj" \ + "$(INTDIR)\jcmainct.obj" \ + "$(INTDIR)\jcprepct.obj" \ + "$(INTDIR)\jccoefct.obj" \ + "$(INTDIR)\jccolor.obj" \ + "$(INTDIR)\jcsample.obj" \ + "$(INTDIR)\jchuff.obj" \ + "$(INTDIR)\jcphuff.obj" \ + "$(INTDIR)\jcdctmgr.obj" \ + "$(INTDIR)\jfdctfst.obj" \ + "$(INTDIR)\jfdctflt.obj" \ + "$(INTDIR)\jfdctint.obj" \ + "$(INTDIR)\jdapimin.obj" \ + "$(INTDIR)\jdapistd.obj" \ + "$(INTDIR)\jdtrans.obj" \ + "$(INTDIR)\jdatasrc.obj" \ + "$(INTDIR)\jdmaster.obj" \ + "$(INTDIR)\jdinput.obj" \ + "$(INTDIR)\jdmarker.obj" \ + "$(INTDIR)\jdhuff.obj" \ + "$(INTDIR)\jdphuff.obj" \ + "$(INTDIR)\jdmainct.obj" \ + "$(INTDIR)\jdcoefct.obj" \ + "$(INTDIR)\jdpostct.obj" \ + "$(INTDIR)\jddctmgr.obj" \ + "$(INTDIR)\jidctfst.obj" \ + "$(INTDIR)\jidctflt.obj" \ + "$(INTDIR)\jidctint.obj" \ + "$(INTDIR)\jidctred.obj" \ + "$(INTDIR)\jdsample.obj" \ + "$(INTDIR)\jdcolor.obj" \ + "$(INTDIR)\jquant1.obj" \ + "$(INTDIR)\jquant2.obj" \ + "$(INTDIR)\jdmerge.obj" \ + "$(INTDIR)\jcomapi.obj" \ + "$(INTDIR)\jutils.obj" \ + "$(INTDIR)\jerror.obj" \ + "$(INTDIR)\jmemmgr.obj" \ + "$(INTDIR)\jmemnobs.obj" + +"$(OUTDIR)\jpeg.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS) + $(LIB32) @<< + $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_OBJS) +<< + +!ENDIF + +.c{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.c{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +################################################################################ +# Begin Target + +# Name "jpeg - Win32" + +!IF "$(CFG)" == "jpeg - Win32" + +!ENDIF + +################################################################################ +# Begin Source File + +SOURCE="jcapimin.c" +DEP_CPP_JCAPI=\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jpegint.h"\ + "jerror.h"\ + + +"$(INTDIR)\jcapimin.obj" : $(SOURCE) $(DEP_CPP_JCAPI) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="jcapistd.c" +DEP_CPP_JCAPIS=\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jpegint.h"\ + "jerror.h"\ + + +"$(INTDIR)\jcapistd.obj" : $(SOURCE) $(DEP_CPP_JCAPIS) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="jccoefct.c" +DEP_CPP_JCCOE=\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jpegint.h"\ + "jerror.h"\ + + +"$(INTDIR)\jccoefct.obj" : $(SOURCE) $(DEP_CPP_JCCOE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="jccolor.c" +DEP_CPP_JCCOL=\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jpegint.h"\ + "jerror.h"\ + + +"$(INTDIR)\jccolor.obj" : $(SOURCE) $(DEP_CPP_JCCOL) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="jcdctmgr.c" +DEP_CPP_JCDCT=\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jpegint.h"\ + "jerror.h"\ + "jdct.h"\ + + +"$(INTDIR)\jcdctmgr.obj" : $(SOURCE) $(DEP_CPP_JCDCT) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="jchuff.c" +DEP_CPP_JCHUF=\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jpegint.h"\ + "jerror.h"\ + "jchuff.h"\ + + +"$(INTDIR)\jchuff.obj" : $(SOURCE) $(DEP_CPP_JCHUF) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="jcinit.c" +DEP_CPP_JCINI=\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jpegint.h"\ + "jerror.h"\ + + +"$(INTDIR)\jcinit.obj" : $(SOURCE) $(DEP_CPP_JCINI) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="jcmainct.c" +DEP_CPP_JCMAI=\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jpegint.h"\ + "jerror.h"\ + + +"$(INTDIR)\jcmainct.obj" : $(SOURCE) $(DEP_CPP_JCMAI) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="jcmarker.c" +DEP_CPP_JCMAR=\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jpegint.h"\ + "jerror.h"\ + + +"$(INTDIR)\jcmarker.obj" : $(SOURCE) $(DEP_CPP_JCMAR) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="jcmaster.c" +DEP_CPP_JCMAS=\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jpegint.h"\ + "jerror.h"\ + + +"$(INTDIR)\jcmaster.obj" : $(SOURCE) $(DEP_CPP_JCMAS) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="jcomapi.c" +DEP_CPP_JCOMA=\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jpegint.h"\ + "jerror.h"\ + + +"$(INTDIR)\jcomapi.obj" : $(SOURCE) $(DEP_CPP_JCOMA) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="jcparam.c" +DEP_CPP_JCPAR=\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jpegint.h"\ + "jerror.h"\ + + +"$(INTDIR)\jcparam.obj" : $(SOURCE) $(DEP_CPP_JCPAR) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="jcphuff.c" +DEP_CPP_JCPHU=\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jpegint.h"\ + "jerror.h"\ + "jchuff.h"\ + + +"$(INTDIR)\jcphuff.obj" : $(SOURCE) $(DEP_CPP_JCPHU) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="jcprepct.c" +DEP_CPP_JCPRE=\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jpegint.h"\ + "jerror.h"\ + + +"$(INTDIR)\jcprepct.obj" : $(SOURCE) $(DEP_CPP_JCPRE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="jcsample.c" +DEP_CPP_JCSAM=\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jpegint.h"\ + "jerror.h"\ + + +"$(INTDIR)\jcsample.obj" : $(SOURCE) $(DEP_CPP_JCSAM) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="jctrans.c" +DEP_CPP_JCTRA=\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jpegint.h"\ + "jerror.h"\ + + +"$(INTDIR)\jctrans.obj" : $(SOURCE) $(DEP_CPP_JCTRA) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="jdapimin.c" +DEP_CPP_JDAPI=\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jpegint.h"\ + "jerror.h"\ + + +"$(INTDIR)\jdapimin.obj" : $(SOURCE) $(DEP_CPP_JDAPI) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="jdapistd.c" +DEP_CPP_JDAPIS=\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jpegint.h"\ + "jerror.h"\ + + +"$(INTDIR)\jdapistd.obj" : $(SOURCE) $(DEP_CPP_JDAPIS) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="jdatadst.c" +DEP_CPP_JDATA=\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jerror.h"\ + + +"$(INTDIR)\jdatadst.obj" : $(SOURCE) $(DEP_CPP_JDATA) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="jdatasrc.c" +DEP_CPP_JDATAS=\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jerror.h"\ + + +"$(INTDIR)\jdatasrc.obj" : $(SOURCE) $(DEP_CPP_JDATAS) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="jdcoefct.c" +DEP_CPP_JDCOE=\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jpegint.h"\ + "jerror.h"\ + + +"$(INTDIR)\jdcoefct.obj" : $(SOURCE) $(DEP_CPP_JDCOE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="jdcolor.c" +DEP_CPP_JDCOL=\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jpegint.h"\ + "jerror.h"\ + + +"$(INTDIR)\jdcolor.obj" : $(SOURCE) $(DEP_CPP_JDCOL) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="jddctmgr.c" +DEP_CPP_JDDCT=\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jpegint.h"\ + "jerror.h"\ + "jdct.h"\ + + +"$(INTDIR)\jddctmgr.obj" : $(SOURCE) $(DEP_CPP_JDDCT) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="jdhuff.c" +DEP_CPP_JDHUF=\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jpegint.h"\ + "jerror.h"\ + "jdhuff.h"\ + + +"$(INTDIR)\jdhuff.obj" : $(SOURCE) $(DEP_CPP_JDHUF) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="jdinput.c" +DEP_CPP_JDINP=\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jpegint.h"\ + "jerror.h"\ + + +"$(INTDIR)\jdinput.obj" : $(SOURCE) $(DEP_CPP_JDINP) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="jdmainct.c" +DEP_CPP_JDMAI=\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jpegint.h"\ + "jerror.h"\ + + +"$(INTDIR)\jdmainct.obj" : $(SOURCE) $(DEP_CPP_JDMAI) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="jdmarker.c" +DEP_CPP_JDMAR=\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jpegint.h"\ + "jerror.h"\ + + +"$(INTDIR)\jdmarker.obj" : $(SOURCE) $(DEP_CPP_JDMAR) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="jdmaster.c" +DEP_CPP_JDMAS=\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jpegint.h"\ + "jerror.h"\ + + +"$(INTDIR)\jdmaster.obj" : $(SOURCE) $(DEP_CPP_JDMAS) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="jdmerge.c" +DEP_CPP_JDMER=\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jpegint.h"\ + "jerror.h"\ + + +"$(INTDIR)\jdmerge.obj" : $(SOURCE) $(DEP_CPP_JDMER) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="jdphuff.c" +DEP_CPP_JDPHU=\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jpegint.h"\ + "jerror.h"\ + "jdhuff.h"\ + + +"$(INTDIR)\jdphuff.obj" : $(SOURCE) $(DEP_CPP_JDPHU) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="jdpostct.c" +DEP_CPP_JDPOS=\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jpegint.h"\ + "jerror.h"\ + + +"$(INTDIR)\jdpostct.obj" : $(SOURCE) $(DEP_CPP_JDPOS) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="jdsample.c" +DEP_CPP_JDSAM=\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jpegint.h"\ + "jerror.h"\ + + +"$(INTDIR)\jdsample.obj" : $(SOURCE) $(DEP_CPP_JDSAM) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="jdtrans.c" +DEP_CPP_JDTRA=\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jpegint.h"\ + "jerror.h"\ + + +"$(INTDIR)\jdtrans.obj" : $(SOURCE) $(DEP_CPP_JDTRA) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="jerror.c" +DEP_CPP_JERRO=\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jversion.h"\ + "jerror.h"\ + + +"$(INTDIR)\jerror.obj" : $(SOURCE) $(DEP_CPP_JERRO) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="jfdctflt.c" +DEP_CPP_JFDCT=\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jpegint.h"\ + "jerror.h"\ + "jdct.h"\ + + +"$(INTDIR)\jfdctflt.obj" : $(SOURCE) $(DEP_CPP_JFDCT) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="jfdctfst.c" +DEP_CPP_JFDCTF=\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jpegint.h"\ + "jerror.h"\ + "jdct.h"\ + + +"$(INTDIR)\jfdctfst.obj" : $(SOURCE) $(DEP_CPP_JFDCTF) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="jfdctint.c" +DEP_CPP_JFDCTI=\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jpegint.h"\ + "jerror.h"\ + "jdct.h"\ + + +"$(INTDIR)\jfdctint.obj" : $(SOURCE) $(DEP_CPP_JFDCTI) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="jidctflt.c" +DEP_CPP_JIDCT=\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jpegint.h"\ + "jerror.h"\ + "jdct.h"\ + + +"$(INTDIR)\jidctflt.obj" : $(SOURCE) $(DEP_CPP_JIDCT) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="jidctfst.c" +DEP_CPP_JIDCTF=\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jpegint.h"\ + "jerror.h"\ + "jdct.h"\ + + +"$(INTDIR)\jidctfst.obj" : $(SOURCE) $(DEP_CPP_JIDCTF) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="jidctint.c" +DEP_CPP_JIDCTI=\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jpegint.h"\ + "jerror.h"\ + "jdct.h"\ + + +"$(INTDIR)\jidctint.obj" : $(SOURCE) $(DEP_CPP_JIDCTI) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="jidctred.c" +DEP_CPP_JIDCTR=\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jpegint.h"\ + "jerror.h"\ + "jdct.h"\ + + +"$(INTDIR)\jidctred.obj" : $(SOURCE) $(DEP_CPP_JIDCTR) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="jquant1.c" +DEP_CPP_JQUAN=\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jpegint.h"\ + "jerror.h"\ + + +"$(INTDIR)\jquant1.obj" : $(SOURCE) $(DEP_CPP_JQUAN) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="jquant2.c" +DEP_CPP_JQUANT=\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jpegint.h"\ + "jerror.h"\ + + +"$(INTDIR)\jquant2.obj" : $(SOURCE) $(DEP_CPP_JQUANT) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="jutils.c" +DEP_CPP_JUTIL=\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jpegint.h"\ + "jerror.h"\ + + +"$(INTDIR)\jutils.obj" : $(SOURCE) $(DEP_CPP_JUTIL) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="jmemmgr.c" +DEP_CPP_JMEMM=\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jpegint.h"\ + "jerror.h"\ + "jmemsys.h"\ + + +"$(INTDIR)\jmemmgr.obj" : $(SOURCE) $(DEP_CPP_JMEMM) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE="jmemnobs.c" +DEP_CPP_JMEMN=\ + "jinclude.h"\ + "jconfig.h"\ + "jpeglib.h"\ + "jmorecfg.h"\ + "jpegint.h"\ + "jerror.h"\ + "jmemsys.h"\ + + +"$(INTDIR)\jmemnobs.obj" : $(SOURCE) $(DEP_CPP_JMEMN) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +# End Target +# End Project +################################################################################ + diff --git a/lc-continuity/mk4/modimage/jpeg-6b/makeproj.mac b/lc-continuity/mk4/modimage/jpeg-6b/makeproj.mac new file mode 100644 index 0000000000000000000000000000000000000000..ed277c83da8bea7c78d37c7b4c6eab5df7aebd50 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/makeproj.mac @@ -0,0 +1,213 @@ +-- +-- makeproj.mac +-- +-- This AppleScript builds Code Warrior PRO Release 2 project files for the +-- libjpeg library as well as the test programs 'cjpeg', 'djpeg', 'jpegtran'. +-- (We'd distribute real project files, except they're not text +-- and would create maintenance headaches.) +-- +-- The script then compiles and links the library and the test programs. +-- NOTE: if you haven't already created a 'jconfig.h' file, the script +-- automatically copies 'jconfig.mac' to 'jconfig.h'. +-- +-- To use this script, you must have AppleScript 1.1 or later installed +-- and a suitable AppleScript editor like Script Editor or Script Debugger +-- (http://www.latenightsw.com). Open this file with your AppleScript +-- editor and execute the "run" command to build the projects. +-- +-- Thanks to Dan Sears and Don Agro for this script. +-- Questions about this script can be addressed to dogpark@interlog.com +-- + +on run + + choose folder with prompt ">>> Select IJG source folder <<<" + set ijg_folder to result + + choose folder with prompt ">>> Select MetroWerks folder <<<" + set cw_folder to result + + -- if jconfig.h doesn't already exist, copy jconfig.mac + + tell application "Finder" + if not (exists file "jconfig.h" of ijg_folder) then + duplicate {file "jconfig.mac" of folder ijg_folder} + select file "jconfig.mac copy" of folder ijg_folder + set name of selection to "jconfig.h" + end if + end tell + + tell application "CodeWarrior IDE 2.1" + with timeout of 10000 seconds + + -- create libjpeg project + + activate + Create Project (ijg_folder as string) & "libjpeg.proj" + Set Preferences of panel "Target Settings" to {Target Name:"libjpeg"} + Set Preferences of panel "PPC Project" to {File Name:"libjpeg"} + Set Preferences of panel "Target Settings" to {Linker:"MacOS PPC Linker"} + Set Preferences of panel "PPC Project" to {Project Type:library} + Set Preferences of panel "C/C++ Compiler" to {ANSI Strict:true} + Set Preferences of panel "C/C++ Compiler" to {Enums Always Ints:true} + Set Preferences of panel "PPC Codegen" to {Struct Alignment:PowerPC} + Set Preferences of panel "PPC Linker" to {Generate SYM File:false} + + Add Files (ijg_folder as string) & "jcapimin.c" To Segment 1 + Add Files (ijg_folder as string) & "jcapistd.c" To Segment 1 + Add Files (ijg_folder as string) & "jctrans.c" To Segment 1 + Add Files (ijg_folder as string) & "jcparam.c" To Segment 1 + Add Files (ijg_folder as string) & "jdatadst.c" To Segment 1 + Add Files (ijg_folder as string) & "jcinit.c" To Segment 1 + Add Files (ijg_folder as string) & "jcmaster.c" To Segment 1 + Add Files (ijg_folder as string) & "jcmarker.c" To Segment 1 + Add Files (ijg_folder as string) & "jcmainct.c" To Segment 1 + Add Files (ijg_folder as string) & "jcprepct.c" To Segment 1 + Add Files (ijg_folder as string) & "jccoefct.c" To Segment 1 + Add Files (ijg_folder as string) & "jccolor.c" To Segment 1 + Add Files (ijg_folder as string) & "jcsample.c" To Segment 1 + Add Files (ijg_folder as string) & "jchuff.c" To Segment 1 + Add Files (ijg_folder as string) & "jcphuff.c" To Segment 1 + Add Files (ijg_folder as string) & "jcdctmgr.c" To Segment 1 + Add Files (ijg_folder as string) & "jfdctfst.c" To Segment 1 + Add Files (ijg_folder as string) & "jfdctflt.c" To Segment 1 + Add Files (ijg_folder as string) & "jfdctint.c" To Segment 1 + Add Files (ijg_folder as string) & "jdapimin.c" To Segment 1 + Add Files (ijg_folder as string) & "jdapistd.c" To Segment 1 + Add Files (ijg_folder as string) & "jdtrans.c" To Segment 1 + Add Files (ijg_folder as string) & "jdatasrc.c" To Segment 1 + Add Files (ijg_folder as string) & "jdmaster.c" To Segment 1 + Add Files (ijg_folder as string) & "jdinput.c" To Segment 1 + Add Files (ijg_folder as string) & "jdmarker.c" To Segment 1 + Add Files (ijg_folder as string) & "jdhuff.c" To Segment 1 + Add Files (ijg_folder as string) & "jdphuff.c" To Segment 1 + Add Files (ijg_folder as string) & "jdmainct.c" To Segment 1 + Add Files (ijg_folder as string) & "jdcoefct.c" To Segment 1 + Add Files (ijg_folder as string) & "jdpostct.c" To Segment 1 + Add Files (ijg_folder as string) & "jddctmgr.c" To Segment 1 + Add Files (ijg_folder as string) & "jidctfst.c" To Segment 1 + Add Files (ijg_folder as string) & "jidctflt.c" To Segment 1 + Add Files (ijg_folder as string) & "jidctint.c" To Segment 1 + Add Files (ijg_folder as string) & "jidctred.c" To Segment 1 + Add Files (ijg_folder as string) & "jdsample.c" To Segment 1 + Add Files (ijg_folder as string) & "jdcolor.c" To Segment 1 + Add Files (ijg_folder as string) & "jquant1.c" To Segment 1 + Add Files (ijg_folder as string) & "jquant2.c" To Segment 1 + Add Files (ijg_folder as string) & "jdmerge.c" To Segment 1 + Add Files (ijg_folder as string) & "jcomapi.c" To Segment 1 + Add Files (ijg_folder as string) & "jutils.c" To Segment 1 + Add Files (ijg_folder as string) & "jerror.c" To Segment 1 + Add Files (ijg_folder as string) & "jmemmgr.c" To Segment 1 + Add Files (ijg_folder as string) & "jmemmac.c" To Segment 1 + + -- compile and link the library + + Make Project + Close Project + + -- create cjpeg project + + activate + Create Project (ijg_folder as string) & "cjpeg.proj" + Set Preferences of panel "Target Settings" to {Target Name:"cjpeg"} + Set Preferences of panel "PPC Project" to {File Name:"cjpeg"} + Set Preferences of panel "Target Settings" to {Linker:"MacOS PPC Linker"} + Set Preferences of panel "C/C++ Compiler" to {ANSI Strict:true} + Set Preferences of panel "C/C++ Compiler" to {Enums Always Ints:true} + Set Preferences of panel "PPC Codegen" to {Struct Alignment:PowerPC} + Set Preferences of panel "PPC Linker" to {Generate SYM File:false} + + Add Files (ijg_folder as string) & "cjpeg.c" To Segment 1 + Add Files (ijg_folder as string) & "rdppm.c" To Segment 1 + Add Files (ijg_folder as string) & "rdgif.c" To Segment 1 + Add Files (ijg_folder as string) & "rdtarga.c" To Segment 1 + Add Files (ijg_folder as string) & "rdrle.c" To Segment 1 + Add Files (ijg_folder as string) & "rdbmp.c" To Segment 1 + Add Files (ijg_folder as string) & "rdswitch.c" To Segment 1 + Add Files (ijg_folder as string) & "cdjpeg.c" To Segment 1 + + Add Files (ijg_folder as string) & "libjpeg" To Segment 2 + + Add Files (cw_folder as string) & "Metrowerks CodeWarrior:Metrowerks Standard Library:MSL C:Bin:MSL C.PPC.Lib" To Segment 3 + Add Files (cw_folder as string) & "Metrowerks CodeWarrior:Metrowerks Standard Library:MSL C:Bin:MSL SIOUX.PPC.Lib" To Segment 3 + Add Files (cw_folder as string) & "Metrowerks CodeWarrior:MacOS Support:Libraries:Runtime:Runtime PPC:MSL RuntimePPC.Lib" To Segment 3 + + Add Files (cw_folder as string) & "Metrowerks CodeWarrior:MacOS Support:Libraries:MacOS Common:InterfaceLib" To Segment 4 + Add Files (cw_folder as string) & "Metrowerks CodeWarrior:MacOS Support:Libraries:MacOS Common:MathLib" To Segment 4 + + -- compile and link cjpeg + + Make Project + Close Project + + -- create djpeg project + + activate + Create Project (ijg_folder as string) & "djpeg.proj" + Set Preferences of panel "Target Settings" to {Target Name:"djpeg"} + Set Preferences of panel "PPC Project" to {File Name:"djpeg"} + Set Preferences of panel "Target Settings" to {Linker:"MacOS PPC Linker"} + Set Preferences of panel "C/C++ Compiler" to {ANSI Strict:true} + Set Preferences of panel "C/C++ Compiler" to {Enums Always Ints:true} + Set Preferences of panel "PPC Codegen" to {Struct Alignment:PowerPC} + Set Preferences of panel "PPC Linker" to {Generate SYM File:false} + + Add Files (ijg_folder as string) & "djpeg.c" To Segment 1 + Add Files (ijg_folder as string) & "wrppm.c" To Segment 1 + Add Files (ijg_folder as string) & "wrgif.c" To Segment 1 + Add Files (ijg_folder as string) & "wrtarga.c" To Segment 1 + Add Files (ijg_folder as string) & "wrrle.c" To Segment 1 + Add Files (ijg_folder as string) & "wrbmp.c" To Segment 1 + Add Files (ijg_folder as string) & "rdcolmap.c" To Segment 1 + Add Files (ijg_folder as string) & "cdjpeg.c" To Segment 1 + + Add Files (ijg_folder as string) & "libjpeg" To Segment 2 + + Add Files (cw_folder as string) & "Metrowerks CodeWarrior:Metrowerks Standard Library:MSL C:Bin:MSL C.PPC.Lib" To Segment 3 + Add Files (cw_folder as string) & "Metrowerks CodeWarrior:Metrowerks Standard Library:MSL C:Bin:MSL SIOUX.PPC.Lib" To Segment 3 + Add Files (cw_folder as string) & "Metrowerks CodeWarrior:MacOS Support:Libraries:Runtime:Runtime PPC:MSL RuntimePPC.Lib" To Segment 3 + + Add Files (cw_folder as string) & "Metrowerks CodeWarrior:MacOS Support:Libraries:MacOS Common:InterfaceLib" To Segment 4 + Add Files (cw_folder as string) & "Metrowerks CodeWarrior:MacOS Support:Libraries:MacOS Common:MathLib" To Segment 4 + + -- compile and link djpeg + + Make Project + Close Project + + -- create jpegtran project + + activate + Create Project (ijg_folder as string) & "jpegtran.proj" + Set Preferences of panel "Target Settings" to {Target Name:"jpegtran"} + Set Preferences of panel "PPC Project" to {File Name:"jpegtran"} + Set Preferences of panel "Target Settings" to {Linker:"MacOS PPC Linker"} + Set Preferences of panel "C/C++ Compiler" to {ANSI Strict:true} + Set Preferences of panel "C/C++ Compiler" to {Enums Always Ints:true} + Set Preferences of panel "PPC Codegen" to {Struct Alignment:PowerPC} + Set Preferences of panel "PPC Linker" to {Generate SYM File:false} + + Add Files (ijg_folder as string) & "jpegtran.c" To Segment 1 + Add Files (ijg_folder as string) & "rdswitch.c" To Segment 1 + Add Files (ijg_folder as string) & "cdjpeg.c" To Segment 1 + Add Files (ijg_folder as string) & "transupp.c" To Segment 1 + + Add Files (ijg_folder as string) & "libjpeg" To Segment 2 + + Add Files (cw_folder as string) & "Metrowerks CodeWarrior:Metrowerks Standard Library:MSL C:Bin:MSL C.PPC.Lib" To Segment 3 + Add Files (cw_folder as string) & "Metrowerks CodeWarrior:Metrowerks Standard Library:MSL C:Bin:MSL SIOUX.PPC.Lib" To Segment 3 + Add Files (cw_folder as string) & "Metrowerks CodeWarrior:MacOS Support:Libraries:Runtime:Runtime PPC:MSL RuntimePPC.Lib" To Segment 3 + + Add Files (cw_folder as string) & "Metrowerks CodeWarrior:MacOS Support:Libraries:MacOS Common:InterfaceLib" To Segment 4 + Add Files (cw_folder as string) & "Metrowerks CodeWarrior:MacOS Support:Libraries:MacOS Common:MathLib" To Segment 4 + + -- compile and link jpegtran + + Make Project + Close Project + + quit + + end timeout + end tell +end run diff --git a/lc-continuity/mk4/modimage/jpeg-6b/makljpeg.st b/lc-continuity/mk4/modimage/jpeg-6b/makljpeg.st new file mode 100644 index 0000000000000000000000000000000000000000..813493ea878e3cbf09d2bf6649323c1c810192e2 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/makljpeg.st @@ -0,0 +1,70 @@ +; Project file for Independent JPEG Group's software +; +; This project file is for Atari ST/STE/TT systems using Pure C or Turbo C. +; Thanks to Frank Moehle (Frank.Moehle@arbi.informatik.uni-oldenburg.de), +; Dr. B. Setzepfandt (bernd@gina.uni-muenster.de), +; and Guido Vollbeding (guivol@esc.de). +; +; To use this file, rename it to libjpeg.prj. +; Read installation instructions before trying to make the program! +; +; +; * * * Output file * * * +libjpeg.lib +; +; * * * COMPILER OPTIONS * * * +.C[-P] ; absolute calls +.C[-M] ; and no string merging, folks +.C[-w-cln] ; no "constant is long" warnings +.C[-w-par] ; no "parameter xxxx unused" +.C[-w-rch] ; no "unreachable code" +.C[-wsig] ; warn if significant digits may be lost +.L[-J] ; link new Obj-format (so we get a library) += +; * * * * List of modules * * * * +jcapimin.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) +jcapistd.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) +jccoefct.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) +jccolor.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) +jcdctmgr.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h,jdct.h) +jchuff.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h,jchuff.h) +jcinit.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) +jcmainct.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) +jcmarker.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) +jcmaster.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) +jcomapi.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) +jcparam.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) +jcphuff.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h,jchuff.h) +jcprepct.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) +jcsample.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) +jctrans.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) +jdapimin.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) +jdapistd.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) +jdatadst.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h) +jdatasrc.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h) +jdcoefct.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) +jdcolor.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) +jddctmgr.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h,jdct.h) +jdhuff.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h,jdhuff.h) +jdinput.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) +jdmainct.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) +jdmarker.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) +jdmaster.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) +jdmerge.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) +jdphuff.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h,jdhuff.h) +jdpostct.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) +jdsample.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) +jdtrans.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) +jerror.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jversion.h,jerror.h) +jfdctflt.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h,jdct.h) +jfdctfst.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h,jdct.h) +jfdctint.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h,jdct.h) +jidctflt.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h,jdct.h) +jidctfst.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h,jdct.h) +jidctint.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h,jdct.h) +jidctred.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h,jdct.h) +jquant1.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) +jquant2.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) +jutils.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) +jmemmgr.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h,jmemsys.h) +jmemansi.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h,jmemsys.h) diff --git a/lc-continuity/mk4/modimage/jpeg-6b/maktjpeg.st b/lc-continuity/mk4/modimage/jpeg-6b/maktjpeg.st new file mode 100644 index 0000000000000000000000000000000000000000..31f4d169cdb3b6560b55356080dd09896024fa2b --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/maktjpeg.st @@ -0,0 +1,32 @@ +; Project file for Independent JPEG Group's software +; +; This project file is for Atari ST/STE/TT systems using Pure C or Turbo C. +; Thanks to Frank Moehle (Frank.Moehle@arbi.informatik.uni-oldenburg.de), +; Dr. B. Setzepfandt (bernd@gina.uni-muenster.de), +; and Guido Vollbeding (guivol@esc.de). +; +; To use this file, rename it to jpegtran.prj. +; If you are using Turbo C, change filenames beginning with "pc..." to "tc..." +; Read installation instructions before trying to make the program! +; +; +; * * * Output file * * * +jpegtran.ttp +; +; * * * COMPILER OPTIONS * * * +.C[-P] ; absolute calls +.C[-M] ; and no string merging, folks +.C[-w-cln] ; no "constant is long" warnings +.C[-w-par] ; no "parameter xxxx unused" +.C[-w-rch] ; no "unreachable code" +.C[-wsig] ; warn if significant digits may be lost += +; * * * * List of modules * * * * +pcstart.o +jpegtran.c (cdjpeg.h,jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h,cderror.h,transupp.h,jversion.h) +cdjpeg.c (cdjpeg.h,jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h,cderror.h) +rdswitch.c (cdjpeg.h,jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h,cderror.h) +transupp.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h,transupp.h) +libjpeg.lib ; built by libjpeg.prj +pcstdlib.lib ; standard library +pcextlib.lib ; extended library diff --git a/lc-continuity/mk4/modimage/jpeg-6b/makvms.opt b/lc-continuity/mk4/modimage/jpeg-6b/makvms.opt new file mode 100644 index 0000000000000000000000000000000000000000..675e8fe98a41c1689b170a4ec981df95ef21a319 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/makvms.opt @@ -0,0 +1,4 @@ +! A pointer to the VAX/VMS C Run-Time Shareable Library. +! This file is needed by makefile.mms and makefile.vms, +! but only for the older VAX C compiler. DEC C does not need it. +Sys$Library:VAXCRTL.EXE /Share diff --git a/lc-continuity/mk4/modimage/jpeg-6b/rdbmp.c b/lc-continuity/mk4/modimage/jpeg-6b/rdbmp.c new file mode 100644 index 0000000000000000000000000000000000000000..b05fe2ac47cf2753dda7cb89a756984498d118bd --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/rdbmp.c @@ -0,0 +1,439 @@ +/* + * rdbmp.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains routines to read input images in Microsoft "BMP" + * format (MS Windows 3.x, OS/2 1.x, and OS/2 2.x flavors). + * Currently, only 8-bit and 24-bit images are supported, not 1-bit or + * 4-bit (feeding such low-depth images into JPEG would be silly anyway). + * Also, we don't support RLE-compressed files. + * + * These routines may need modification for non-Unix environments or + * specialized applications. As they stand, they assume input from + * an ordinary stdio stream. They further assume that reading begins + * at the start of the file; start_input may need work if the + * user interface has already read some data (e.g., to determine that + * the file is indeed BMP format). + * + * This code contributed by James Arthur Boucher. + */ + +#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ + +#ifdef BMP_SUPPORTED + + +/* Macros to deal with unsigned chars as efficiently as compiler allows */ + +#ifdef HAVE_UNSIGNED_CHAR +typedef unsigned char U_CHAR; +#define UCH(x) ((int) (x)) +#else /* !HAVE_UNSIGNED_CHAR */ +#ifdef CHAR_IS_UNSIGNED +typedef char U_CHAR; +#define UCH(x) ((int) (x)) +#else +typedef char U_CHAR; +#define UCH(x) ((int) (x) & 0xFF) +#endif +#endif /* HAVE_UNSIGNED_CHAR */ + + +#define ReadOK(file,buffer,len) (JFREAD(file,buffer,len) == ((size_t) (len))) + + +/* Private version of data source object */ + +typedef struct _bmp_source_struct * bmp_source_ptr; + +typedef struct _bmp_source_struct { + struct cjpeg_source_struct pub; /* public fields */ + + j_compress_ptr cinfo; /* back link saves passing separate parm */ + + JSAMPARRAY colormap; /* BMP colormap (converted to my format) */ + + jvirt_sarray_ptr whole_image; /* Needed to reverse row order */ + JDIMENSION source_row; /* Current source row number */ + JDIMENSION row_width; /* Physical width of scanlines in file */ + + int bits_per_pixel; /* remembers 8- or 24-bit format */ +} bmp_source_struct; + + +LOCAL(int) +read_byte (bmp_source_ptr sinfo) +/* Read next byte from BMP file */ +{ + register FILE *infile = sinfo->pub.input_file; + register int c; + + if ((c = getc(infile)) == EOF) + ERREXIT(sinfo->cinfo, JERR_INPUT_EOF); + return c; +} + + +LOCAL(void) +read_colormap (bmp_source_ptr sinfo, int cmaplen, int mapentrysize) +/* Read the colormap from a BMP file */ +{ + int i; + + switch (mapentrysize) { + case 3: + /* BGR format (occurs in OS/2 files) */ + for (i = 0; i < cmaplen; i++) { + sinfo->colormap[2][i] = (JSAMPLE) read_byte(sinfo); + sinfo->colormap[1][i] = (JSAMPLE) read_byte(sinfo); + sinfo->colormap[0][i] = (JSAMPLE) read_byte(sinfo); + } + break; + case 4: + /* BGR0 format (occurs in MS Windows files) */ + for (i = 0; i < cmaplen; i++) { + sinfo->colormap[2][i] = (JSAMPLE) read_byte(sinfo); + sinfo->colormap[1][i] = (JSAMPLE) read_byte(sinfo); + sinfo->colormap[0][i] = (JSAMPLE) read_byte(sinfo); + (void) read_byte(sinfo); + } + break; + default: + ERREXIT(sinfo->cinfo, JERR_BMP_BADCMAP); + break; + } +} + + +/* + * Read one row of pixels. + * The image has been read into the whole_image array, but is otherwise + * unprocessed. We must read it out in top-to-bottom row order, and if + * it is an 8-bit image, we must expand colormapped pixels to 24bit format. + */ + +METHODDEF(JDIMENSION) +get_8bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading 8-bit colormap indexes */ +{ + bmp_source_ptr source = (bmp_source_ptr) sinfo; + register JSAMPARRAY colormap = source->colormap; + JSAMPARRAY image_ptr; + register int t; + register JSAMPROW inptr, outptr; + register JDIMENSION col; + + /* Fetch next row from virtual array */ + source->source_row--; + image_ptr = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, source->whole_image, + source->source_row, (JDIMENSION) 1, FALSE); + + /* Expand the colormap indexes to real data */ + inptr = image_ptr[0]; + outptr = source->pub.buffer[0]; + for (col = cinfo->image_width; col > 0; col--) { + t = GETJSAMPLE(*inptr++); + *outptr++ = colormap[0][t]; /* can omit GETJSAMPLE() safely */ + *outptr++ = colormap[1][t]; + *outptr++ = colormap[2][t]; + } + + return 1; +} + + +METHODDEF(JDIMENSION) +get_24bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading 24-bit pixels */ +{ + bmp_source_ptr source = (bmp_source_ptr) sinfo; + JSAMPARRAY image_ptr; + register JSAMPROW inptr, outptr; + register JDIMENSION col; + + /* Fetch next row from virtual array */ + source->source_row--; + image_ptr = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, source->whole_image, + source->source_row, (JDIMENSION) 1, FALSE); + + /* Transfer data. Note source values are in BGR order + * (even though Microsoft's own documents say the opposite). + */ + inptr = image_ptr[0]; + outptr = source->pub.buffer[0]; + for (col = cinfo->image_width; col > 0; col--) { + outptr[2] = *inptr++; /* can omit GETJSAMPLE() safely */ + outptr[1] = *inptr++; + outptr[0] = *inptr++; + outptr += 3; + } + + return 1; +} + + +/* + * This method loads the image into whole_image during the first call on + * get_pixel_rows. The get_pixel_rows pointer is then adjusted to call + * get_8bit_row or get_24bit_row on subsequent calls. + */ + +METHODDEF(JDIMENSION) +preload_image (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +{ + bmp_source_ptr source = (bmp_source_ptr) sinfo; + register FILE *infile = source->pub.input_file; + register int c; + register JSAMPROW out_ptr; + JSAMPARRAY image_ptr; + JDIMENSION row, col; + cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress; + + /* Read the data into a virtual array in input-file row order. */ + for (row = 0; row < cinfo->image_height; row++) { + if (progress != NULL) { + progress->pub.pass_counter = (long) row; + progress->pub.pass_limit = (long) cinfo->image_height; + (*progress->pub.progress_monitor) ((j_common_ptr) cinfo); + } + image_ptr = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, source->whole_image, + row, (JDIMENSION) 1, TRUE); + out_ptr = image_ptr[0]; + for (col = source->row_width; col > 0; col--) { + /* inline copy of read_byte() for speed */ + if ((c = getc(infile)) == EOF) + ERREXIT(cinfo, JERR_INPUT_EOF); + *out_ptr++ = (JSAMPLE) c; + } + } + if (progress != NULL) + progress->completed_extra_passes++; + + /* Set up to read from the virtual array in top-to-bottom order */ + switch (source->bits_per_pixel) { + case 8: + source->pub.get_pixel_rows = get_8bit_row; + break; + case 24: + source->pub.get_pixel_rows = get_24bit_row; + break; + default: + ERREXIT(cinfo, JERR_BMP_BADDEPTH); + } + source->source_row = cinfo->image_height; + + /* And read the first row */ + return (*source->pub.get_pixel_rows) (cinfo, sinfo); +} + + +/* + * Read the file header; return image size and component count. + */ + +METHODDEF(void) +start_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +{ + bmp_source_ptr source = (bmp_source_ptr) sinfo; + U_CHAR bmpfileheader[14]; + U_CHAR bmpinfoheader[64]; +#define GET_2B(array,offset) ((unsigned int) UCH(array[offset]) + \ + (((unsigned int) UCH(array[offset+1])) << 8)) +#define GET_4B(array,offset) ((INT32) UCH(array[offset]) + \ + (((INT32) UCH(array[offset+1])) << 8) + \ + (((INT32) UCH(array[offset+2])) << 16) + \ + (((INT32) UCH(array[offset+3])) << 24)) + INT32 bfOffBits; + INT32 headerSize; + INT32 biWidth = 0; /* initialize to avoid compiler warning */ + INT32 biHeight = 0; + unsigned int biPlanes; + INT32 biCompression; + INT32 biXPelsPerMeter,biYPelsPerMeter; + INT32 biClrUsed = 0; + int mapentrysize = 0; /* 0 indicates no colormap */ + INT32 bPad; + JDIMENSION row_width; + + /* Read and verify the bitmap file header */ + if (! ReadOK(source->pub.input_file, bmpfileheader, 14)) + ERREXIT(cinfo, JERR_INPUT_EOF); + if (GET_2B(bmpfileheader,0) != 0x4D42) /* 'BM' */ + ERREXIT(cinfo, JERR_BMP_NOT); + bfOffBits = (INT32) GET_4B(bmpfileheader,10); + /* We ignore the remaining fileheader fields */ + + /* The infoheader might be 12 bytes (OS/2 1.x), 40 bytes (Windows), + * or 64 bytes (OS/2 2.x). Check the first 4 bytes to find out which. + */ + if (! ReadOK(source->pub.input_file, bmpinfoheader, 4)) + ERREXIT(cinfo, JERR_INPUT_EOF); + headerSize = (INT32) GET_4B(bmpinfoheader,0); + if (headerSize < 12 || headerSize > 64) + ERREXIT(cinfo, JERR_BMP_BADHEADER); + if (! ReadOK(source->pub.input_file, bmpinfoheader+4, headerSize-4)) + ERREXIT(cinfo, JERR_INPUT_EOF); + + switch ((int) headerSize) { + case 12: + /* Decode OS/2 1.x header (Microsoft calls this a BITMAPCOREHEADER) */ + biWidth = (INT32) GET_2B(bmpinfoheader,4); + biHeight = (INT32) GET_2B(bmpinfoheader,6); + biPlanes = GET_2B(bmpinfoheader,8); + source->bits_per_pixel = (int) GET_2B(bmpinfoheader,10); + + switch (source->bits_per_pixel) { + case 8: /* colormapped image */ + mapentrysize = 3; /* OS/2 uses RGBTRIPLE colormap */ + TRACEMS2(cinfo, 1, JTRC_BMP_OS2_MAPPED, (int) biWidth, (int) biHeight); + break; + case 24: /* RGB image */ + TRACEMS2(cinfo, 1, JTRC_BMP_OS2, (int) biWidth, (int) biHeight); + break; + default: + ERREXIT(cinfo, JERR_BMP_BADDEPTH); + break; + } + if (biPlanes != 1) + ERREXIT(cinfo, JERR_BMP_BADPLANES); + break; + case 40: + case 64: + /* Decode Windows 3.x header (Microsoft calls this a BITMAPINFOHEADER) */ + /* or OS/2 2.x header, which has additional fields that we ignore */ + biWidth = GET_4B(bmpinfoheader,4); + biHeight = GET_4B(bmpinfoheader,8); + biPlanes = GET_2B(bmpinfoheader,12); + source->bits_per_pixel = (int) GET_2B(bmpinfoheader,14); + biCompression = GET_4B(bmpinfoheader,16); + biXPelsPerMeter = GET_4B(bmpinfoheader,24); + biYPelsPerMeter = GET_4B(bmpinfoheader,28); + biClrUsed = GET_4B(bmpinfoheader,32); + /* biSizeImage, biClrImportant fields are ignored */ + + switch (source->bits_per_pixel) { + case 8: /* colormapped image */ + mapentrysize = 4; /* Windows uses RGBQUAD colormap */ + TRACEMS2(cinfo, 1, JTRC_BMP_MAPPED, (int) biWidth, (int) biHeight); + break; + case 24: /* RGB image */ + TRACEMS2(cinfo, 1, JTRC_BMP, (int) biWidth, (int) biHeight); + break; + default: + ERREXIT(cinfo, JERR_BMP_BADDEPTH); + break; + } + if (biPlanes != 1) + ERREXIT(cinfo, JERR_BMP_BADPLANES); + if (biCompression != 0) + ERREXIT(cinfo, JERR_BMP_COMPRESSED); + + if (biXPelsPerMeter > 0 && biYPelsPerMeter > 0) { + /* Set JFIF density parameters from the BMP data */ + cinfo->X_density = (UINT16) (biXPelsPerMeter/100); /* 100 cm per meter */ + cinfo->Y_density = (UINT16) (biYPelsPerMeter/100); + cinfo->density_unit = 2; /* dots/cm */ + } + break; + default: + ERREXIT(cinfo, JERR_BMP_BADHEADER); + break; + } + + /* Compute distance to bitmap data --- will adjust for colormap below */ + bPad = bfOffBits - (headerSize + 14); + + /* Read the colormap, if any */ + if (mapentrysize > 0) { + if (biClrUsed <= 0) + biClrUsed = 256; /* assume it's 256 */ + else if (biClrUsed > 256) + ERREXIT(cinfo, JERR_BMP_BADCMAP); + /* Allocate space to store the colormap */ + source->colormap = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) biClrUsed, (JDIMENSION) 3); + /* and read it from the file */ + read_colormap(source, (int) biClrUsed, mapentrysize); + /* account for size of colormap */ + bPad -= biClrUsed * mapentrysize; + } + + /* Skip any remaining pad bytes */ + if (bPad < 0) /* incorrect bfOffBits value? */ + ERREXIT(cinfo, JERR_BMP_BADHEADER); + while (--bPad >= 0) { + (void) read_byte(source); + } + + /* Compute row width in file, including padding to 4-byte boundary */ + if (source->bits_per_pixel == 24) + row_width = (JDIMENSION) (biWidth * 3); + else + row_width = (JDIMENSION) biWidth; + while ((row_width & 3) != 0) row_width++; + source->row_width = row_width; + + /* Allocate space for inversion array, prepare for preload pass */ + source->whole_image = (*cinfo->mem->request_virt_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, + row_width, (JDIMENSION) biHeight, (JDIMENSION) 1); + source->pub.get_pixel_rows = preload_image; + if (cinfo->progress != NULL) { + cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress; + progress->total_extra_passes++; /* count file input as separate pass */ + } + + /* Allocate one-row buffer for returned data */ + source->pub.buffer = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) (biWidth * 3), (JDIMENSION) 1); + source->pub.buffer_height = 1; + + cinfo->in_color_space = JCS_RGB; + cinfo->input_components = 3; + cinfo->data_precision = 8; + cinfo->image_width = (JDIMENSION) biWidth; + cinfo->image_height = (JDIMENSION) biHeight; +} + + +/* + * Finish up at the end of the file. + */ + +METHODDEF(void) +finish_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +{ + /* no work */ +} + + +/* + * The module selection routine for BMP format input. + */ + +GLOBAL(cjpeg_source_ptr) +jinit_read_bmp (j_compress_ptr cinfo) +{ + bmp_source_ptr source; + + /* Create module interface object */ + source = (bmp_source_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(bmp_source_struct)); + source->cinfo = cinfo; /* make back link for subroutines */ + /* Fill in method ptrs, except get_pixel_rows which start_input sets */ + source->pub.start_input = start_input_bmp; + source->pub.finish_input = finish_input_bmp; + + return (cjpeg_source_ptr) source; +} + +#endif /* BMP_SUPPORTED */ diff --git a/lc-continuity/mk4/modimage/jpeg-6b/rdcolmap.c b/lc-continuity/mk4/modimage/jpeg-6b/rdcolmap.c new file mode 100644 index 0000000000000000000000000000000000000000..42b343763b59af25303d43462c8149e837694a5b --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/rdcolmap.c @@ -0,0 +1,253 @@ +/* + * rdcolmap.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file implements djpeg's "-map file" switch. It reads a source image + * and constructs a colormap to be supplied to the JPEG decompressor. + * + * Currently, these file formats are supported for the map file: + * GIF: the contents of the GIF's global colormap are used. + * PPM (either text or raw flavor): the entire file is read and + * each unique pixel value is entered in the map. + * Note that reading a large PPM file will be horrendously slow. + * Typically, a PPM-format map file should contain just one pixel + * of each desired color. Such a file can be extracted from an + * ordinary image PPM file with ppmtomap(1). + * + * Rescaling a PPM that has a maxval unequal to MAXJSAMPLE is not + * currently implemented. + */ + +#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ + +#ifdef QUANT_2PASS_SUPPORTED /* otherwise can't quantize to supplied map */ + +/* Portions of this code are based on the PBMPLUS library, which is: +** +** Copyright (C) 1988 by Jef Poskanzer. +** +** Permission to use, copy, modify, and distribute this software and its +** documentation for any purpose and without fee is hereby granted, provided +** that the above copyright notice appear in all copies and that both that +** copyright notice and this permission notice appear in supporting +** documentation. This software is provided "as is" without express or +** implied warranty. +*/ + + +/* + * Add a (potentially) new color to the color map. + */ + +LOCAL(void) +add_map_entry (j_decompress_ptr cinfo, int R, int G, int B) +{ + JSAMPROW colormap0 = cinfo->colormap[0]; + JSAMPROW colormap1 = cinfo->colormap[1]; + JSAMPROW colormap2 = cinfo->colormap[2]; + int ncolors = cinfo->actual_number_of_colors; + int index; + + /* Check for duplicate color. */ + for (index = 0; index < ncolors; index++) { + if (GETJSAMPLE(colormap0[index]) == R && + GETJSAMPLE(colormap1[index]) == G && + GETJSAMPLE(colormap2[index]) == B) + return; /* color is already in map */ + } + + /* Check for map overflow. */ + if (ncolors >= (MAXJSAMPLE+1)) + ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, (MAXJSAMPLE+1)); + + /* OK, add color to map. */ + colormap0[ncolors] = (JSAMPLE) R; + colormap1[ncolors] = (JSAMPLE) G; + colormap2[ncolors] = (JSAMPLE) B; + cinfo->actual_number_of_colors++; +} + + +/* + * Extract color map from a GIF file. + */ + +LOCAL(void) +read_gif_map (j_decompress_ptr cinfo, FILE * infile) +{ + int header[13]; + int i, colormaplen; + int R, G, B; + + /* Initial 'G' has already been read by read_color_map */ + /* Read the rest of the GIF header and logical screen descriptor */ + for (i = 1; i < 13; i++) { + if ((header[i] = getc(infile)) == EOF) + ERREXIT(cinfo, JERR_BAD_CMAP_FILE); + } + + /* Verify GIF Header */ + if (header[1] != 'I' || header[2] != 'F') + ERREXIT(cinfo, JERR_BAD_CMAP_FILE); + + /* There must be a global color map. */ + if ((header[10] & 0x80) == 0) + ERREXIT(cinfo, JERR_BAD_CMAP_FILE); + + /* OK, fetch it. */ + colormaplen = 2 << (header[10] & 0x07); + + for (i = 0; i < colormaplen; i++) { + R = getc(infile); + G = getc(infile); + B = getc(infile); + if (R == EOF || G == EOF || B == EOF) + ERREXIT(cinfo, JERR_BAD_CMAP_FILE); + add_map_entry(cinfo, + R << (BITS_IN_JSAMPLE-8), + G << (BITS_IN_JSAMPLE-8), + B << (BITS_IN_JSAMPLE-8)); + } +} + + +/* Support routines for reading PPM */ + + +LOCAL(int) +pbm_getc (FILE * infile) +/* Read next char, skipping over any comments */ +/* A comment/newline sequence is returned as a newline */ +{ + register int ch; + + ch = getc(infile); + if (ch == '#') { + do { + ch = getc(infile); + } while (ch != '\n' && ch != EOF); + } + return ch; +} + + +LOCAL(unsigned int) +read_pbm_integer (j_decompress_ptr cinfo, FILE * infile) +/* Read an unsigned decimal integer from the PPM file */ +/* Swallows one trailing character after the integer */ +/* Note that on a 16-bit-int machine, only values up to 64k can be read. */ +/* This should not be a problem in practice. */ +{ + register int ch; + register unsigned int val; + + /* Skip any leading whitespace */ + do { + ch = pbm_getc(infile); + if (ch == EOF) + ERREXIT(cinfo, JERR_BAD_CMAP_FILE); + } while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'); + + if (ch < '0' || ch > '9') + ERREXIT(cinfo, JERR_BAD_CMAP_FILE); + + val = ch - '0'; + while ((ch = pbm_getc(infile)) >= '0' && ch <= '9') { + val *= 10; + val += ch - '0'; + } + return val; +} + + +/* + * Extract color map from a PPM file. + */ + +LOCAL(void) +read_ppm_map (j_decompress_ptr cinfo, FILE * infile) +{ + int c; + unsigned int w, h, maxval, row, col; + int R, G, B; + + /* Initial 'P' has already been read by read_color_map */ + c = getc(infile); /* save format discriminator for a sec */ + + /* while we fetch the remaining header info */ + w = read_pbm_integer(cinfo, infile); + h = read_pbm_integer(cinfo, infile); + maxval = read_pbm_integer(cinfo, infile); + + if (w <= 0 || h <= 0 || maxval <= 0) /* error check */ + ERREXIT(cinfo, JERR_BAD_CMAP_FILE); + + /* For now, we don't support rescaling from an unusual maxval. */ + if (maxval != (unsigned int) MAXJSAMPLE) + ERREXIT(cinfo, JERR_BAD_CMAP_FILE); + + switch (c) { + case '3': /* it's a text-format PPM file */ + for (row = 0; row < h; row++) { + for (col = 0; col < w; col++) { + R = read_pbm_integer(cinfo, infile); + G = read_pbm_integer(cinfo, infile); + B = read_pbm_integer(cinfo, infile); + add_map_entry(cinfo, R, G, B); + } + } + break; + + case '6': /* it's a raw-format PPM file */ + for (row = 0; row < h; row++) { + for (col = 0; col < w; col++) { + R = getc(infile); + G = getc(infile); + B = getc(infile); + if (R == EOF || G == EOF || B == EOF) + ERREXIT(cinfo, JERR_BAD_CMAP_FILE); + add_map_entry(cinfo, R, G, B); + } + } + break; + + default: + ERREXIT(cinfo, JERR_BAD_CMAP_FILE); + break; + } +} + + +/* + * Main entry point from djpeg.c. + * Input: opened input file (from file name argument on command line). + * Output: colormap and actual_number_of_colors fields are set in cinfo. + */ + +GLOBAL(void) +read_color_map (j_decompress_ptr cinfo, FILE * infile) +{ + /* Allocate space for a color map of maximum supported size. */ + cinfo->colormap = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) (MAXJSAMPLE+1), (JDIMENSION) 3); + cinfo->actual_number_of_colors = 0; /* initialize map to empty */ + + /* Read first byte to determine file format */ + switch (getc(infile)) { + case 'G': + read_gif_map(cinfo, infile); + break; + case 'P': + read_ppm_map(cinfo, infile); + break; + default: + ERREXIT(cinfo, JERR_BAD_CMAP_FILE); + break; + } +} + +#endif /* QUANT_2PASS_SUPPORTED */ diff --git a/lc-continuity/mk4/modimage/jpeg-6b/rdgif.c b/lc-continuity/mk4/modimage/jpeg-6b/rdgif.c new file mode 100644 index 0000000000000000000000000000000000000000..b27c1675d763fde7d81591c3e521c02027690fe0 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/rdgif.c @@ -0,0 +1,38 @@ +/* + * rdgif.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains routines to read input images in GIF format. + * + ***************************************************************************** + * NOTE: to avoid entanglements with Unisys' patent on LZW compression, * + * the ability to read GIF files has been removed from the IJG distribution. * + * Sorry about that. * + ***************************************************************************** + * + * We are required to state that + * "The Graphics Interchange Format(c) is the Copyright property of + * CompuServe Incorporated. GIF(sm) is a Service Mark property of + * CompuServe Incorporated." + */ + +#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ + +#ifdef GIF_SUPPORTED + +/* + * The module selection routine for GIF format input. + */ + +GLOBAL(cjpeg_source_ptr) +jinit_read_gif (j_compress_ptr cinfo) +{ + fprintf(stderr, "GIF input is unsupported for legal reasons. Sorry.\n"); + exit(EXIT_FAILURE); + return NULL; /* keep compiler happy */ +} + +#endif /* GIF_SUPPORTED */ diff --git a/lc-continuity/mk4/modimage/jpeg-6b/rdjpgcom.1 b/lc-continuity/mk4/modimage/jpeg-6b/rdjpgcom.1 new file mode 100644 index 0000000000000000000000000000000000000000..2bba04e1a242182a3ef279367610a85745d67e7a --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/rdjpgcom.1 @@ -0,0 +1,54 @@ +.TH RDJPGCOM 1 "11 October 1997" +.SH NAME +rdjpgcom \- display text comments from a JPEG file +.SH SYNOPSIS +.B rdjpgcom +[ +.B \-verbose +] +[ +.I filename +] +.LP +.SH DESCRIPTION +.LP +.B rdjpgcom +reads the named JPEG/JFIF file, or the standard input if no file is named, +and prints any text comments found in the file on the standard output. +.PP +The JPEG standard allows "comment" (COM) blocks to occur within a JPEG file. +Although the standard doesn't actually define what COM blocks are for, they +are widely used to hold user-supplied text strings. This lets you add +annotations, titles, index terms, etc to your JPEG files, and later retrieve +them as text. COM blocks do not interfere with the image stored in the JPEG +file. The maximum size of a COM block is 64K, but you can have as many of +them as you like in one JPEG file. +.SH OPTIONS +.TP +.B \-verbose +Causes +.B rdjpgcom +to also display the JPEG image dimensions. +.PP +Switch names may be abbreviated, and are not case sensitive. +.SH HINTS +.B rdjpgcom +does not depend on the IJG JPEG library. Its source code is intended as an +illustration of the minimum amount of code required to parse a JPEG file +header correctly. +.PP +In +.B \-verbose +mode, +.B rdjpgcom +will also attempt to print the contents of any "APP12" markers as text. +Some digital cameras produce APP12 markers containing useful textual +information. If you like, you can modify the source code to print +other APPn marker types as well. +.SH SEE ALSO +.BR cjpeg (1), +.BR djpeg (1), +.BR jpegtran (1), +.BR wrjpgcom (1) +.SH AUTHOR +Independent JPEG Group diff --git a/lc-continuity/mk4/modimage/jpeg-6b/rdjpgcom.c b/lc-continuity/mk4/modimage/jpeg-6b/rdjpgcom.c new file mode 100644 index 0000000000000000000000000000000000000000..ffe6fc6218d3c0bfe449bdf0f6984f88ba278891 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/rdjpgcom.c @@ -0,0 +1,496 @@ +/* + * rdjpgcom.c + * + * Copyright (C) 1994-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a very simple stand-alone application that displays + * the text in COM (comment) markers in a JFIF file. + * This may be useful as an example of the minimum logic needed to parse + * JPEG markers. + */ + +#define JPEG_CJPEG_DJPEG /* to get the command-line config symbols */ +#include "jinclude.h" /* get auto-config symbols, */ + +#include /* to declare isupper(), tolower() */ +#ifdef USE_SETMODE +#include /* to declare setmode()'s parameter macros */ +/* If you have setmode() but not , just delete this line: */ +#include /* to declare setmode() */ +#endif + +#ifdef USE_CCOMMAND /* command-line reader for Macintosh */ +#ifdef __MWERKS__ +#include /* Metrowerks needs this */ +#include /* ... and this */ +#endif +#ifdef THINK_C +#include /* Think declares it here */ +#endif +#endif + +#ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */ +#define READ_BINARY "r" +#else +#ifdef VMS /* VMS is very nonstandard */ +#define READ_BINARY "rb", "ctx=stm" +#else /* standard ANSI-compliant case */ +#define READ_BINARY "rb" +#endif +#endif + +#ifndef EXIT_FAILURE /* define exit() codes if not provided */ +#define EXIT_FAILURE 1 +#endif +#ifndef EXIT_SUCCESS +#ifdef VMS +#define EXIT_SUCCESS 1 /* VMS is very nonstandard */ +#else +#define EXIT_SUCCESS 0 +#endif +#endif + + +/* + * These macros are used to read the input file. + * To reuse this code in another application, you might need to change these. + */ + +static FILE * infile; /* input JPEG file */ + +/* Return next input byte, or EOF if no more */ +#define NEXTBYTE() getc(infile) + + +/* Error exit handler */ +#define ERREXIT(msg) (fprintf(stderr, "%s\n", msg), exit(EXIT_FAILURE)) + + +/* Read one byte, testing for EOF */ +static int +read_1_byte (void) +{ + int c; + + c = NEXTBYTE(); + if (c == EOF) + ERREXIT("Premature EOF in JPEG file"); + return c; +} + +/* Read 2 bytes, convert to unsigned int */ +/* All 2-byte quantities in JPEG markers are MSB first */ +static unsigned int +read_2_bytes (void) +{ + int c1, c2; + + c1 = NEXTBYTE(); + if (c1 == EOF) + ERREXIT("Premature EOF in JPEG file"); + c2 = NEXTBYTE(); + if (c2 == EOF) + ERREXIT("Premature EOF in JPEG file"); + return (((unsigned int) c1) << 8) + ((unsigned int) c2); +} + + +/* + * JPEG markers consist of one or more 0xFF bytes, followed by a marker + * code byte (which is not an FF). Here are the marker codes of interest + * in this program. (See jdmarker.c for a more complete list.) + */ + +#define M_SOF0 0xC0 /* Start Of Frame N */ +#define M_SOF1 0xC1 /* N indicates which compression process */ +#define M_SOF2 0xC2 /* Only SOF0-SOF2 are now in common use */ +#define M_SOF3 0xC3 +#define M_SOF5 0xC5 /* NB: codes C4 and CC are NOT SOF markers */ +#define M_SOF6 0xC6 +#define M_SOF7 0xC7 +#define M_SOF9 0xC9 +#define M_SOF10 0xCA +#define M_SOF11 0xCB +#define M_SOF13 0xCD +#define M_SOF14 0xCE +#define M_SOF15 0xCF +#define M_SOI 0xD8 /* Start Of Image (beginning of datastream) */ +#define M_EOI 0xD9 /* End Of Image (end of datastream) */ +#define M_SOS 0xDA /* Start Of Scan (begins compressed data) */ +#define M_APP0 0xE0 /* Application-specific marker, type N */ +#define M_APP12 0xEC /* (we don't bother to list all 16 APPn's) */ +#define M_COM 0xFE /* COMment */ + + +/* + * Find the next JPEG marker and return its marker code. + * We expect at least one FF byte, possibly more if the compressor used FFs + * to pad the file. + * There could also be non-FF garbage between markers. The treatment of such + * garbage is unspecified; we choose to skip over it but emit a warning msg. + * NB: this routine must not be used after seeing SOS marker, since it will + * not deal correctly with FF/00 sequences in the compressed image data... + */ + +static int +next_marker (void) +{ + int c; + int discarded_bytes = 0; + + /* Find 0xFF byte; count and skip any non-FFs. */ + c = read_1_byte(); + while (c != 0xFF) { + discarded_bytes++; + c = read_1_byte(); + } + /* Get marker code byte, swallowing any duplicate FF bytes. Extra FFs + * are legal as pad bytes, so don't count them in discarded_bytes. + */ + do { + c = read_1_byte(); + } while (c == 0xFF); + + if (discarded_bytes != 0) { + fprintf(stderr, "Warning: garbage data found in JPEG file\n"); + } + + return c; +} + + +/* + * Read the initial marker, which should be SOI. + * For a JFIF file, the first two bytes of the file should be literally + * 0xFF M_SOI. To be more general, we could use next_marker, but if the + * input file weren't actually JPEG at all, next_marker might read the whole + * file and then return a misleading error message... + */ + +static int +first_marker (void) +{ + int c1, c2; + + c1 = NEXTBYTE(); + c2 = NEXTBYTE(); + if (c1 != 0xFF || c2 != M_SOI) + ERREXIT("Not a JPEG file"); + return c2; +} + + +/* + * Most types of marker are followed by a variable-length parameter segment. + * This routine skips over the parameters for any marker we don't otherwise + * want to process. + * Note that we MUST skip the parameter segment explicitly in order not to + * be fooled by 0xFF bytes that might appear within the parameter segment; + * such bytes do NOT introduce new markers. + */ + +static void +skip_variable (void) +/* Skip over an unknown or uninteresting variable-length marker */ +{ + unsigned int length; + + /* Get the marker parameter length count */ + length = read_2_bytes(); + /* Length includes itself, so must be at least 2 */ + if (length < 2) + ERREXIT("Erroneous JPEG marker length"); + length -= 2; + /* Skip over the remaining bytes */ + while (length > 0) { + (void) read_1_byte(); + length--; + } +} + + +/* + * Process a COM marker. + * We want to print out the marker contents as legible text; + * we must guard against non-text junk and varying newline representations. + */ + +static void +process_COM (void) +{ + unsigned int length; + int ch; + int lastch = 0; + + /* Get the marker parameter length count */ + length = read_2_bytes(); + /* Length includes itself, so must be at least 2 */ + if (length < 2) + ERREXIT("Erroneous JPEG marker length"); + length -= 2; + + while (length > 0) { + ch = read_1_byte(); + /* Emit the character in a readable form. + * Nonprintables are converted to \nnn form, + * while \ is converted to \\. + * Newlines in CR, CR/LF, or LF form will be printed as one newline. + */ + if (ch == '\r') { + printf("\n"); + } else if (ch == '\n') { + if (lastch != '\r') + printf("\n"); + } else if (ch == '\\') { + printf("\\\\"); + } else if (isprint(ch)) { + putc(ch, stdout); + } else { + printf("\\%03o", ch); + } + lastch = ch; + length--; + } + printf("\n"); +} + + +/* + * Process a SOFn marker. + * This code is only needed if you want to know the image dimensions... + */ + +static void +process_SOFn (int marker) +{ + unsigned int length; + unsigned int image_height, image_width; + int data_precision, num_components; + const char * process; + int ci; + + length = read_2_bytes(); /* usual parameter length count */ + + data_precision = read_1_byte(); + image_height = read_2_bytes(); + image_width = read_2_bytes(); + num_components = read_1_byte(); + + switch (marker) { + case M_SOF0: process = "Baseline"; break; + case M_SOF1: process = "Extended sequential"; break; + case M_SOF2: process = "Progressive"; break; + case M_SOF3: process = "Lossless"; break; + case M_SOF5: process = "Differential sequential"; break; + case M_SOF6: process = "Differential progressive"; break; + case M_SOF7: process = "Differential lossless"; break; + case M_SOF9: process = "Extended sequential, arithmetic coding"; break; + case M_SOF10: process = "Progressive, arithmetic coding"; break; + case M_SOF11: process = "Lossless, arithmetic coding"; break; + case M_SOF13: process = "Differential sequential, arithmetic coding"; break; + case M_SOF14: process = "Differential progressive, arithmetic coding"; break; + case M_SOF15: process = "Differential lossless, arithmetic coding"; break; + default: process = "Unknown"; break; + } + + printf("JPEG image is %uw * %uh, %d color components, %d bits per sample\n", + image_width, image_height, num_components, data_precision); + printf("JPEG process: %s\n", process); + + if (length != (unsigned int) (8 + num_components * 3)) + ERREXIT("Bogus SOF marker length"); + + for (ci = 0; ci < num_components; ci++) { + (void) read_1_byte(); /* Component ID code */ + (void) read_1_byte(); /* H, V sampling factors */ + (void) read_1_byte(); /* Quantization table number */ + } +} + + +/* + * Parse the marker stream until SOS or EOI is seen; + * display any COM markers. + * While the companion program wrjpgcom will always insert COM markers before + * SOFn, other implementations might not, so we scan to SOS before stopping. + * If we were only interested in the image dimensions, we would stop at SOFn. + * (Conversely, if we only cared about COM markers, there would be no need + * for special code to handle SOFn; we could treat it like other markers.) + */ + +static int +scan_JPEG_header (int verbose) +{ + int marker; + + /* Expect SOI at start of file */ + if (first_marker() != M_SOI) + ERREXIT("Expected SOI marker first"); + + /* Scan miscellaneous markers until we reach SOS. */ + for (;;) { + marker = next_marker(); + switch (marker) { + /* Note that marker codes 0xC4, 0xC8, 0xCC are not, and must not be, + * treated as SOFn. C4 in particular is actually DHT. + */ + case M_SOF0: /* Baseline */ + case M_SOF1: /* Extended sequential, Huffman */ + case M_SOF2: /* Progressive, Huffman */ + case M_SOF3: /* Lossless, Huffman */ + case M_SOF5: /* Differential sequential, Huffman */ + case M_SOF6: /* Differential progressive, Huffman */ + case M_SOF7: /* Differential lossless, Huffman */ + case M_SOF9: /* Extended sequential, arithmetic */ + case M_SOF10: /* Progressive, arithmetic */ + case M_SOF11: /* Lossless, arithmetic */ + case M_SOF13: /* Differential sequential, arithmetic */ + case M_SOF14: /* Differential progressive, arithmetic */ + case M_SOF15: /* Differential lossless, arithmetic */ + if (verbose) + process_SOFn(marker); + else + skip_variable(); + break; + + case M_SOS: /* stop before hitting compressed data */ + return marker; + + case M_EOI: /* in case it's a tables-only JPEG stream */ + return marker; + + case M_COM: + process_COM(); + break; + + case M_APP12: + /* Some digital camera makers put useful textual information into + * APP12 markers, so we print those out too when in -verbose mode. + */ + if (verbose) { + printf("APP12 contains:\n"); + process_COM(); + } else + skip_variable(); + break; + + default: /* Anything else just gets skipped */ + skip_variable(); /* we assume it has a parameter count... */ + break; + } + } /* end loop */ +} + + +/* Command line parsing code */ + +static const char * progname; /* program name for error messages */ + + +static void +usage (void) +/* complain about bad command line */ +{ + fprintf(stderr, "rdjpgcom displays any textual comments in a JPEG file.\n"); + + fprintf(stderr, "Usage: %s [switches] [inputfile]\n", progname); + + fprintf(stderr, "Switches (names may be abbreviated):\n"); + fprintf(stderr, " -verbose Also display dimensions of JPEG image\n"); + + exit(EXIT_FAILURE); +} + + +static int +keymatch (char * arg, const char * keyword, int minchars) +/* Case-insensitive matching of (possibly abbreviated) keyword switches. */ +/* keyword is the constant keyword (must be lower case already), */ +/* minchars is length of minimum legal abbreviation. */ +{ + register int ca, ck; + register int nmatched = 0; + + while ((ca = *arg++) != '\0') { + if ((ck = *keyword++) == '\0') + return 0; /* arg longer than keyword, no good */ + if (isupper(ca)) /* force arg to lcase (assume ck is already) */ + ca = tolower(ca); + if (ca != ck) + return 0; /* no good */ + nmatched++; /* count matched characters */ + } + /* reached end of argument; fail if it's too short for unique abbrev */ + if (nmatched < minchars) + return 0; + return 1; /* A-OK */ +} + + +/* + * The main program. + */ + +int +main (int argc, char **argv) +{ + int argn; + char * arg; + int verbose = 0; + + /* On Mac, fetch a command line. */ +#ifdef USE_CCOMMAND + argc = ccommand(&argv); +#endif + + progname = argv[0]; + if (progname == NULL || progname[0] == 0) + progname = "rdjpgcom"; /* in case C library doesn't provide it */ + + /* Parse switches, if any */ + for (argn = 1; argn < argc; argn++) { + arg = argv[argn]; + if (arg[0] != '-') + break; /* not switch, must be file name */ + arg++; /* advance over '-' */ + if (keymatch(arg, "verbose", 1)) { + verbose++; + } else + usage(); + } + + /* Open the input file. */ + /* Unix style: expect zero or one file name */ + if (argn < argc-1) { + fprintf(stderr, "%s: only one input file\n", progname); + usage(); + } + if (argn < argc) { + if ((infile = fopen(argv[argn], READ_BINARY)) == NULL) { + fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]); + exit(EXIT_FAILURE); + } + } else { + /* default input file is stdin */ +#ifdef USE_SETMODE /* need to hack file mode? */ + setmode(fileno(stdin), O_BINARY); +#endif +#ifdef USE_FDOPEN /* need to re-open in binary mode? */ + if ((infile = fdopen(fileno(stdin), READ_BINARY)) == NULL) { + fprintf(stderr, "%s: can't open stdin\n", progname); + exit(EXIT_FAILURE); + } +#else + infile = stdin; +#endif + } + + /* Scan the JPEG headers. */ + (void) scan_JPEG_header(verbose); + + /* All done. */ + exit(EXIT_SUCCESS); + return 0; /* suppress no-return-value warnings */ +} diff --git a/lc-continuity/mk4/modimage/jpeg-6b/rdppm.c b/lc-continuity/mk4/modimage/jpeg-6b/rdppm.c new file mode 100644 index 0000000000000000000000000000000000000000..1df35c1b3a441ac3092e06fc873d823f867eef5c --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/rdppm.c @@ -0,0 +1,458 @@ +/* + * rdppm.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains routines to read input images in PPM/PGM format. + * The extended 2-byte-per-sample raw PPM/PGM formats are supported. + * The PBMPLUS library is NOT required to compile this software + * (but it is highly useful as a set of PPM image manipulation programs). + * + * These routines may need modification for non-Unix environments or + * specialized applications. As they stand, they assume input from + * an ordinary stdio stream. They further assume that reading begins + * at the start of the file; start_input may need work if the + * user interface has already read some data (e.g., to determine that + * the file is indeed PPM format). + */ + +#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ + +#ifdef PPM_SUPPORTED + + +/* Portions of this code are based on the PBMPLUS library, which is: +** +** Copyright (C) 1988 by Jef Poskanzer. +** +** Permission to use, copy, modify, and distribute this software and its +** documentation for any purpose and without fee is hereby granted, provided +** that the above copyright notice appear in all copies and that both that +** copyright notice and this permission notice appear in supporting +** documentation. This software is provided "as is" without express or +** implied warranty. +*/ + + +/* Macros to deal with unsigned chars as efficiently as compiler allows */ + +#ifdef HAVE_UNSIGNED_CHAR +typedef unsigned char U_CHAR; +#define UCH(x) ((int) (x)) +#else /* !HAVE_UNSIGNED_CHAR */ +#ifdef CHAR_IS_UNSIGNED +typedef char U_CHAR; +#define UCH(x) ((int) (x)) +#else +typedef char U_CHAR; +#define UCH(x) ((int) (x) & 0xFF) +#endif +#endif /* HAVE_UNSIGNED_CHAR */ + + +#define ReadOK(file,buffer,len) (JFREAD(file,buffer,len) == ((size_t) (len))) + + +/* + * On most systems, reading individual bytes with getc() is drastically less + * efficient than buffering a row at a time with fread(). On PCs, we must + * allocate the buffer in near data space, because we are assuming small-data + * memory model, wherein fread() can't reach far memory. If you need to + * process very wide images on a PC, you might have to compile in large-memory + * model, or else replace fread() with a getc() loop --- which will be much + * slower. + */ + + +/* Private version of data source object */ + +typedef struct { + struct cjpeg_source_struct pub; /* public fields */ + + U_CHAR *iobuffer; /* non-FAR pointer to I/O buffer */ + JSAMPROW pixrow; /* FAR pointer to same */ + size_t buffer_width; /* width of I/O buffer */ + JSAMPLE *rescale; /* => maxval-remapping array, or NULL */ +} ppm_source_struct; + +typedef ppm_source_struct * ppm_source_ptr; + + +LOCAL(int) +pbm_getc (FILE * infile) +/* Read next char, skipping over any comments */ +/* A comment/newline sequence is returned as a newline */ +{ + register int ch; + + ch = getc(infile); + if (ch == '#') { + do { + ch = getc(infile); + } while (ch != '\n' && ch != EOF); + } + return ch; +} + + +LOCAL(unsigned int) +read_pbm_integer (j_compress_ptr cinfo, FILE * infile) +/* Read an unsigned decimal integer from the PPM file */ +/* Swallows one trailing character after the integer */ +/* Note that on a 16-bit-int machine, only values up to 64k can be read. */ +/* This should not be a problem in practice. */ +{ + register int ch; + register unsigned int val; + + /* Skip any leading whitespace */ + do { + ch = pbm_getc(infile); + if (ch == EOF) + ERREXIT(cinfo, JERR_INPUT_EOF); + } while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'); + + if (ch < '0' || ch > '9') + ERREXIT(cinfo, JERR_PPM_NONNUMERIC); + + val = ch - '0'; + while ((ch = pbm_getc(infile)) >= '0' && ch <= '9') { + val *= 10; + val += ch - '0'; + } + return val; +} + + +/* + * Read one row of pixels. + * + * We provide several different versions depending on input file format. + * In all cases, input is scaled to the size of JSAMPLE. + * + * A really fast path is provided for reading byte/sample raw files with + * maxval = MAXJSAMPLE, which is the normal case for 8-bit data. + */ + + +METHODDEF(JDIMENSION) +get_text_gray_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading text-format PGM files with any maxval */ +{ + ppm_source_ptr source = (ppm_source_ptr) sinfo; + FILE * infile = source->pub.input_file; + register JSAMPROW ptr; + register JSAMPLE *rescale = source->rescale; + JDIMENSION col; + + ptr = source->pub.buffer[0]; + for (col = cinfo->image_width; col > 0; col--) { + *ptr++ = rescale[read_pbm_integer(cinfo, infile)]; + } + return 1; +} + + +METHODDEF(JDIMENSION) +get_text_rgb_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading text-format PPM files with any maxval */ +{ + ppm_source_ptr source = (ppm_source_ptr) sinfo; + FILE * infile = source->pub.input_file; + register JSAMPROW ptr; + register JSAMPLE *rescale = source->rescale; + JDIMENSION col; + + ptr = source->pub.buffer[0]; + for (col = cinfo->image_width; col > 0; col--) { + *ptr++ = rescale[read_pbm_integer(cinfo, infile)]; + *ptr++ = rescale[read_pbm_integer(cinfo, infile)]; + *ptr++ = rescale[read_pbm_integer(cinfo, infile)]; + } + return 1; +} + + +METHODDEF(JDIMENSION) +get_scaled_gray_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading raw-byte-format PGM files with any maxval */ +{ + ppm_source_ptr source = (ppm_source_ptr) sinfo; + register JSAMPROW ptr; + register U_CHAR * bufferptr; + register JSAMPLE *rescale = source->rescale; + JDIMENSION col; + + if (! ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width)) + ERREXIT(cinfo, JERR_INPUT_EOF); + ptr = source->pub.buffer[0]; + bufferptr = source->iobuffer; + for (col = cinfo->image_width; col > 0; col--) { + *ptr++ = rescale[UCH(*bufferptr++)]; + } + return 1; +} + + +METHODDEF(JDIMENSION) +get_scaled_rgb_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading raw-byte-format PPM files with any maxval */ +{ + ppm_source_ptr source = (ppm_source_ptr) sinfo; + register JSAMPROW ptr; + register U_CHAR * bufferptr; + register JSAMPLE *rescale = source->rescale; + JDIMENSION col; + + if (! ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width)) + ERREXIT(cinfo, JERR_INPUT_EOF); + ptr = source->pub.buffer[0]; + bufferptr = source->iobuffer; + for (col = cinfo->image_width; col > 0; col--) { + *ptr++ = rescale[UCH(*bufferptr++)]; + *ptr++ = rescale[UCH(*bufferptr++)]; + *ptr++ = rescale[UCH(*bufferptr++)]; + } + return 1; +} + + +METHODDEF(JDIMENSION) +get_raw_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading raw-byte-format files with maxval = MAXJSAMPLE. + * In this case we just read right into the JSAMPLE buffer! + * Note that same code works for PPM and PGM files. + */ +{ + ppm_source_ptr source = (ppm_source_ptr) sinfo; + + if (! ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width)) + ERREXIT(cinfo, JERR_INPUT_EOF); + return 1; +} + + +METHODDEF(JDIMENSION) +get_word_gray_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading raw-word-format PGM files with any maxval */ +{ + ppm_source_ptr source = (ppm_source_ptr) sinfo; + register JSAMPROW ptr; + register U_CHAR * bufferptr; + register JSAMPLE *rescale = source->rescale; + JDIMENSION col; + + if (! ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width)) + ERREXIT(cinfo, JERR_INPUT_EOF); + ptr = source->pub.buffer[0]; + bufferptr = source->iobuffer; + for (col = cinfo->image_width; col > 0; col--) { + register int temp; + temp = UCH(*bufferptr++); + temp |= UCH(*bufferptr++) << 8; + *ptr++ = rescale[temp]; + } + return 1; +} + + +METHODDEF(JDIMENSION) +get_word_rgb_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading raw-word-format PPM files with any maxval */ +{ + ppm_source_ptr source = (ppm_source_ptr) sinfo; + register JSAMPROW ptr; + register U_CHAR * bufferptr; + register JSAMPLE *rescale = source->rescale; + JDIMENSION col; + + if (! ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width)) + ERREXIT(cinfo, JERR_INPUT_EOF); + ptr = source->pub.buffer[0]; + bufferptr = source->iobuffer; + for (col = cinfo->image_width; col > 0; col--) { + register int temp; + temp = UCH(*bufferptr++); + temp |= UCH(*bufferptr++) << 8; + *ptr++ = rescale[temp]; + temp = UCH(*bufferptr++); + temp |= UCH(*bufferptr++) << 8; + *ptr++ = rescale[temp]; + temp = UCH(*bufferptr++); + temp |= UCH(*bufferptr++) << 8; + *ptr++ = rescale[temp]; + } + return 1; +} + + +/* + * Read the file header; return image size and component count. + */ + +METHODDEF(void) +start_input_ppm (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +{ + ppm_source_ptr source = (ppm_source_ptr) sinfo; + int c; + unsigned int w, h, maxval; + boolean need_iobuffer, use_raw_buffer, need_rescale; + + if (getc(source->pub.input_file) != 'P') + ERREXIT(cinfo, JERR_PPM_NOT); + + c = getc(source->pub.input_file); /* subformat discriminator character */ + + /* detect unsupported variants (ie, PBM) before trying to read header */ + switch (c) { + case '2': /* it's a text-format PGM file */ + case '3': /* it's a text-format PPM file */ + case '5': /* it's a raw-format PGM file */ + case '6': /* it's a raw-format PPM file */ + break; + default: + ERREXIT(cinfo, JERR_PPM_NOT); + break; + } + + /* fetch the remaining header info */ + w = read_pbm_integer(cinfo, source->pub.input_file); + h = read_pbm_integer(cinfo, source->pub.input_file); + maxval = read_pbm_integer(cinfo, source->pub.input_file); + + if (w <= 0 || h <= 0 || maxval <= 0) /* error check */ + ERREXIT(cinfo, JERR_PPM_NOT); + + cinfo->data_precision = BITS_IN_JSAMPLE; /* we always rescale data to this */ + cinfo->image_width = (JDIMENSION) w; + cinfo->image_height = (JDIMENSION) h; + + /* initialize flags to most common settings */ + need_iobuffer = TRUE; /* do we need an I/O buffer? */ + use_raw_buffer = FALSE; /* do we map input buffer onto I/O buffer? */ + need_rescale = TRUE; /* do we need a rescale array? */ + + switch (c) { + case '2': /* it's a text-format PGM file */ + cinfo->input_components = 1; + cinfo->in_color_space = JCS_GRAYSCALE; + TRACEMS2(cinfo, 1, JTRC_PGM_TEXT, w, h); + source->pub.get_pixel_rows = get_text_gray_row; + need_iobuffer = FALSE; + break; + + case '3': /* it's a text-format PPM file */ + cinfo->input_components = 3; + cinfo->in_color_space = JCS_RGB; + TRACEMS2(cinfo, 1, JTRC_PPM_TEXT, w, h); + source->pub.get_pixel_rows = get_text_rgb_row; + need_iobuffer = FALSE; + break; + + case '5': /* it's a raw-format PGM file */ + cinfo->input_components = 1; + cinfo->in_color_space = JCS_GRAYSCALE; + TRACEMS2(cinfo, 1, JTRC_PGM, w, h); + if (maxval > 255) { + source->pub.get_pixel_rows = get_word_gray_row; + } else if (maxval == MAXJSAMPLE && SIZEOF(JSAMPLE) == SIZEOF(U_CHAR)) { + source->pub.get_pixel_rows = get_raw_row; + use_raw_buffer = TRUE; + need_rescale = FALSE; + } else { + source->pub.get_pixel_rows = get_scaled_gray_row; + } + break; + + case '6': /* it's a raw-format PPM file */ + cinfo->input_components = 3; + cinfo->in_color_space = JCS_RGB; + TRACEMS2(cinfo, 1, JTRC_PPM, w, h); + if (maxval > 255) { + source->pub.get_pixel_rows = get_word_rgb_row; + } else if (maxval == MAXJSAMPLE && SIZEOF(JSAMPLE) == SIZEOF(U_CHAR)) { + source->pub.get_pixel_rows = get_raw_row; + use_raw_buffer = TRUE; + need_rescale = FALSE; + } else { + source->pub.get_pixel_rows = get_scaled_rgb_row; + } + break; + } + + /* Allocate space for I/O buffer: 1 or 3 bytes or words/pixel. */ + if (need_iobuffer) { + source->buffer_width = (size_t) w * cinfo->input_components * + ((maxval<=255) ? SIZEOF(U_CHAR) : (2*SIZEOF(U_CHAR))); + source->iobuffer = (U_CHAR *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + source->buffer_width); + } + + /* Create compressor input buffer. */ + if (use_raw_buffer) { + /* For unscaled raw-input case, we can just map it onto the I/O buffer. */ + /* Synthesize a JSAMPARRAY pointer structure */ + /* Cast here implies near->far pointer conversion on PCs */ + source->pixrow = (JSAMPROW) source->iobuffer; + source->pub.buffer = & source->pixrow; + source->pub.buffer_height = 1; + } else { + /* Need to translate anyway, so make a separate sample buffer. */ + source->pub.buffer = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) w * cinfo->input_components, (JDIMENSION) 1); + source->pub.buffer_height = 1; + } + + /* Compute the rescaling array if required. */ + if (need_rescale) { + INT32 val, half_maxval; + + /* On 16-bit-int machines we have to be careful of maxval = 65535 */ + source->rescale = (JSAMPLE *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (size_t) (((long) maxval + 1L) * SIZEOF(JSAMPLE))); + half_maxval = maxval / 2; + for (val = 0; val <= (INT32) maxval; val++) { + /* The multiplication here must be done in 32 bits to avoid overflow */ + source->rescale[val] = (JSAMPLE) ((val*MAXJSAMPLE + half_maxval)/maxval); + } + } +} + + +/* + * Finish up at the end of the file. + */ + +METHODDEF(void) +finish_input_ppm (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +{ + /* no work */ +} + + +/* + * The module selection routine for PPM format input. + */ + +GLOBAL(cjpeg_source_ptr) +jinit_read_ppm (j_compress_ptr cinfo) +{ + ppm_source_ptr source; + + /* Create module interface object */ + source = (ppm_source_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(ppm_source_struct)); + /* Fill in method ptrs, except get_pixel_rows which start_input sets */ + source->pub.start_input = start_input_ppm; + source->pub.finish_input = finish_input_ppm; + + return (cjpeg_source_ptr) source; +} + +#endif /* PPM_SUPPORTED */ diff --git a/lc-continuity/mk4/modimage/jpeg-6b/rdrle.c b/lc-continuity/mk4/modimage/jpeg-6b/rdrle.c new file mode 100644 index 0000000000000000000000000000000000000000..542bc37490cc563f89da25a686144099984496d8 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/rdrle.c @@ -0,0 +1,387 @@ +/* + * rdrle.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains routines to read input images in Utah RLE format. + * The Utah Raster Toolkit library is required (version 3.1 or later). + * + * These routines may need modification for non-Unix environments or + * specialized applications. As they stand, they assume input from + * an ordinary stdio stream. They further assume that reading begins + * at the start of the file; start_input may need work if the + * user interface has already read some data (e.g., to determine that + * the file is indeed RLE format). + * + * Based on code contributed by Mike Lijewski, + * with updates from Robert Hutchinson. + */ + +#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ + +#ifdef RLE_SUPPORTED + +/* rle.h is provided by the Utah Raster Toolkit. */ + +#include + +/* + * We assume that JSAMPLE has the same representation as rle_pixel, + * to wit, "unsigned char". Hence we can't cope with 12- or 16-bit samples. + */ + +#if BITS_IN_JSAMPLE != 8 + Sorry, this code only copes with 8-bit JSAMPLEs. /* deliberate syntax err */ +#endif + +/* + * We support the following types of RLE files: + * + * GRAYSCALE - 8 bits, no colormap + * MAPPEDGRAY - 8 bits, 1 channel colomap + * PSEUDOCOLOR - 8 bits, 3 channel colormap + * TRUECOLOR - 24 bits, 3 channel colormap + * DIRECTCOLOR - 24 bits, no colormap + * + * For now, we ignore any alpha channel in the image. + */ + +typedef enum + { GRAYSCALE, MAPPEDGRAY, PSEUDOCOLOR, TRUECOLOR, DIRECTCOLOR } rle_kind; + + +/* + * Since RLE stores scanlines bottom-to-top, we have to invert the image + * to conform to JPEG's top-to-bottom order. To do this, we read the + * incoming image into a virtual array on the first get_pixel_rows call, + * then fetch the required row from the virtual array on subsequent calls. + */ + +typedef struct _rle_source_struct * rle_source_ptr; + +typedef struct _rle_source_struct { + struct cjpeg_source_struct pub; /* public fields */ + + rle_kind visual; /* actual type of input file */ + jvirt_sarray_ptr image; /* virtual array to hold the image */ + JDIMENSION row; /* current row # in the virtual array */ + rle_hdr header; /* Input file information */ + rle_pixel** rle_row; /* holds a row returned by rle_getrow() */ + +} rle_source_struct; + + +/* + * Read the file header; return image size and component count. + */ + +METHODDEF(void) +start_input_rle (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +{ + rle_source_ptr source = (rle_source_ptr) sinfo; + JDIMENSION width, height; +#ifdef PROGRESS_REPORT + cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress; +#endif + + /* Use RLE library routine to get the header info */ + source->header = *rle_hdr_init(NULL); + source->header.rle_file = source->pub.input_file; + switch (rle_get_setup(&(source->header))) { + case RLE_SUCCESS: + /* A-OK */ + break; + case RLE_NOT_RLE: + ERREXIT(cinfo, JERR_RLE_NOT); + break; + case RLE_NO_SPACE: + ERREXIT(cinfo, JERR_RLE_MEM); + break; + case RLE_EMPTY: + ERREXIT(cinfo, JERR_RLE_EMPTY); + break; + case RLE_EOF: + ERREXIT(cinfo, JERR_RLE_EOF); + break; + default: + ERREXIT(cinfo, JERR_RLE_BADERROR); + break; + } + + /* Figure out what we have, set private vars and return values accordingly */ + + width = source->header.xmax - source->header.xmin + 1; + height = source->header.ymax - source->header.ymin + 1; + source->header.xmin = 0; /* realign horizontally */ + source->header.xmax = width-1; + + cinfo->image_width = width; + cinfo->image_height = height; + cinfo->data_precision = 8; /* we can only handle 8 bit data */ + + if (source->header.ncolors == 1 && source->header.ncmap == 0) { + source->visual = GRAYSCALE; + TRACEMS2(cinfo, 1, JTRC_RLE_GRAY, width, height); + } else if (source->header.ncolors == 1 && source->header.ncmap == 1) { + source->visual = MAPPEDGRAY; + TRACEMS3(cinfo, 1, JTRC_RLE_MAPGRAY, width, height, + 1 << source->header.cmaplen); + } else if (source->header.ncolors == 1 && source->header.ncmap == 3) { + source->visual = PSEUDOCOLOR; + TRACEMS3(cinfo, 1, JTRC_RLE_MAPPED, width, height, + 1 << source->header.cmaplen); + } else if (source->header.ncolors == 3 && source->header.ncmap == 3) { + source->visual = TRUECOLOR; + TRACEMS3(cinfo, 1, JTRC_RLE_FULLMAP, width, height, + 1 << source->header.cmaplen); + } else if (source->header.ncolors == 3 && source->header.ncmap == 0) { + source->visual = DIRECTCOLOR; + TRACEMS2(cinfo, 1, JTRC_RLE, width, height); + } else + ERREXIT(cinfo, JERR_RLE_UNSUPPORTED); + + if (source->visual == GRAYSCALE || source->visual == MAPPEDGRAY) { + cinfo->in_color_space = JCS_GRAYSCALE; + cinfo->input_components = 1; + } else { + cinfo->in_color_space = JCS_RGB; + cinfo->input_components = 3; + } + + /* + * A place to hold each scanline while it's converted. + * (GRAYSCALE scanlines don't need converting) + */ + if (source->visual != GRAYSCALE) { + source->rle_row = (rle_pixel**) (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) width, (JDIMENSION) cinfo->input_components); + } + + /* request a virtual array to hold the image */ + source->image = (*cinfo->mem->request_virt_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, + (JDIMENSION) (width * source->header.ncolors), + (JDIMENSION) height, (JDIMENSION) 1); + +#ifdef PROGRESS_REPORT + if (progress != NULL) { + /* count file input as separate pass */ + progress->total_extra_passes++; + } +#endif + + source->pub.buffer_height = 1; +} + + +/* + * Read one row of pixels. + * Called only after load_image has read the image into the virtual array. + * Used for GRAYSCALE, MAPPEDGRAY, TRUECOLOR, and DIRECTCOLOR images. + */ + +METHODDEF(JDIMENSION) +get_rle_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +{ + rle_source_ptr source = (rle_source_ptr) sinfo; + + source->row--; + source->pub.buffer = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, source->image, source->row, (JDIMENSION) 1, FALSE); + + return 1; +} + +/* + * Read one row of pixels. + * Called only after load_image has read the image into the virtual array. + * Used for PSEUDOCOLOR images. + */ + +METHODDEF(JDIMENSION) +get_pseudocolor_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +{ + rle_source_ptr source = (rle_source_ptr) sinfo; + JSAMPROW src_row, dest_row; + JDIMENSION col; + rle_map *colormap; + int val; + + colormap = source->header.cmap; + dest_row = source->pub.buffer[0]; + source->row--; + src_row = * (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, source->image, source->row, (JDIMENSION) 1, FALSE); + + for (col = cinfo->image_width; col > 0; col--) { + val = GETJSAMPLE(*src_row++); + *dest_row++ = (JSAMPLE) (colormap[val ] >> 8); + *dest_row++ = (JSAMPLE) (colormap[val + 256] >> 8); + *dest_row++ = (JSAMPLE) (colormap[val + 512] >> 8); + } + + return 1; +} + + +/* + * Load the image into a virtual array. We have to do this because RLE + * files start at the lower left while the JPEG standard has them starting + * in the upper left. This is called the first time we want to get a row + * of input. What we do is load the RLE data into the array and then call + * the appropriate routine to read one row from the array. Before returning, + * we set source->pub.get_pixel_rows so that subsequent calls go straight to + * the appropriate row-reading routine. + */ + +METHODDEF(JDIMENSION) +load_image (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +{ + rle_source_ptr source = (rle_source_ptr) sinfo; + JDIMENSION row, col; + JSAMPROW scanline, red_ptr, green_ptr, blue_ptr; + rle_pixel **rle_row; + rle_map *colormap; + char channel; +#ifdef PROGRESS_REPORT + cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress; +#endif + + colormap = source->header.cmap; + rle_row = source->rle_row; + + /* Read the RLE data into our virtual array. + * We assume here that (a) rle_pixel is represented the same as JSAMPLE, + * and (b) we are not on a machine where FAR pointers differ from regular. + */ + RLE_CLR_BIT(source->header, RLE_ALPHA); /* don't read the alpha channel */ + +#ifdef PROGRESS_REPORT + if (progress != NULL) { + progress->pub.pass_limit = cinfo->image_height; + progress->pub.pass_counter = 0; + (*progress->pub.progress_monitor) ((j_common_ptr) cinfo); + } +#endif + + switch (source->visual) { + + case GRAYSCALE: + case PSEUDOCOLOR: + for (row = 0; row < cinfo->image_height; row++) { + rle_row = (rle_pixel **) (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, source->image, row, (JDIMENSION) 1, TRUE); + rle_getrow(&source->header, rle_row); +#ifdef PROGRESS_REPORT + if (progress != NULL) { + progress->pub.pass_counter++; + (*progress->pub.progress_monitor) ((j_common_ptr) cinfo); + } +#endif + } + break; + + case MAPPEDGRAY: + case TRUECOLOR: + for (row = 0; row < cinfo->image_height; row++) { + scanline = * (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, source->image, row, (JDIMENSION) 1, TRUE); + rle_row = source->rle_row; + rle_getrow(&source->header, rle_row); + + for (col = 0; col < cinfo->image_width; col++) { + for (channel = 0; channel < source->header.ncolors; channel++) { + *scanline++ = (JSAMPLE) + (colormap[GETJSAMPLE(rle_row[channel][col]) + 256 * channel] >> 8); + } + } + +#ifdef PROGRESS_REPORT + if (progress != NULL) { + progress->pub.pass_counter++; + (*progress->pub.progress_monitor) ((j_common_ptr) cinfo); + } +#endif + } + break; + + case DIRECTCOLOR: + for (row = 0; row < cinfo->image_height; row++) { + scanline = * (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, source->image, row, (JDIMENSION) 1, TRUE); + rle_getrow(&source->header, rle_row); + + red_ptr = rle_row[0]; + green_ptr = rle_row[1]; + blue_ptr = rle_row[2]; + + for (col = cinfo->image_width; col > 0; col--) { + *scanline++ = *red_ptr++; + *scanline++ = *green_ptr++; + *scanline++ = *blue_ptr++; + } + +#ifdef PROGRESS_REPORT + if (progress != NULL) { + progress->pub.pass_counter++; + (*progress->pub.progress_monitor) ((j_common_ptr) cinfo); + } +#endif + } + } + +#ifdef PROGRESS_REPORT + if (progress != NULL) + progress->completed_extra_passes++; +#endif + + /* Set up to call proper row-extraction routine in future */ + if (source->visual == PSEUDOCOLOR) { + source->pub.buffer = source->rle_row; + source->pub.get_pixel_rows = get_pseudocolor_row; + } else { + source->pub.get_pixel_rows = get_rle_row; + } + source->row = cinfo->image_height; + + /* And fetch the topmost (bottommost) row */ + return (*source->pub.get_pixel_rows) (cinfo, sinfo); +} + + +/* + * Finish up at the end of the file. + */ + +METHODDEF(void) +finish_input_rle (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +{ + /* no work */ +} + + +/* + * The module selection routine for RLE format input. + */ + +GLOBAL(cjpeg_source_ptr) +jinit_read_rle (j_compress_ptr cinfo) +{ + rle_source_ptr source; + + /* Create module interface object */ + source = (rle_source_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(rle_source_struct)); + /* Fill in method ptrs */ + source->pub.start_input = start_input_rle; + source->pub.finish_input = finish_input_rle; + source->pub.get_pixel_rows = load_image; + + return (cjpeg_source_ptr) source; +} + +#endif /* RLE_SUPPORTED */ diff --git a/lc-continuity/mk4/modimage/jpeg-6b/rdswitch.c b/lc-continuity/mk4/modimage/jpeg-6b/rdswitch.c new file mode 100644 index 0000000000000000000000000000000000000000..4f4bb4f58994719124b0b1fa7827389307126a59 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/rdswitch.c @@ -0,0 +1,332 @@ +/* + * rdswitch.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains routines to process some of cjpeg's more complicated + * command-line switches. Switches processed here are: + * -qtables file Read quantization tables from text file + * -scans file Read scan script from text file + * -qslots N[,N,...] Set component quantization table selectors + * -sample HxV[,HxV,...] Set component sampling factors + */ + +#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ +#include /* to declare isdigit(), isspace() */ + + +LOCAL(int) +text_getc (FILE * file) +/* Read next char, skipping over any comments (# to end of line) */ +/* A comment/newline sequence is returned as a newline */ +{ + register int ch; + + ch = getc(file); + if (ch == '#') { + do { + ch = getc(file); + } while (ch != '\n' && ch != EOF); + } + return ch; +} + + +LOCAL(boolean) +read_text_integer (FILE * file, long * result, int * termchar) +/* Read an unsigned decimal integer from a file, store it in result */ +/* Reads one trailing character after the integer; returns it in termchar */ +{ + register int ch; + register long val; + + /* Skip any leading whitespace, detect EOF */ + do { + ch = text_getc(file); + if (ch == EOF) { + *termchar = ch; + return FALSE; + } + } while (isspace(ch)); + + if (! isdigit(ch)) { + *termchar = ch; + return FALSE; + } + + val = ch - '0'; + while ((ch = text_getc(file)) != EOF) { + if (! isdigit(ch)) + break; + val *= 10; + val += ch - '0'; + } + *result = val; + *termchar = ch; + return TRUE; +} + + +GLOBAL(boolean) +read_quant_tables (j_compress_ptr cinfo, char * filename, + int scale_factor, boolean force_baseline) +/* Read a set of quantization tables from the specified file. + * The file is plain ASCII text: decimal numbers with whitespace between. + * Comments preceded by '#' may be included in the file. + * There may be one to NUM_QUANT_TBLS tables in the file, each of 64 values. + * The tables are implicitly numbered 0,1,etc. + * NOTE: does not affect the qslots mapping, which will default to selecting + * table 0 for luminance (or primary) components, 1 for chrominance components. + * You must use -qslots if you want a different component->table mapping. + */ +{ + FILE * fp; + int tblno, i, termchar; + long val; + unsigned int table[DCTSIZE2]; + + if ((fp = fopen(filename, "r")) == NULL) { + fprintf(stderr, "Can't open table file %s\n", filename); + return FALSE; + } + tblno = 0; + + while (read_text_integer(fp, &val, &termchar)) { /* read 1st element of table */ + if (tblno >= NUM_QUANT_TBLS) { + fprintf(stderr, "Too many tables in file %s\n", filename); + fclose(fp); + return FALSE; + } + table[0] = (unsigned int) val; + for (i = 1; i < DCTSIZE2; i++) { + if (! read_text_integer(fp, &val, &termchar)) { + fprintf(stderr, "Invalid table data in file %s\n", filename); + fclose(fp); + return FALSE; + } + table[i] = (unsigned int) val; + } + jpeg_add_quant_table(cinfo, tblno, table, scale_factor, force_baseline); + tblno++; + } + + if (termchar != EOF) { + fprintf(stderr, "Non-numeric data in file %s\n", filename); + fclose(fp); + return FALSE; + } + + fclose(fp); + return TRUE; +} + + +#ifdef C_MULTISCAN_FILES_SUPPORTED + +LOCAL(boolean) +read_scan_integer (FILE * file, long * result, int * termchar) +/* Variant of read_text_integer that always looks for a non-space termchar; + * this simplifies parsing of punctuation in scan scripts. + */ +{ + register int ch; + + if (! read_text_integer(file, result, termchar)) + return FALSE; + ch = *termchar; + while (ch != EOF && isspace(ch)) + ch = text_getc(file); + if (isdigit(ch)) { /* oops, put it back */ + if (ungetc(ch, file) == EOF) + return FALSE; + ch = ' '; + } else { + /* Any separators other than ';' and ':' are ignored; + * this allows user to insert commas, etc, if desired. + */ + if (ch != EOF && ch != ';' && ch != ':') + ch = ' '; + } + *termchar = ch; + return TRUE; +} + + +GLOBAL(boolean) +read_scan_script (j_compress_ptr cinfo, char * filename) +/* Read a scan script from the specified text file. + * Each entry in the file defines one scan to be emitted. + * Entries are separated by semicolons ';'. + * An entry contains one to four component indexes, + * optionally followed by a colon ':' and four progressive-JPEG parameters. + * The component indexes denote which component(s) are to be transmitted + * in the current scan. The first component has index 0. + * Sequential JPEG is used if the progressive-JPEG parameters are omitted. + * The file is free format text: any whitespace may appear between numbers + * and the ':' and ';' punctuation marks. Also, other punctuation (such + * as commas or dashes) can be placed between numbers if desired. + * Comments preceded by '#' may be included in the file. + * Note: we do very little validity checking here; + * jcmaster.c will validate the script parameters. + */ +{ + FILE * fp; + int scanno, ncomps, termchar; + long val; + jpeg_scan_info * scanptr; +#define MAX_SCANS 100 /* quite arbitrary limit */ + jpeg_scan_info scans[MAX_SCANS]; + + if ((fp = fopen(filename, "r")) == NULL) { + fprintf(stderr, "Can't open scan definition file %s\n", filename); + return FALSE; + } + scanptr = scans; + scanno = 0; + + while (read_scan_integer(fp, &val, &termchar)) { + if (scanno >= MAX_SCANS) { + fprintf(stderr, "Too many scans defined in file %s\n", filename); + fclose(fp); + return FALSE; + } + scanptr->component_index[0] = (int) val; + ncomps = 1; + while (termchar == ' ') { + if (ncomps >= MAX_COMPS_IN_SCAN) { + fprintf(stderr, "Too many components in one scan in file %s\n", + filename); + fclose(fp); + return FALSE; + } + if (! read_scan_integer(fp, &val, &termchar)) + goto bogus; + scanptr->component_index[ncomps] = (int) val; + ncomps++; + } + scanptr->comps_in_scan = ncomps; + if (termchar == ':') { + if (! read_scan_integer(fp, &val, &termchar) || termchar != ' ') + goto bogus; + scanptr->Ss = (int) val; + if (! read_scan_integer(fp, &val, &termchar) || termchar != ' ') + goto bogus; + scanptr->Se = (int) val; + if (! read_scan_integer(fp, &val, &termchar) || termchar != ' ') + goto bogus; + scanptr->Ah = (int) val; + if (! read_scan_integer(fp, &val, &termchar)) + goto bogus; + scanptr->Al = (int) val; + } else { + /* set non-progressive parameters */ + scanptr->Ss = 0; + scanptr->Se = DCTSIZE2-1; + scanptr->Ah = 0; + scanptr->Al = 0; + } + if (termchar != ';' && termchar != EOF) { +bogus: + fprintf(stderr, "Invalid scan entry format in file %s\n", filename); + fclose(fp); + return FALSE; + } + scanptr++, scanno++; + } + + if (termchar != EOF) { + fprintf(stderr, "Non-numeric data in file %s\n", filename); + fclose(fp); + return FALSE; + } + + if (scanno > 0) { + /* Stash completed scan list in cinfo structure. + * NOTE: for cjpeg's use, JPOOL_IMAGE is the right lifetime for this data, + * but if you want to compress multiple images you'd want JPOOL_PERMANENT. + */ + scanptr = (jpeg_scan_info *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + scanno * SIZEOF(jpeg_scan_info)); + MEMCOPY(scanptr, scans, scanno * SIZEOF(jpeg_scan_info)); + cinfo->scan_info = scanptr; + cinfo->num_scans = scanno; + } + + fclose(fp); + return TRUE; +} + +#endif /* C_MULTISCAN_FILES_SUPPORTED */ + + +GLOBAL(boolean) +set_quant_slots (j_compress_ptr cinfo, char *arg) +/* Process a quantization-table-selectors parameter string, of the form + * N[,N,...] + * If there are more components than parameters, the last value is replicated. + */ +{ + int val = 0; /* default table # */ + int ci; + char ch; + + for (ci = 0; ci < MAX_COMPONENTS; ci++) { + if (*arg) { + ch = ','; /* if not set by sscanf, will be ',' */ + if (sscanf(arg, "%d%c", &val, &ch) < 1) + return FALSE; + if (ch != ',') /* syntax check */ + return FALSE; + if (val < 0 || val >= NUM_QUANT_TBLS) { + fprintf(stderr, "JPEG quantization tables are numbered 0..%d\n", + NUM_QUANT_TBLS-1); + return FALSE; + } + cinfo->comp_info[ci].quant_tbl_no = val; + while (*arg && *arg++ != ',') /* advance to next segment of arg string */ + ; + } else { + /* reached end of parameter, set remaining components to last table */ + cinfo->comp_info[ci].quant_tbl_no = val; + } + } + return TRUE; +} + + +GLOBAL(boolean) +set_sample_factors (j_compress_ptr cinfo, char *arg) +/* Process a sample-factors parameter string, of the form + * HxV[,HxV,...] + * If there are more components than parameters, "1x1" is assumed for the rest. + */ +{ + int ci, val1, val2; + char ch1, ch2; + + for (ci = 0; ci < MAX_COMPONENTS; ci++) { + if (*arg) { + ch2 = ','; /* if not set by sscanf, will be ',' */ + if (sscanf(arg, "%d%c%d%c", &val1, &ch1, &val2, &ch2) < 3) + return FALSE; + if ((ch1 != 'x' && ch1 != 'X') || ch2 != ',') /* syntax check */ + return FALSE; + if (val1 <= 0 || val1 > 4 || val2 <= 0 || val2 > 4) { + fprintf(stderr, "JPEG sampling factors must be 1..4\n"); + return FALSE; + } + cinfo->comp_info[ci].h_samp_factor = val1; + cinfo->comp_info[ci].v_samp_factor = val2; + while (*arg && *arg++ != ',') /* advance to next segment of arg string */ + ; + } else { + /* reached end of parameter, set remaining components to 1x1 sampling */ + cinfo->comp_info[ci].h_samp_factor = 1; + cinfo->comp_info[ci].v_samp_factor = 1; + } + } + return TRUE; +} diff --git a/lc-continuity/mk4/modimage/jpeg-6b/rdtarga.c b/lc-continuity/mk4/modimage/jpeg-6b/rdtarga.c new file mode 100644 index 0000000000000000000000000000000000000000..4c2cd26730a8af052bd674bb1aba7af0295a8d19 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/rdtarga.c @@ -0,0 +1,500 @@ +/* + * rdtarga.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains routines to read input images in Targa format. + * + * These routines may need modification for non-Unix environments or + * specialized applications. As they stand, they assume input from + * an ordinary stdio stream. They further assume that reading begins + * at the start of the file; start_input may need work if the + * user interface has already read some data (e.g., to determine that + * the file is indeed Targa format). + * + * Based on code contributed by Lee Daniel Crocker. + */ + +#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ + +#ifdef TARGA_SUPPORTED + + +/* Macros to deal with unsigned chars as efficiently as compiler allows */ + +#ifdef HAVE_UNSIGNED_CHAR +typedef unsigned char U_CHAR; +#define UCH(x) ((int) (x)) +#else /* !HAVE_UNSIGNED_CHAR */ +#ifdef CHAR_IS_UNSIGNED +typedef char U_CHAR; +#define UCH(x) ((int) (x)) +#else +typedef char U_CHAR; +#define UCH(x) ((int) (x) & 0xFF) +#endif +#endif /* HAVE_UNSIGNED_CHAR */ + + +#define ReadOK(file,buffer,len) (JFREAD(file,buffer,len) == ((size_t) (len))) + + +/* Private version of data source object */ + +typedef struct _tga_source_struct * tga_source_ptr; + +typedef struct _tga_source_struct { + struct cjpeg_source_struct pub; /* public fields */ + + j_compress_ptr cinfo; /* back link saves passing separate parm */ + + JSAMPARRAY colormap; /* Targa colormap (converted to my format) */ + + jvirt_sarray_ptr whole_image; /* Needed if funny input row order */ + JDIMENSION current_row; /* Current logical row number to read */ + + /* Pointer to routine to extract next Targa pixel from input file */ + JMETHOD(void, read_pixel, (tga_source_ptr sinfo)); + + /* Result of read_pixel is delivered here: */ + U_CHAR tga_pixel[4]; + + int pixel_size; /* Bytes per Targa pixel (1 to 4) */ + + /* State info for reading RLE-coded pixels; both counts must be init to 0 */ + int block_count; /* # of pixels remaining in RLE block */ + int dup_pixel_count; /* # of times to duplicate previous pixel */ + + /* This saves the correct pixel-row-expansion method for preload_image */ + JMETHOD(JDIMENSION, get_pixel_rows, (j_compress_ptr cinfo, + cjpeg_source_ptr sinfo)); +} tga_source_struct; + + +/* For expanding 5-bit pixel values to 8-bit with best rounding */ + +static const UINT8 c5to8bits[32] = { + 0, 8, 16, 25, 33, 41, 49, 58, + 66, 74, 82, 90, 99, 107, 115, 123, + 132, 140, 148, 156, 165, 173, 181, 189, + 197, 206, 214, 222, 230, 239, 247, 255 +}; + + + +LOCAL(int) +read_byte (tga_source_ptr sinfo) +/* Read next byte from Targa file */ +{ + register FILE *infile = sinfo->pub.input_file; + register int c; + + if ((c = getc(infile)) == EOF) + ERREXIT(sinfo->cinfo, JERR_INPUT_EOF); + return c; +} + + +LOCAL(void) +read_colormap (tga_source_ptr sinfo, int cmaplen, int mapentrysize) +/* Read the colormap from a Targa file */ +{ + int i; + + /* Presently only handles 24-bit BGR format */ + if (mapentrysize != 24) + ERREXIT(sinfo->cinfo, JERR_TGA_BADCMAP); + + for (i = 0; i < cmaplen; i++) { + sinfo->colormap[2][i] = (JSAMPLE) read_byte(sinfo); + sinfo->colormap[1][i] = (JSAMPLE) read_byte(sinfo); + sinfo->colormap[0][i] = (JSAMPLE) read_byte(sinfo); + } +} + + +/* + * read_pixel methods: get a single pixel from Targa file into tga_pixel[] + */ + +METHODDEF(void) +read_non_rle_pixel (tga_source_ptr sinfo) +/* Read one Targa pixel from the input file; no RLE expansion */ +{ + register FILE *infile = sinfo->pub.input_file; + register int i; + + for (i = 0; i < sinfo->pixel_size; i++) { + sinfo->tga_pixel[i] = (U_CHAR) getc(infile); + } +} + + +METHODDEF(void) +read_rle_pixel (tga_source_ptr sinfo) +/* Read one Targa pixel from the input file, expanding RLE data as needed */ +{ + register FILE *infile = sinfo->pub.input_file; + register int i; + + /* Duplicate previously read pixel? */ + if (sinfo->dup_pixel_count > 0) { + sinfo->dup_pixel_count--; + return; + } + + /* Time to read RLE block header? */ + if (--sinfo->block_count < 0) { /* decrement pixels remaining in block */ + i = read_byte(sinfo); + if (i & 0x80) { /* Start of duplicate-pixel block? */ + sinfo->dup_pixel_count = i & 0x7F; /* number of dups after this one */ + sinfo->block_count = 0; /* then read new block header */ + } else { + sinfo->block_count = i & 0x7F; /* number of pixels after this one */ + } + } + + /* Read next pixel */ + for (i = 0; i < sinfo->pixel_size; i++) { + sinfo->tga_pixel[i] = (U_CHAR) getc(infile); + } +} + + +/* + * Read one row of pixels. + * + * We provide several different versions depending on input file format. + */ + + +METHODDEF(JDIMENSION) +get_8bit_gray_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading 8-bit grayscale pixels */ +{ + tga_source_ptr source = (tga_source_ptr) sinfo; + register JSAMPROW ptr; + register JDIMENSION col; + + ptr = source->pub.buffer[0]; + for (col = cinfo->image_width; col > 0; col--) { + (*source->read_pixel) (source); /* Load next pixel into tga_pixel */ + *ptr++ = (JSAMPLE) UCH(source->tga_pixel[0]); + } + return 1; +} + +METHODDEF(JDIMENSION) +get_8bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading 8-bit colormap indexes */ +{ + tga_source_ptr source = (tga_source_ptr) sinfo; + register int t; + register JSAMPROW ptr; + register JDIMENSION col; + register JSAMPARRAY colormap = source->colormap; + + ptr = source->pub.buffer[0]; + for (col = cinfo->image_width; col > 0; col--) { + (*source->read_pixel) (source); /* Load next pixel into tga_pixel */ + t = UCH(source->tga_pixel[0]); + *ptr++ = colormap[0][t]; + *ptr++ = colormap[1][t]; + *ptr++ = colormap[2][t]; + } + return 1; +} + +METHODDEF(JDIMENSION) +get_16bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading 16-bit pixels */ +{ + tga_source_ptr source = (tga_source_ptr) sinfo; + register int t; + register JSAMPROW ptr; + register JDIMENSION col; + + ptr = source->pub.buffer[0]; + for (col = cinfo->image_width; col > 0; col--) { + (*source->read_pixel) (source); /* Load next pixel into tga_pixel */ + t = UCH(source->tga_pixel[0]); + t += UCH(source->tga_pixel[1]) << 8; + /* We expand 5 bit data to 8 bit sample width. + * The format of the 16-bit (LSB first) input word is + * xRRRRRGGGGGBBBBB + */ + ptr[2] = (JSAMPLE) c5to8bits[t & 0x1F]; + t >>= 5; + ptr[1] = (JSAMPLE) c5to8bits[t & 0x1F]; + t >>= 5; + ptr[0] = (JSAMPLE) c5to8bits[t & 0x1F]; + ptr += 3; + } + return 1; +} + +METHODDEF(JDIMENSION) +get_24bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading 24-bit pixels */ +{ + tga_source_ptr source = (tga_source_ptr) sinfo; + register JSAMPROW ptr; + register JDIMENSION col; + + ptr = source->pub.buffer[0]; + for (col = cinfo->image_width; col > 0; col--) { + (*source->read_pixel) (source); /* Load next pixel into tga_pixel */ + *ptr++ = (JSAMPLE) UCH(source->tga_pixel[2]); /* change BGR to RGB order */ + *ptr++ = (JSAMPLE) UCH(source->tga_pixel[1]); + *ptr++ = (JSAMPLE) UCH(source->tga_pixel[0]); + } + return 1; +} + +/* + * Targa also defines a 32-bit pixel format with order B,G,R,A. + * We presently ignore the attribute byte, so the code for reading + * these pixels is identical to the 24-bit routine above. + * This works because the actual pixel length is only known to read_pixel. + */ + +#define get_32bit_row get_24bit_row + + +/* + * This method is for re-reading the input data in standard top-down + * row order. The entire image has already been read into whole_image + * with proper conversion of pixel format, but it's in a funny row order. + */ + +METHODDEF(JDIMENSION) +get_memory_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +{ + tga_source_ptr source = (tga_source_ptr) sinfo; + JDIMENSION source_row; + + /* Compute row of source that maps to current_row of normal order */ + /* For now, assume image is bottom-up and not interlaced. */ + /* NEEDS WORK to support interlaced images! */ + source_row = cinfo->image_height - source->current_row - 1; + + /* Fetch that row from virtual array */ + source->pub.buffer = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, source->whole_image, + source_row, (JDIMENSION) 1, FALSE); + + source->current_row++; + return 1; +} + + +/* + * This method loads the image into whole_image during the first call on + * get_pixel_rows. The get_pixel_rows pointer is then adjusted to call + * get_memory_row on subsequent calls. + */ + +METHODDEF(JDIMENSION) +preload_image (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +{ + tga_source_ptr source = (tga_source_ptr) sinfo; + JDIMENSION row; + cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress; + + /* Read the data into a virtual array in input-file row order. */ + for (row = 0; row < cinfo->image_height; row++) { + if (progress != NULL) { + progress->pub.pass_counter = (long) row; + progress->pub.pass_limit = (long) cinfo->image_height; + (*progress->pub.progress_monitor) ((j_common_ptr) cinfo); + } + source->pub.buffer = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, source->whole_image, row, (JDIMENSION) 1, TRUE); + (*source->get_pixel_rows) (cinfo, sinfo); + } + if (progress != NULL) + progress->completed_extra_passes++; + + /* Set up to read from the virtual array in unscrambled order */ + source->pub.get_pixel_rows = get_memory_row; + source->current_row = 0; + /* And read the first row */ + return get_memory_row(cinfo, sinfo); +} + + +/* + * Read the file header; return image size and component count. + */ + +METHODDEF(void) +start_input_tga (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +{ + tga_source_ptr source = (tga_source_ptr) sinfo; + U_CHAR targaheader[18]; + int idlen, cmaptype, subtype, flags, interlace_type, components; + unsigned int width, height, maplen; + boolean is_bottom_up; + +#define GET_2B(offset) ((unsigned int) UCH(targaheader[offset]) + \ + (((unsigned int) UCH(targaheader[offset+1])) << 8)) + + if (! ReadOK(source->pub.input_file, targaheader, 18)) + ERREXIT(cinfo, JERR_INPUT_EOF); + + /* Pretend "15-bit" pixels are 16-bit --- we ignore attribute bit anyway */ + if (targaheader[16] == 15) + targaheader[16] = 16; + + idlen = UCH(targaheader[0]); + cmaptype = UCH(targaheader[1]); + subtype = UCH(targaheader[2]); + maplen = GET_2B(5); + width = GET_2B(12); + height = GET_2B(14); + source->pixel_size = UCH(targaheader[16]) >> 3; + flags = UCH(targaheader[17]); /* Image Descriptor byte */ + + is_bottom_up = ((flags & 0x20) == 0); /* bit 5 set => top-down */ + interlace_type = flags >> 6; /* bits 6/7 are interlace code */ + + if (cmaptype > 1 || /* cmaptype must be 0 or 1 */ + source->pixel_size < 1 || source->pixel_size > 4 || + (UCH(targaheader[16]) & 7) != 0 || /* bits/pixel must be multiple of 8 */ + interlace_type != 0) /* currently don't allow interlaced image */ + ERREXIT(cinfo, JERR_TGA_BADPARMS); + + if (subtype > 8) { + /* It's an RLE-coded file */ + source->read_pixel = read_rle_pixel; + source->block_count = source->dup_pixel_count = 0; + subtype -= 8; + } else { + /* Non-RLE file */ + source->read_pixel = read_non_rle_pixel; + } + + /* Now should have subtype 1, 2, or 3 */ + components = 3; /* until proven different */ + cinfo->in_color_space = JCS_RGB; + + switch (subtype) { + case 1: /* Colormapped image */ + if (source->pixel_size == 1 && cmaptype == 1) + source->get_pixel_rows = get_8bit_row; + else + ERREXIT(cinfo, JERR_TGA_BADPARMS); + TRACEMS2(cinfo, 1, JTRC_TGA_MAPPED, width, height); + break; + case 2: /* RGB image */ + switch (source->pixel_size) { + case 2: + source->get_pixel_rows = get_16bit_row; + break; + case 3: + source->get_pixel_rows = get_24bit_row; + break; + case 4: + source->get_pixel_rows = get_32bit_row; + break; + default: + ERREXIT(cinfo, JERR_TGA_BADPARMS); + break; + } + TRACEMS2(cinfo, 1, JTRC_TGA, width, height); + break; + case 3: /* Grayscale image */ + components = 1; + cinfo->in_color_space = JCS_GRAYSCALE; + if (source->pixel_size == 1) + source->get_pixel_rows = get_8bit_gray_row; + else + ERREXIT(cinfo, JERR_TGA_BADPARMS); + TRACEMS2(cinfo, 1, JTRC_TGA_GRAY, width, height); + break; + default: + ERREXIT(cinfo, JERR_TGA_BADPARMS); + break; + } + + if (is_bottom_up) { + /* Create a virtual array to buffer the upside-down image. */ + source->whole_image = (*cinfo->mem->request_virt_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, + (JDIMENSION) width * components, (JDIMENSION) height, (JDIMENSION) 1); + if (cinfo->progress != NULL) { + cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress; + progress->total_extra_passes++; /* count file input as separate pass */ + } + /* source->pub.buffer will point to the virtual array. */ + source->pub.buffer_height = 1; /* in case anyone looks at it */ + source->pub.get_pixel_rows = preload_image; + } else { + /* Don't need a virtual array, but do need a one-row input buffer. */ + source->whole_image = NULL; + source->pub.buffer = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) width * components, (JDIMENSION) 1); + source->pub.buffer_height = 1; + source->pub.get_pixel_rows = source->get_pixel_rows; + } + + while (idlen--) /* Throw away ID field */ + (void) read_byte(source); + + if (maplen > 0) { + if (maplen > 256 || GET_2B(3) != 0) + ERREXIT(cinfo, JERR_TGA_BADCMAP); + /* Allocate space to store the colormap */ + source->colormap = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, (JDIMENSION) maplen, (JDIMENSION) 3); + /* and read it from the file */ + read_colormap(source, (int) maplen, UCH(targaheader[7])); + } else { + if (cmaptype) /* but you promised a cmap! */ + ERREXIT(cinfo, JERR_TGA_BADPARMS); + source->colormap = NULL; + } + + cinfo->input_components = components; + cinfo->data_precision = 8; + cinfo->image_width = width; + cinfo->image_height = height; +} + + +/* + * Finish up at the end of the file. + */ + +METHODDEF(void) +finish_input_tga (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +{ + /* no work */ +} + + +/* + * The module selection routine for Targa format input. + */ + +GLOBAL(cjpeg_source_ptr) +jinit_read_targa (j_compress_ptr cinfo) +{ + tga_source_ptr source; + + /* Create module interface object */ + source = (tga_source_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(tga_source_struct)); + source->cinfo = cinfo; /* make back link for subroutines */ + /* Fill in method ptrs, except get_pixel_rows which start_input sets */ + source->pub.start_input = start_input_tga; + source->pub.finish_input = finish_input_tga; + + return (cjpeg_source_ptr) source; +} + +#endif /* TARGA_SUPPORTED */ diff --git a/lc-continuity/mk4/modimage/jpeg-6b/structure.doc b/lc-continuity/mk4/modimage/jpeg-6b/structure.doc new file mode 100644 index 0000000000000000000000000000000000000000..51c9def7e5d0cbbf81ea8e3fc8d6e9cb7e7ff173 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/structure.doc @@ -0,0 +1,948 @@ +IJG JPEG LIBRARY: SYSTEM ARCHITECTURE + +Copyright (C) 1991-1995, Thomas G. Lane. +This file is part of the Independent JPEG Group's software. +For conditions of distribution and use, see the accompanying README file. + + +This file provides an overview of the architecture of the IJG JPEG software; +that is, the functions of the various modules in the system and the interfaces +between modules. For more precise details about any data structure or calling +convention, see the include files and comments in the source code. + +We assume that the reader is already somewhat familiar with the JPEG standard. +The README file includes references for learning about JPEG. The file +libjpeg.doc describes the library from the viewpoint of an application +programmer using the library; it's best to read that file before this one. +Also, the file coderules.doc describes the coding style conventions we use. + +In this document, JPEG-specific terminology follows the JPEG standard: + A "component" means a color channel, e.g., Red or Luminance. + A "sample" is a single component value (i.e., one number in the image data). + A "coefficient" is a frequency coefficient (a DCT transform output number). + A "block" is an 8x8 group of samples or coefficients. + An "MCU" (minimum coded unit) is an interleaved set of blocks of size + determined by the sampling factors, or a single block in a + noninterleaved scan. +We do not use the terms "pixel" and "sample" interchangeably. When we say +pixel, we mean an element of the full-size image, while a sample is an element +of the downsampled image. Thus the number of samples may vary across +components while the number of pixels does not. (This terminology is not used +rigorously throughout the code, but it is used in places where confusion would +otherwise result.) + + +*** System features *** + +The IJG distribution contains two parts: + * A subroutine library for JPEG compression and decompression. + * cjpeg/djpeg, two sample applications that use the library to transform + JFIF JPEG files to and from several other image formats. +cjpeg/djpeg are of no great intellectual complexity: they merely add a simple +command-line user interface and I/O routines for several uncompressed image +formats. This document concentrates on the library itself. + +We desire the library to be capable of supporting all JPEG baseline, extended +sequential, and progressive DCT processes. Hierarchical processes are not +supported. + +The library does not support the lossless (spatial) JPEG process. Lossless +JPEG shares little or no code with lossy JPEG, and would normally be used +without the extensive pre- and post-processing provided by this library. +We feel that lossless JPEG is better handled by a separate library. + +Within these limits, any set of compression parameters allowed by the JPEG +spec should be readable for decompression. (We can be more restrictive about +what formats we can generate.) Although the system design allows for all +parameter values, some uncommon settings are not yet implemented and may +never be; nonintegral sampling ratios are the prime example. Furthermore, +we treat 8-bit vs. 12-bit data precision as a compile-time switch, not a +run-time option, because most machines can store 8-bit pixels much more +compactly than 12-bit. + +For legal reasons, JPEG arithmetic coding is not currently supported, but +extending the library to include it would be straightforward. + +By itself, the library handles only interchange JPEG datastreams --- in +particular the widely used JFIF file format. The library can be used by +surrounding code to process interchange or abbreviated JPEG datastreams that +are embedded in more complex file formats. (For example, libtiff uses this +library to implement JPEG compression within the TIFF file format.) + +The library includes a substantial amount of code that is not covered by the +JPEG standard but is necessary for typical applications of JPEG. These +functions preprocess the image before JPEG compression or postprocess it after +decompression. They include colorspace conversion, downsampling/upsampling, +and color quantization. This code can be omitted if not needed. + +A wide range of quality vs. speed tradeoffs are possible in JPEG processing, +and even more so in decompression postprocessing. The decompression library +provides multiple implementations that cover most of the useful tradeoffs, +ranging from very-high-quality down to fast-preview operation. On the +compression side we have generally not provided low-quality choices, since +compression is normally less time-critical. It should be understood that the +low-quality modes may not meet the JPEG standard's accuracy requirements; +nonetheless, they are useful for viewers. + + +*** Portability issues *** + +Portability is an essential requirement for the library. The key portability +issues that show up at the level of system architecture are: + +1. Memory usage. We want the code to be able to run on PC-class machines +with limited memory. Images should therefore be processed sequentially (in +strips), to avoid holding the whole image in memory at once. Where a +full-image buffer is necessary, we should be able to use either virtual memory +or temporary files. + +2. Near/far pointer distinction. To run efficiently on 80x86 machines, the +code should distinguish "small" objects (kept in near data space) from +"large" ones (kept in far data space). This is an annoying restriction, but +fortunately it does not impact code quality for less brain-damaged machines, +and the source code clutter turns out to be minimal with sufficient use of +pointer typedefs. + +3. Data precision. We assume that "char" is at least 8 bits, "short" and +"int" at least 16, "long" at least 32. The code will work fine with larger +data sizes, although memory may be used inefficiently in some cases. However, +the JPEG compressed datastream must ultimately appear on external storage as a +sequence of 8-bit bytes if it is to conform to the standard. This may pose a +problem on machines where char is wider than 8 bits. The library represents +compressed data as an array of values of typedef JOCTET. If no data type +exactly 8 bits wide is available, custom data source and data destination +modules must be written to unpack and pack the chosen JOCTET datatype into +8-bit external representation. + + +*** System overview *** + +The compressor and decompressor are each divided into two main sections: +the JPEG compressor or decompressor proper, and the preprocessing or +postprocessing functions. The interface between these two sections is the +image data that the official JPEG spec regards as its input or output: this +data is in the colorspace to be used for compression, and it is downsampled +to the sampling factors to be used. The preprocessing and postprocessing +steps are responsible for converting a normal image representation to or from +this form. (Those few applications that want to deal with YCbCr downsampled +data can skip the preprocessing or postprocessing step.) + +Looking more closely, the compressor library contains the following main +elements: + + Preprocessing: + * Color space conversion (e.g., RGB to YCbCr). + * Edge expansion and downsampling. Optionally, this step can do simple + smoothing --- this is often helpful for low-quality source data. + JPEG proper: + * MCU assembly, DCT, quantization. + * Entropy coding (sequential or progressive, Huffman or arithmetic). + +In addition to these modules we need overall control, marker generation, +and support code (memory management & error handling). There is also a +module responsible for physically writing the output data --- typically +this is just an interface to fwrite(), but some applications may need to +do something else with the data. + +The decompressor library contains the following main elements: + + JPEG proper: + * Entropy decoding (sequential or progressive, Huffman or arithmetic). + * Dequantization, inverse DCT, MCU disassembly. + Postprocessing: + * Upsampling. Optionally, this step may be able to do more general + rescaling of the image. + * Color space conversion (e.g., YCbCr to RGB). This step may also + provide gamma adjustment [ currently it does not ]. + * Optional color quantization (e.g., reduction to 256 colors). + * Optional color precision reduction (e.g., 24-bit to 15-bit color). + [This feature is not currently implemented.] + +We also need overall control, marker parsing, and a data source module. +The support code (memory management & error handling) can be shared with +the compression half of the library. + +There may be several implementations of each of these elements, particularly +in the decompressor, where a wide range of speed/quality tradeoffs is very +useful. It must be understood that some of the best speedups involve +merging adjacent steps in the pipeline. For example, upsampling, color space +conversion, and color quantization might all be done at once when using a +low-quality ordered-dither technique. The system architecture is designed to +allow such merging where appropriate. + + +Note: it is convenient to regard edge expansion (padding to block boundaries) +as a preprocessing/postprocessing function, even though the JPEG spec includes +it in compression/decompression. We do this because downsampling/upsampling +can be simplified a little if they work on padded data: it's not necessary to +have special cases at the right and bottom edges. Therefore the interface +buffer is always an integral number of blocks wide and high, and we expect +compression preprocessing to pad the source data properly. Padding will occur +only to the next block (8-sample) boundary. In an interleaved-scan situation, +additional dummy blocks may be used to fill out MCUs, but the MCU assembly and +disassembly logic will create or discard these blocks internally. (This is +advantageous for speed reasons, since we avoid DCTing the dummy blocks. +It also permits a small reduction in file size, because the compressor can +choose dummy block contents so as to minimize their size in compressed form. +Finally, it makes the interface buffer specification independent of whether +the file is actually interleaved or not.) Applications that wish to deal +directly with the downsampled data must provide similar buffering and padding +for odd-sized images. + + +*** Poor man's object-oriented programming *** + +It should be clear by now that we have a lot of quasi-independent processing +steps, many of which have several possible behaviors. To avoid cluttering the +code with lots of switch statements, we use a simple form of object-style +programming to separate out the different possibilities. + +For example, two different color quantization algorithms could be implemented +as two separate modules that present the same external interface; at runtime, +the calling code will access the proper module indirectly through an "object". + +We can get the limited features we need while staying within portable C. +The basic tool is a function pointer. An "object" is just a struct +containing one or more function pointer fields, each of which corresponds to +a method name in real object-oriented languages. During initialization we +fill in the function pointers with references to whichever module we have +determined we need to use in this run. Then invocation of the module is done +by indirecting through a function pointer; on most machines this is no more +expensive than a switch statement, which would be the only other way of +making the required run-time choice. The really significant benefit, of +course, is keeping the source code clean and well structured. + +We can also arrange to have private storage that varies between different +implementations of the same kind of object. We do this by making all the +module-specific object structs be separately allocated entities, which will +be accessed via pointers in the master compression or decompression struct. +The "public" fields or methods for a given kind of object are specified by +a commonly known struct. But a module's initialization code can allocate +a larger struct that contains the common struct as its first member, plus +additional private fields. With appropriate pointer casting, the module's +internal functions can access these private fields. (For a simple example, +see jdatadst.c, which implements the external interface specified by struct +jpeg_destination_mgr, but adds extra fields.) + +(Of course this would all be a lot easier if we were using C++, but we are +not yet prepared to assume that everyone has a C++ compiler.) + +An important benefit of this scheme is that it is easy to provide multiple +versions of any method, each tuned to a particular case. While a lot of +precalculation might be done to select an optimal implementation of a method, +the cost per invocation is constant. For example, the upsampling step might +have a "generic" method, plus one or more "hardwired" methods for the most +popular sampling factors; the hardwired methods would be faster because they'd +use straight-line code instead of for-loops. The cost to determine which +method to use is paid only once, at startup, and the selection criteria are +hidden from the callers of the method. + +This plan differs a little bit from usual object-oriented structures, in that +only one instance of each object class will exist during execution. The +reason for having the class structure is that on different runs we may create +different instances (choose to execute different modules). You can think of +the term "method" as denoting the common interface presented by a particular +set of interchangeable functions, and "object" as denoting a group of related +methods, or the total shared interface behavior of a group of modules. + + +*** Overall control structure *** + +We previously mentioned the need for overall control logic in the compression +and decompression libraries. In IJG implementations prior to v5, overall +control was mostly provided by "pipeline control" modules, which proved to be +large, unwieldy, and hard to understand. To improve the situation, the +control logic has been subdivided into multiple modules. The control modules +consist of: + +1. Master control for module selection and initialization. This has two +responsibilities: + + 1A. Startup initialization at the beginning of image processing. + The individual processing modules to be used in this run are selected + and given initialization calls. + + 1B. Per-pass control. This determines how many passes will be performed + and calls each active processing module to configure itself + appropriately at the beginning of each pass. End-of-pass processing, + where necessary, is also invoked from the master control module. + + Method selection is partially distributed, in that a particular processing + module may contain several possible implementations of a particular method, + which it will select among when given its initialization call. The master + control code need only be concerned with decisions that affect more than + one module. + +2. Data buffering control. A separate control module exists for each + inter-processing-step data buffer. This module is responsible for + invoking the processing steps that write or read that data buffer. + +Each buffer controller sees the world as follows: + +input data => processing step A => buffer => processing step B => output data + | | | + ------------------ controller ------------------ + +The controller knows the dataflow requirements of steps A and B: how much data +they want to accept in one chunk and how much they output in one chunk. Its +function is to manage its buffer and call A and B at the proper times. + +A data buffer control module may itself be viewed as a processing step by a +higher-level control module; thus the control modules form a binary tree with +elementary processing steps at the leaves of the tree. + +The control modules are objects. A considerable amount of flexibility can +be had by replacing implementations of a control module. For example: +* Merging of adjacent steps in the pipeline is done by replacing a control + module and its pair of processing-step modules with a single processing- + step module. (Hence the possible merges are determined by the tree of + control modules.) +* In some processing modes, a given interstep buffer need only be a "strip" + buffer large enough to accommodate the desired data chunk sizes. In other + modes, a full-image buffer is needed and several passes are required. + The control module determines which kind of buffer is used and manipulates + virtual array buffers as needed. One or both processing steps may be + unaware of the multi-pass behavior. + +In theory, we might be able to make all of the data buffer controllers +interchangeable and provide just one set of implementations for all. In +practice, each one contains considerable special-case processing for its +particular job. The buffer controller concept should be regarded as an +overall system structuring principle, not as a complete description of the +task performed by any one controller. + + +*** Compression object structure *** + +Here is a sketch of the logical structure of the JPEG compression library: + + |-- Colorspace conversion + |-- Preprocessing controller --| + | |-- Downsampling +Main controller --| + | |-- Forward DCT, quantize + |-- Coefficient controller --| + |-- Entropy encoding + +This sketch also describes the flow of control (subroutine calls) during +typical image data processing. Each of the components shown in the diagram is +an "object" which may have several different implementations available. One +or more source code files contain the actual implementation(s) of each object. + +The objects shown above are: + +* Main controller: buffer controller for the subsampled-data buffer, which + holds the preprocessed input data. This controller invokes preprocessing to + fill the subsampled-data buffer, and JPEG compression to empty it. There is + usually no need for a full-image buffer here; a strip buffer is adequate. + +* Preprocessing controller: buffer controller for the downsampling input data + buffer, which lies between colorspace conversion and downsampling. Note + that a unified conversion/downsampling module would probably replace this + controller entirely. + +* Colorspace conversion: converts application image data into the desired + JPEG color space; also changes the data from pixel-interleaved layout to + separate component planes. Processes one pixel row at a time. + +* Downsampling: performs reduction of chroma components as required. + Optionally may perform pixel-level smoothing as well. Processes a "row + group" at a time, where a row group is defined as Vmax pixel rows of each + component before downsampling, and Vk sample rows afterwards (remember Vk + differs across components). Some downsampling or smoothing algorithms may + require context rows above and below the current row group; the + preprocessing controller is responsible for supplying these rows via proper + buffering. The downsampler is responsible for edge expansion at the right + edge (i.e., extending each sample row to a multiple of 8 samples); but the + preprocessing controller is responsible for vertical edge expansion (i.e., + duplicating the bottom sample row as needed to make a multiple of 8 rows). + +* Coefficient controller: buffer controller for the DCT-coefficient data. + This controller handles MCU assembly, including insertion of dummy DCT + blocks when needed at the right or bottom edge. When performing + Huffman-code optimization or emitting a multiscan JPEG file, this + controller is responsible for buffering the full image. The equivalent of + one fully interleaved MCU row of subsampled data is processed per call, + even when the JPEG file is noninterleaved. + +* Forward DCT and quantization: Perform DCT, quantize, and emit coefficients. + Works on one or more DCT blocks at a time. (Note: the coefficients are now + emitted in normal array order, which the entropy encoder is expected to + convert to zigzag order as necessary. Prior versions of the IJG code did + the conversion to zigzag order within the quantization step.) + +* Entropy encoding: Perform Huffman or arithmetic entropy coding and emit the + coded data to the data destination module. Works on one MCU per call. + For progressive JPEG, the same DCT blocks are fed to the entropy coder + during each pass, and the coder must emit the appropriate subset of + coefficients. + +In addition to the above objects, the compression library includes these +objects: + +* Master control: determines the number of passes required, controls overall + and per-pass initialization of the other modules. + +* Marker writing: generates JPEG markers (except for RSTn, which is emitted + by the entropy encoder when needed). + +* Data destination manager: writes the output JPEG datastream to its final + destination (e.g., a file). The destination manager supplied with the + library knows how to write to a stdio stream; for other behaviors, the + surrounding application may provide its own destination manager. + +* Memory manager: allocates and releases memory, controls virtual arrays + (with backing store management, where required). + +* Error handler: performs formatting and output of error and trace messages; + determines handling of nonfatal errors. The surrounding application may + override some or all of this object's methods to change error handling. + +* Progress monitor: supports output of "percent-done" progress reports. + This object represents an optional callback to the surrounding application: + if wanted, it must be supplied by the application. + +The error handler, destination manager, and progress monitor objects are +defined as separate objects in order to simplify application-specific +customization of the JPEG library. A surrounding application may override +individual methods or supply its own all-new implementation of one of these +objects. The object interfaces for these objects are therefore treated as +part of the application interface of the library, whereas the other objects +are internal to the library. + +The error handler and memory manager are shared by JPEG compression and +decompression; the progress monitor, if used, may be shared as well. + + +*** Decompression object structure *** + +Here is a sketch of the logical structure of the JPEG decompression library: + + |-- Entropy decoding + |-- Coefficient controller --| + | |-- Dequantize, Inverse DCT +Main controller --| + | |-- Upsampling + |-- Postprocessing controller --| |-- Colorspace conversion + |-- Color quantization + |-- Color precision reduction + +As before, this diagram also represents typical control flow. The objects +shown are: + +* Main controller: buffer controller for the subsampled-data buffer, which + holds the output of JPEG decompression proper. This controller's primary + task is to feed the postprocessing procedure. Some upsampling algorithms + may require context rows above and below the current row group; when this + is true, the main controller is responsible for managing its buffer so as + to make context rows available. In the current design, the main buffer is + always a strip buffer; a full-image buffer is never required. + +* Coefficient controller: buffer controller for the DCT-coefficient data. + This controller handles MCU disassembly, including deletion of any dummy + DCT blocks at the right or bottom edge. When reading a multiscan JPEG + file, this controller is responsible for buffering the full image. + (Buffering DCT coefficients, rather than samples, is necessary to support + progressive JPEG.) The equivalent of one fully interleaved MCU row of + subsampled data is processed per call, even when the source JPEG file is + noninterleaved. + +* Entropy decoding: Read coded data from the data source module and perform + Huffman or arithmetic entropy decoding. Works on one MCU per call. + For progressive JPEG decoding, the coefficient controller supplies the prior + coefficients of each MCU (initially all zeroes), which the entropy decoder + modifies in each scan. + +* Dequantization and inverse DCT: like it says. Note that the coefficients + buffered by the coefficient controller have NOT been dequantized; we + merge dequantization and inverse DCT into a single step for speed reasons. + When scaled-down output is asked for, simplified DCT algorithms may be used + that emit only 1x1, 2x2, or 4x4 samples per DCT block, not the full 8x8. + Works on one DCT block at a time. + +* Postprocessing controller: buffer controller for the color quantization + input buffer, when quantization is in use. (Without quantization, this + controller just calls the upsampler.) For two-pass quantization, this + controller is responsible for buffering the full-image data. + +* Upsampling: restores chroma components to full size. (May support more + general output rescaling, too. Note that if undersized DCT outputs have + been emitted by the DCT module, this module must adjust so that properly + sized outputs are created.) Works on one row group at a time. This module + also calls the color conversion module, so its top level is effectively a + buffer controller for the upsampling->color conversion buffer. However, in + all but the highest-quality operating modes, upsampling and color + conversion are likely to be merged into a single step. + +* Colorspace conversion: convert from JPEG color space to output color space, + and change data layout from separate component planes to pixel-interleaved. + Works on one pixel row at a time. + +* Color quantization: reduce the data to colormapped form, using either an + externally specified colormap or an internally generated one. This module + is not used for full-color output. Works on one pixel row at a time; may + require two passes to generate a color map. Note that the output will + always be a single component representing colormap indexes. In the current + design, the output values are JSAMPLEs, so an 8-bit compilation cannot + quantize to more than 256 colors. This is unlikely to be a problem in + practice. + +* Color reduction: this module handles color precision reduction, e.g., + generating 15-bit color (5 bits/primary) from JPEG's 24-bit output. + Not quite clear yet how this should be handled... should we merge it with + colorspace conversion??? + +Note that some high-speed operating modes might condense the entire +postprocessing sequence to a single module (upsample, color convert, and +quantize in one step). + +In addition to the above objects, the decompression library includes these +objects: + +* Master control: determines the number of passes required, controls overall + and per-pass initialization of the other modules. This is subdivided into + input and output control: jdinput.c controls only input-side processing, + while jdmaster.c handles overall initialization and output-side control. + +* Marker reading: decodes JPEG markers (except for RSTn). + +* Data source manager: supplies the input JPEG datastream. The source + manager supplied with the library knows how to read from a stdio stream; + for other behaviors, the surrounding application may provide its own source + manager. + +* Memory manager: same as for compression library. + +* Error handler: same as for compression library. + +* Progress monitor: same as for compression library. + +As with compression, the data source manager, error handler, and progress +monitor are candidates for replacement by a surrounding application. + + +*** Decompression input and output separation *** + +To support efficient incremental display of progressive JPEG files, the +decompressor is divided into two sections that can run independently: + +1. Data input includes marker parsing, entropy decoding, and input into the + coefficient controller's DCT coefficient buffer. Note that this + processing is relatively cheap and fast. + +2. Data output reads from the DCT coefficient buffer and performs the IDCT + and all postprocessing steps. + +For a progressive JPEG file, the data input processing is allowed to get +arbitrarily far ahead of the data output processing. (This occurs only +if the application calls jpeg_consume_input(); otherwise input and output +run in lockstep, since the input section is called only when the output +section needs more data.) In this way the application can avoid making +extra display passes when data is arriving faster than the display pass +can run. Furthermore, it is possible to abort an output pass without +losing anything, since the coefficient buffer is read-only as far as the +output section is concerned. See libjpeg.doc for more detail. + +A full-image coefficient array is only created if the JPEG file has multiple +scans (or if the application specifies buffered-image mode anyway). When +reading a single-scan file, the coefficient controller normally creates only +a one-MCU buffer, so input and output processing must run in lockstep in this +case. jpeg_consume_input() is effectively a no-op in this situation. + +The main impact of dividing the decompressor in this fashion is that we must +be very careful with shared variables in the cinfo data structure. Each +variable that can change during the course of decompression must be +classified as belonging to data input or data output, and each section must +look only at its own variables. For example, the data output section may not +depend on any of the variables that describe the current scan in the JPEG +file, because these may change as the data input section advances into a new +scan. + +The progress monitor is (somewhat arbitrarily) defined to treat input of the +file as one pass when buffered-image mode is not used, and to ignore data +input work completely when buffered-image mode is used. Note that the +library has no reliable way to predict the number of passes when dealing +with a progressive JPEG file, nor can it predict the number of output passes +in buffered-image mode. So the work estimate is inherently bogus anyway. + +No comparable division is currently made in the compression library, because +there isn't any real need for it. + + +*** Data formats *** + +Arrays of pixel sample values use the following data structure: + + typedef something JSAMPLE; a pixel component value, 0..MAXJSAMPLE + typedef JSAMPLE *JSAMPROW; ptr to a row of samples + typedef JSAMPROW *JSAMPARRAY; ptr to a list of rows + typedef JSAMPARRAY *JSAMPIMAGE; ptr to a list of color-component arrays + +The basic element type JSAMPLE will typically be one of unsigned char, +(signed) char, or short. Short will be used if samples wider than 8 bits are +to be supported (this is a compile-time option). Otherwise, unsigned char is +used if possible. If the compiler only supports signed chars, then it is +necessary to mask off the value when reading. Thus, all reads of JSAMPLE +values must be coded as "GETJSAMPLE(value)", where the macro will be defined +as "((value) & 0xFF)" on signed-char machines and "((int) (value))" elsewhere. + +With these conventions, JSAMPLE values can be assumed to be >= 0. This helps +simplify correct rounding during downsampling, etc. The JPEG standard's +specification that sample values run from -128..127 is accommodated by +subtracting 128 just as the sample value is copied into the source array for +the DCT step (this will be an array of signed ints). Similarly, during +decompression the output of the IDCT step will be immediately shifted back to +0..255. (NB: different values are required when 12-bit samples are in use. +The code is written in terms of MAXJSAMPLE and CENTERJSAMPLE, which will be +defined as 255 and 128 respectively in an 8-bit implementation, and as 4095 +and 2048 in a 12-bit implementation.) + +We use a pointer per row, rather than a two-dimensional JSAMPLE array. This +choice costs only a small amount of memory and has several benefits: +* Code using the data structure doesn't need to know the allocated width of + the rows. This simplifies edge expansion/compression, since we can work + in an array that's wider than the logical picture width. +* Indexing doesn't require multiplication; this is a performance win on many + machines. +* Arrays with more than 64K total elements can be supported even on machines + where malloc() cannot allocate chunks larger than 64K. +* The rows forming a component array may be allocated at different times + without extra copying. This trick allows some speedups in smoothing steps + that need access to the previous and next rows. + +Note that each color component is stored in a separate array; we don't use the +traditional layout in which the components of a pixel are stored together. +This simplifies coding of modules that work on each component independently, +because they don't need to know how many components there are. Furthermore, +we can read or write each component to a temporary file independently, which +is helpful when dealing with noninterleaved JPEG files. + +In general, a specific sample value is accessed by code such as + GETJSAMPLE(image[colorcomponent][row][col]) +where col is measured from the image left edge, but row is measured from the +first sample row currently in memory. Either of the first two indexings can +be precomputed by copying the relevant pointer. + + +Since most image-processing applications prefer to work on images in which +the components of a pixel are stored together, the data passed to or from the +surrounding application uses the traditional convention: a single pixel is +represented by N consecutive JSAMPLE values, and an image row is an array of +(# of color components)*(image width) JSAMPLEs. One or more rows of data can +be represented by a pointer of type JSAMPARRAY in this scheme. This scheme is +converted to component-wise storage inside the JPEG library. (Applications +that want to skip JPEG preprocessing or postprocessing will have to contend +with component-wise storage.) + + +Arrays of DCT-coefficient values use the following data structure: + + typedef short JCOEF; a 16-bit signed integer + typedef JCOEF JBLOCK[DCTSIZE2]; an 8x8 block of coefficients + typedef JBLOCK *JBLOCKROW; ptr to one horizontal row of 8x8 blocks + typedef JBLOCKROW *JBLOCKARRAY; ptr to a list of such rows + typedef JBLOCKARRAY *JBLOCKIMAGE; ptr to a list of color component arrays + +The underlying type is at least a 16-bit signed integer; while "short" is big +enough on all machines of interest, on some machines it is preferable to use +"int" for speed reasons, despite the storage cost. Coefficients are grouped +into 8x8 blocks (but we always use #defines DCTSIZE and DCTSIZE2 rather than +"8" and "64"). + +The contents of a coefficient block may be in either "natural" or zigzagged +order, and may be true values or divided by the quantization coefficients, +depending on where the block is in the processing pipeline. In the current +library, coefficient blocks are kept in natural order everywhere; the entropy +codecs zigzag or dezigzag the data as it is written or read. The blocks +contain quantized coefficients everywhere outside the DCT/IDCT subsystems. +(This latter decision may need to be revisited to support variable +quantization a la JPEG Part 3.) + +Notice that the allocation unit is now a row of 8x8 blocks, corresponding to +eight rows of samples. Otherwise the structure is much the same as for +samples, and for the same reasons. + +On machines where malloc() can't handle a request bigger than 64Kb, this data +structure limits us to rows of less than 512 JBLOCKs, or a picture width of +4000+ pixels. This seems an acceptable restriction. + + +On 80x86 machines, the bottom-level pointer types (JSAMPROW and JBLOCKROW) +must be declared as "far" pointers, but the upper levels can be "near" +(implying that the pointer lists are allocated in the DS segment). +We use a #define symbol FAR, which expands to the "far" keyword when +compiling on 80x86 machines and to nothing elsewhere. + + +*** Suspendable processing *** + +In some applications it is desirable to use the JPEG library as an +incremental, memory-to-memory filter. In this situation the data source or +destination may be a limited-size buffer, and we can't rely on being able to +empty or refill the buffer at arbitrary times. Instead the application would +like to have control return from the library at buffer overflow/underrun, and +then resume compression or decompression at a later time. + +This scenario is supported for simple cases. (For anything more complex, we +recommend that the application "bite the bullet" and develop real multitasking +capability.) The libjpeg.doc file goes into more detail about the usage and +limitations of this capability; here we address the implications for library +structure. + +The essence of the problem is that the entropy codec (coder or decoder) must +be prepared to stop at arbitrary times. In turn, the controllers that call +the entropy codec must be able to stop before having produced or consumed all +the data that they normally would handle in one call. That part is reasonably +straightforward: we make the controller call interfaces include "progress +counters" which indicate the number of data chunks successfully processed, and +we require callers to test the counter rather than just assume all of the data +was processed. + +Rather than trying to restart at an arbitrary point, the current Huffman +codecs are designed to restart at the beginning of the current MCU after a +suspension due to buffer overflow/underrun. At the start of each call, the +codec's internal state is loaded from permanent storage (in the JPEG object +structures) into local variables. On successful completion of the MCU, the +permanent state is updated. (This copying is not very expensive, and may even +lead to *improved* performance if the local variables can be registerized.) +If a suspension occurs, the codec simply returns without updating the state, +thus effectively reverting to the start of the MCU. Note that this implies +leaving some data unprocessed in the source/destination buffer (ie, the +compressed partial MCU). The data source/destination module interfaces are +specified so as to make this possible. This also implies that the data buffer +must be large enough to hold a worst-case compressed MCU; a couple thousand +bytes should be enough. + +In a successive-approximation AC refinement scan, the progressive Huffman +decoder has to be able to undo assignments of newly nonzero coefficients if it +suspends before the MCU is complete, since decoding requires distinguishing +previously-zero and previously-nonzero coefficients. This is a bit tedious +but probably won't have much effect on performance. Other variants of Huffman +decoding need not worry about this, since they will just store the same values +again if forced to repeat the MCU. + +This approach would probably not work for an arithmetic codec, since its +modifiable state is quite large and couldn't be copied cheaply. Instead it +would have to suspend and resume exactly at the point of the buffer end. + +The JPEG marker reader is designed to cope with suspension at an arbitrary +point. It does so by backing up to the start of the marker parameter segment, +so the data buffer must be big enough to hold the largest marker of interest. +Again, a couple KB should be adequate. (A special "skip" convention is used +to bypass COM and APPn markers, so these can be larger than the buffer size +without causing problems; otherwise a 64K buffer would be needed in the worst +case.) + +The JPEG marker writer currently does *not* cope with suspension. I feel that +this is not necessary; it is much easier simply to require the application to +ensure there is enough buffer space before starting. (An empty 2K buffer is +more than sufficient for the header markers; and ensuring there are a dozen or +two bytes available before calling jpeg_finish_compress() will suffice for the +trailer.) This would not work for writing multi-scan JPEG files, but +we simply do not intend to support that capability with suspension. + + +*** Memory manager services *** + +The JPEG library's memory manager controls allocation and deallocation of +memory, and it manages large "virtual" data arrays on machines where the +operating system does not provide virtual memory. Note that the same +memory manager serves both compression and decompression operations. + +In all cases, allocated objects are tied to a particular compression or +decompression master record, and they will be released when that master +record is destroyed. + +The memory manager does not provide explicit deallocation of objects. +Instead, objects are created in "pools" of free storage, and a whole pool +can be freed at once. This approach helps prevent storage-leak bugs, and +it speeds up operations whenever malloc/free are slow (as they often are). +The pools can be regarded as lifetime identifiers for objects. Two +pools/lifetimes are defined: + * JPOOL_PERMANENT lasts until master record is destroyed + * JPOOL_IMAGE lasts until done with image (JPEG datastream) +Permanent lifetime is used for parameters and tables that should be carried +across from one datastream to another; this includes all application-visible +parameters. Image lifetime is used for everything else. (A third lifetime, +JPOOL_PASS = one processing pass, was originally planned. However it was +dropped as not being worthwhile. The actual usage patterns are such that the +peak memory usage would be about the same anyway; and having per-pass storage +substantially complicates the virtual memory allocation rules --- see below.) + +The memory manager deals with three kinds of object: +1. "Small" objects. Typically these require no more than 10K-20K total. +2. "Large" objects. These may require tens to hundreds of K depending on + image size. Semantically they behave the same as small objects, but we + distinguish them for two reasons: + * On MS-DOS machines, large objects are referenced by FAR pointers, + small objects by NEAR pointers. + * Pool allocation heuristics may differ for large and small objects. + Note that individual "large" objects cannot exceed the size allowed by + type size_t, which may be 64K or less on some machines. +3. "Virtual" objects. These are large 2-D arrays of JSAMPLEs or JBLOCKs + (typically large enough for the entire image being processed). The + memory manager provides stripwise access to these arrays. On machines + without virtual memory, the rest of the array may be swapped out to a + temporary file. + +(Note: JSAMPARRAY and JBLOCKARRAY data structures are a combination of large +objects for the data proper and small objects for the row pointers. For +convenience and speed, the memory manager provides single routines to create +these structures. Similarly, virtual arrays include a small control block +and a JSAMPARRAY or JBLOCKARRAY working buffer, all created with one call.) + +In the present implementation, virtual arrays are only permitted to have image +lifespan. (Permanent lifespan would not be reasonable, and pass lifespan is +not very useful since a virtual array's raison d'etre is to store data for +multiple passes through the image.) We also expect that only "small" objects +will be given permanent lifespan, though this restriction is not required by +the memory manager. + +In a non-virtual-memory machine, some performance benefit can be gained by +making the in-memory buffers for virtual arrays be as large as possible. +(For small images, the buffers might fit entirely in memory, so blind +swapping would be very wasteful.) The memory manager will adjust the height +of the buffers to fit within a prespecified maximum memory usage. In order +to do this in a reasonably optimal fashion, the manager needs to allocate all +of the virtual arrays at once. Therefore, there isn't a one-step allocation +routine for virtual arrays; instead, there is a "request" routine that simply +allocates the control block, and a "realize" routine (called just once) that +determines space allocation and creates all of the actual buffers. The +realize routine must allow for space occupied by non-virtual large objects. +(We don't bother to factor in the space needed for small objects, on the +grounds that it isn't worth the trouble.) + +To support all this, we establish the following protocol for doing business +with the memory manager: + 1. Modules must request virtual arrays (which may have only image lifespan) + during the initial setup phase, i.e., in their jinit_xxx routines. + 2. All "large" objects (including JSAMPARRAYs and JBLOCKARRAYs) must also be + allocated during initial setup. + 3. realize_virt_arrays will be called at the completion of initial setup. + The above conventions ensure that sufficient information is available + for it to choose a good size for virtual array buffers. +Small objects of any lifespan may be allocated at any time. We expect that +the total space used for small objects will be small enough to be negligible +in the realize_virt_arrays computation. + +In a virtual-memory machine, we simply pretend that the available space is +infinite, thus causing realize_virt_arrays to decide that it can allocate all +the virtual arrays as full-size in-memory buffers. The overhead of the +virtual-array access protocol is very small when no swapping occurs. + +A virtual array can be specified to be "pre-zeroed"; when this flag is set, +never-yet-written sections of the array are set to zero before being made +available to the caller. If this flag is not set, never-written sections +of the array contain garbage. (This feature exists primarily because the +equivalent logic would otherwise be needed in jdcoefct.c for progressive +JPEG mode; we may as well make it available for possible other uses.) + +The first write pass on a virtual array is required to occur in top-to-bottom +order; read passes, as well as any write passes after the first one, may +access the array in any order. This restriction exists partly to simplify +the virtual array control logic, and partly because some file systems may not +support seeking beyond the current end-of-file in a temporary file. The main +implication of this restriction is that rearrangement of rows (such as +converting top-to-bottom data order to bottom-to-top) must be handled while +reading data out of the virtual array, not while putting it in. + + +*** Memory manager internal structure *** + +To isolate system dependencies as much as possible, we have broken the +memory manager into two parts. There is a reasonably system-independent +"front end" (jmemmgr.c) and a "back end" that contains only the code +likely to change across systems. All of the memory management methods +outlined above are implemented by the front end. The back end provides +the following routines for use by the front end (none of these routines +are known to the rest of the JPEG code): + +jpeg_mem_init, jpeg_mem_term system-dependent initialization/shutdown + +jpeg_get_small, jpeg_free_small interface to malloc and free library routines + (or their equivalents) + +jpeg_get_large, jpeg_free_large interface to FAR malloc/free in MSDOS machines; + else usually the same as + jpeg_get_small/jpeg_free_small + +jpeg_mem_available estimate available memory + +jpeg_open_backing_store create a backing-store object + +read_backing_store, manipulate a backing-store object +write_backing_store, +close_backing_store + +On some systems there will be more than one type of backing-store object +(specifically, in MS-DOS a backing store file might be an area of extended +memory as well as a disk file). jpeg_open_backing_store is responsible for +choosing how to implement a given object. The read/write/close routines +are method pointers in the structure that describes a given object; this +lets them be different for different object types. + +It may be necessary to ensure that backing store objects are explicitly +released upon abnormal program termination. For example, MS-DOS won't free +extended memory by itself. To support this, we will expect the main program +or surrounding application to arrange to call self_destruct (typically via +jpeg_destroy) upon abnormal termination. This may require a SIGINT signal +handler or equivalent. We don't want to have the back end module install its +own signal handler, because that would pre-empt the surrounding application's +ability to control signal handling. + +The IJG distribution includes several memory manager back end implementations. +Usually the same back end should be suitable for all applications on a given +system, but it is possible for an application to supply its own back end at +need. + + +*** Implications of DNL marker *** + +Some JPEG files may use a DNL marker to postpone definition of the image +height (this would be useful for a fax-like scanner's output, for instance). +In these files the SOF marker claims the image height is 0, and you only +find out the true image height at the end of the first scan. + +We could read these files as follows: +1. Upon seeing zero image height, replace it by 65535 (the maximum allowed). +2. When the DNL is found, update the image height in the global image + descriptor. +This implies that control modules must avoid making copies of the image +height, and must re-test for termination after each MCU row. This would +be easy enough to do. + +In cases where image-size data structures are allocated, this approach will +result in very inefficient use of virtual memory or much-larger-than-necessary +temporary files. This seems acceptable for something that probably won't be a +mainstream usage. People might have to forgo use of memory-hogging options +(such as two-pass color quantization or noninterleaved JPEG files) if they +want efficient conversion of such files. (One could improve efficiency by +demanding a user-supplied upper bound for the height, less than 65536; in most +cases it could be much less.) + +The standard also permits the SOF marker to overestimate the image height, +with a DNL to give the true, smaller height at the end of the first scan. +This would solve the space problems if the overestimate wasn't too great. +However, it implies that you don't even know whether DNL will be used. + +This leads to a couple of very serious objections: +1. Testing for a DNL marker must occur in the inner loop of the decompressor's + Huffman decoder; this implies a speed penalty whether the feature is used + or not. +2. There is no way to hide the last-minute change in image height from an + application using the decoder. Thus *every* application using the IJG + library would suffer a complexity penalty whether it cared about DNL or + not. +We currently do not support DNL because of these problems. + +A different approach is to insist that DNL-using files be preprocessed by a +separate program that reads ahead to the DNL, then goes back and fixes the SOF +marker. This is a much simpler solution and is probably far more efficient. +Even if one wants piped input, buffering the first scan of the JPEG file needs +a lot smaller temp file than is implied by the maximum-height method. For +this approach we'd simply treat DNL as a no-op in the decompressor (at most, +check that it matches the SOF image height). + +We will not worry about making the compressor capable of outputting DNL. +Something similar to the first scheme above could be applied if anyone ever +wants to make that work. diff --git a/lc-continuity/mk4/modimage/jpeg-6b/transupp.c b/lc-continuity/mk4/modimage/jpeg-6b/transupp.c new file mode 100644 index 0000000000000000000000000000000000000000..e5ec5642f634d3877cd084f6646bb428e1cec94e --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/transupp.c @@ -0,0 +1,928 @@ +/* + * transupp.c + * + * Copyright (C) 1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains image transformation routines and other utility code + * used by the jpegtran sample application. These are NOT part of the core + * JPEG library. But we keep these routines separate from jpegtran.c to + * ease the task of maintaining jpegtran-like programs that have other user + * interfaces. + */ + +/* Although this file really shouldn't have access to the library internals, + * it's helpful to let it call jround_up() and jcopy_block_row(). + */ +#define JPEG_INTERNALS + +#include "jinclude.h" +#include "jpeglib.h" +#include "transupp.h" /* My own external interface */ + + +#if TRANSFORMS_SUPPORTED + +/* + * Lossless image transformation routines. These routines work on DCT + * coefficient arrays and thus do not require any lossy decompression + * or recompression of the image. + * Thanks to Guido Vollbeding for the initial design and code of this feature. + * + * Horizontal flipping is done in-place, using a single top-to-bottom + * pass through the virtual source array. It will thus be much the + * fastest option for images larger than main memory. + * + * The other routines require a set of destination virtual arrays, so they + * need twice as much memory as jpegtran normally does. The destination + * arrays are always written in normal scan order (top to bottom) because + * the virtual array manager expects this. The source arrays will be scanned + * in the corresponding order, which means multiple passes through the source + * arrays for most of the transforms. That could result in much thrashing + * if the image is larger than main memory. + * + * Some notes about the operating environment of the individual transform + * routines: + * 1. Both the source and destination virtual arrays are allocated from the + * source JPEG object, and therefore should be manipulated by calling the + * source's memory manager. + * 2. The destination's component count should be used. It may be smaller + * than the source's when forcing to grayscale. + * 3. Likewise the destination's sampling factors should be used. When + * forcing to grayscale the destination's sampling factors will be all 1, + * and we may as well take that as the effective iMCU size. + * 4. When "trim" is in effect, the destination's dimensions will be the + * trimmed values but the source's will be untrimmed. + * 5. All the routines assume that the source and destination buffers are + * padded out to a full iMCU boundary. This is true, although for the + * source buffer it is an undocumented property of jdcoefct.c. + * Notes 2,3,4 boil down to this: generally we should use the destination's + * dimensions and ignore the source's. + */ + + +LOCAL(void) +do_flip_h (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + jvirt_barray_ptr *src_coef_arrays) +/* Horizontal flip; done in-place, so no separate dest array is required */ +{ + JDIMENSION MCU_cols, comp_width, blk_x, blk_y; + int ci, k, offset_y; + JBLOCKARRAY buffer; + JCOEFPTR ptr1, ptr2; + JCOEF temp1, temp2; + jpeg_component_info *compptr; + + /* Horizontal mirroring of DCT blocks is accomplished by swapping + * pairs of blocks in-place. Within a DCT block, we perform horizontal + * mirroring by changing the signs of odd-numbered columns. + * Partial iMCUs at the right edge are left untouched. + */ + MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE); + + for (ci = 0; ci < dstinfo->num_components; ci++) { + compptr = dstinfo->comp_info + ci; + comp_width = MCU_cols * compptr->h_samp_factor; + for (blk_y = 0; blk_y < compptr->height_in_blocks; + blk_y += compptr->v_samp_factor) { + buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, src_coef_arrays[ci], blk_y, + (JDIMENSION) compptr->v_samp_factor, TRUE); + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + for (blk_x = 0; blk_x * 2 < comp_width; blk_x++) { + ptr1 = buffer[offset_y][blk_x]; + ptr2 = buffer[offset_y][comp_width - blk_x - 1]; + /* this unrolled loop doesn't need to know which row it's on... */ + for (k = 0; k < DCTSIZE2; k += 2) { + temp1 = *ptr1; /* swap even column */ + temp2 = *ptr2; + *ptr1++ = temp2; + *ptr2++ = temp1; + temp1 = *ptr1; /* swap odd column with sign change */ + temp2 = *ptr2; + *ptr1++ = -temp2; + *ptr2++ = -temp1; + } + } + } + } + } +} + + +LOCAL(void) +do_flip_v (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + jvirt_barray_ptr *src_coef_arrays, + jvirt_barray_ptr *dst_coef_arrays) +/* Vertical flip */ +{ + JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y; + int ci, i, j, offset_y; + JBLOCKARRAY src_buffer, dst_buffer; + JBLOCKROW src_row_ptr, dst_row_ptr; + JCOEFPTR src_ptr, dst_ptr; + jpeg_component_info *compptr; + + /* We output into a separate array because we can't touch different + * rows of the source virtual array simultaneously. Otherwise, this + * is a pretty straightforward analog of horizontal flip. + * Within a DCT block, vertical mirroring is done by changing the signs + * of odd-numbered rows. + * Partial iMCUs at the bottom edge are copied verbatim. + */ + MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE); + + for (ci = 0; ci < dstinfo->num_components; ci++) { + compptr = dstinfo->comp_info + ci; + comp_height = MCU_rows * compptr->v_samp_factor; + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; + dst_blk_y += compptr->v_samp_factor) { + dst_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, + (JDIMENSION) compptr->v_samp_factor, TRUE); + if (dst_blk_y < comp_height) { + /* Row is within the mirrorable area. */ + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, src_coef_arrays[ci], + comp_height - dst_blk_y - (JDIMENSION) compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, FALSE); + } else { + /* Bottom-edge blocks will be copied verbatim. */ + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_y, + (JDIMENSION) compptr->v_samp_factor, FALSE); + } + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + if (dst_blk_y < comp_height) { + /* Row is within the mirrorable area. */ + dst_row_ptr = dst_buffer[offset_y]; + src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1]; + for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; + dst_blk_x++) { + dst_ptr = dst_row_ptr[dst_blk_x]; + src_ptr = src_row_ptr[dst_blk_x]; + for (i = 0; i < DCTSIZE; i += 2) { + /* copy even row */ + for (j = 0; j < DCTSIZE; j++) + *dst_ptr++ = *src_ptr++; + /* copy odd row with sign change */ + for (j = 0; j < DCTSIZE; j++) + *dst_ptr++ = - *src_ptr++; + } + } + } else { + /* Just copy row verbatim. */ + jcopy_block_row(src_buffer[offset_y], dst_buffer[offset_y], + compptr->width_in_blocks); + } + } + } + } +} + + +LOCAL(void) +do_transpose (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + jvirt_barray_ptr *src_coef_arrays, + jvirt_barray_ptr *dst_coef_arrays) +/* Transpose source into destination */ +{ + JDIMENSION dst_blk_x, dst_blk_y; + int ci, i, j, offset_x, offset_y; + JBLOCKARRAY src_buffer, dst_buffer; + JCOEFPTR src_ptr, dst_ptr; + jpeg_component_info *compptr; + + /* Transposing pixels within a block just requires transposing the + * DCT coefficients. + * Partial iMCUs at the edges require no special treatment; we simply + * process all the available DCT blocks for every component. + */ + for (ci = 0; ci < dstinfo->num_components; ci++) { + compptr = dstinfo->comp_info + ci; + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; + dst_blk_y += compptr->v_samp_factor) { + dst_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, + (JDIMENSION) compptr->v_samp_factor, TRUE); + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; + dst_blk_x += compptr->h_samp_factor) { + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x, + (JDIMENSION) compptr->h_samp_factor, FALSE); + for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { + src_ptr = src_buffer[offset_x][dst_blk_y + offset_y]; + dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; + for (i = 0; i < DCTSIZE; i++) + for (j = 0; j < DCTSIZE; j++) + dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; + } + } + } + } + } +} + + +LOCAL(void) +do_rot_90 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + jvirt_barray_ptr *src_coef_arrays, + jvirt_barray_ptr *dst_coef_arrays) +/* 90 degree rotation is equivalent to + * 1. Transposing the image; + * 2. Horizontal mirroring. + * These two steps are merged into a single processing routine. + */ +{ + JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y; + int ci, i, j, offset_x, offset_y; + JBLOCKARRAY src_buffer, dst_buffer; + JCOEFPTR src_ptr, dst_ptr; + jpeg_component_info *compptr; + + /* Because of the horizontal mirror step, we can't process partial iMCUs + * at the (output) right edge properly. They just get transposed and + * not mirrored. + */ + MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE); + + for (ci = 0; ci < dstinfo->num_components; ci++) { + compptr = dstinfo->comp_info + ci; + comp_width = MCU_cols * compptr->h_samp_factor; + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; + dst_blk_y += compptr->v_samp_factor) { + dst_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, + (JDIMENSION) compptr->v_samp_factor, TRUE); + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; + dst_blk_x += compptr->h_samp_factor) { + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x, + (JDIMENSION) compptr->h_samp_factor, FALSE); + for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { + src_ptr = src_buffer[offset_x][dst_blk_y + offset_y]; + if (dst_blk_x < comp_width) { + /* Block is within the mirrorable area. */ + dst_ptr = dst_buffer[offset_y] + [comp_width - dst_blk_x - offset_x - 1]; + for (i = 0; i < DCTSIZE; i++) { + for (j = 0; j < DCTSIZE; j++) + dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; + i++; + for (j = 0; j < DCTSIZE; j++) + dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; + } + } else { + /* Edge blocks are transposed but not mirrored. */ + dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; + for (i = 0; i < DCTSIZE; i++) + for (j = 0; j < DCTSIZE; j++) + dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; + } + } + } + } + } + } +} + + +LOCAL(void) +do_rot_270 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + jvirt_barray_ptr *src_coef_arrays, + jvirt_barray_ptr *dst_coef_arrays) +/* 270 degree rotation is equivalent to + * 1. Horizontal mirroring; + * 2. Transposing the image. + * These two steps are merged into a single processing routine. + */ +{ + JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y; + int ci, i, j, offset_x, offset_y; + JBLOCKARRAY src_buffer, dst_buffer; + JCOEFPTR src_ptr, dst_ptr; + jpeg_component_info *compptr; + + /* Because of the horizontal mirror step, we can't process partial iMCUs + * at the (output) bottom edge properly. They just get transposed and + * not mirrored. + */ + MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE); + + for (ci = 0; ci < dstinfo->num_components; ci++) { + compptr = dstinfo->comp_info + ci; + comp_height = MCU_rows * compptr->v_samp_factor; + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; + dst_blk_y += compptr->v_samp_factor) { + dst_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, + (JDIMENSION) compptr->v_samp_factor, TRUE); + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; + dst_blk_x += compptr->h_samp_factor) { + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x, + (JDIMENSION) compptr->h_samp_factor, FALSE); + for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { + dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; + if (dst_blk_y < comp_height) { + /* Block is within the mirrorable area. */ + src_ptr = src_buffer[offset_x] + [comp_height - dst_blk_y - offset_y - 1]; + for (i = 0; i < DCTSIZE; i++) { + for (j = 0; j < DCTSIZE; j++) { + dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; + j++; + dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; + } + } + } else { + /* Edge blocks are transposed but not mirrored. */ + src_ptr = src_buffer[offset_x][dst_blk_y + offset_y]; + for (i = 0; i < DCTSIZE; i++) + for (j = 0; j < DCTSIZE; j++) + dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; + } + } + } + } + } + } +} + + +LOCAL(void) +do_rot_180 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + jvirt_barray_ptr *src_coef_arrays, + jvirt_barray_ptr *dst_coef_arrays) +/* 180 degree rotation is equivalent to + * 1. Vertical mirroring; + * 2. Horizontal mirroring. + * These two steps are merged into a single processing routine. + */ +{ + JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y; + int ci, i, j, offset_y; + JBLOCKARRAY src_buffer, dst_buffer; + JBLOCKROW src_row_ptr, dst_row_ptr; + JCOEFPTR src_ptr, dst_ptr; + jpeg_component_info *compptr; + + MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE); + MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE); + + for (ci = 0; ci < dstinfo->num_components; ci++) { + compptr = dstinfo->comp_info + ci; + comp_width = MCU_cols * compptr->h_samp_factor; + comp_height = MCU_rows * compptr->v_samp_factor; + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; + dst_blk_y += compptr->v_samp_factor) { + dst_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, + (JDIMENSION) compptr->v_samp_factor, TRUE); + if (dst_blk_y < comp_height) { + /* Row is within the vertically mirrorable area. */ + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, src_coef_arrays[ci], + comp_height - dst_blk_y - (JDIMENSION) compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, FALSE); + } else { + /* Bottom-edge rows are only mirrored horizontally. */ + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_y, + (JDIMENSION) compptr->v_samp_factor, FALSE); + } + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + if (dst_blk_y < comp_height) { + /* Row is within the mirrorable area. */ + dst_row_ptr = dst_buffer[offset_y]; + src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1]; + /* Process the blocks that can be mirrored both ways. */ + for (dst_blk_x = 0; dst_blk_x < comp_width; dst_blk_x++) { + dst_ptr = dst_row_ptr[dst_blk_x]; + src_ptr = src_row_ptr[comp_width - dst_blk_x - 1]; + for (i = 0; i < DCTSIZE; i += 2) { + /* For even row, negate every odd column. */ + for (j = 0; j < DCTSIZE; j += 2) { + *dst_ptr++ = *src_ptr++; + *dst_ptr++ = - *src_ptr++; + } + /* For odd row, negate every even column. */ + for (j = 0; j < DCTSIZE; j += 2) { + *dst_ptr++ = - *src_ptr++; + *dst_ptr++ = *src_ptr++; + } + } + } + /* Any remaining right-edge blocks are only mirrored vertically. */ + for (; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) { + dst_ptr = dst_row_ptr[dst_blk_x]; + src_ptr = src_row_ptr[dst_blk_x]; + for (i = 0; i < DCTSIZE; i += 2) { + for (j = 0; j < DCTSIZE; j++) + *dst_ptr++ = *src_ptr++; + for (j = 0; j < DCTSIZE; j++) + *dst_ptr++ = - *src_ptr++; + } + } + } else { + /* Remaining rows are just mirrored horizontally. */ + dst_row_ptr = dst_buffer[offset_y]; + src_row_ptr = src_buffer[offset_y]; + /* Process the blocks that can be mirrored. */ + for (dst_blk_x = 0; dst_blk_x < comp_width; dst_blk_x++) { + dst_ptr = dst_row_ptr[dst_blk_x]; + src_ptr = src_row_ptr[comp_width - dst_blk_x - 1]; + for (i = 0; i < DCTSIZE2; i += 2) { + *dst_ptr++ = *src_ptr++; + *dst_ptr++ = - *src_ptr++; + } + } + /* Any remaining right-edge blocks are only copied. */ + for (; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) { + dst_ptr = dst_row_ptr[dst_blk_x]; + src_ptr = src_row_ptr[dst_blk_x]; + for (i = 0; i < DCTSIZE2; i++) + *dst_ptr++ = *src_ptr++; + } + } + } + } + } +} + + +LOCAL(void) +do_transverse (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + jvirt_barray_ptr *src_coef_arrays, + jvirt_barray_ptr *dst_coef_arrays) +/* Transverse transpose is equivalent to + * 1. 180 degree rotation; + * 2. Transposition; + * or + * 1. Horizontal mirroring; + * 2. Transposition; + * 3. Horizontal mirroring. + * These steps are merged into a single processing routine. + */ +{ + JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y; + int ci, i, j, offset_x, offset_y; + JBLOCKARRAY src_buffer, dst_buffer; + JCOEFPTR src_ptr, dst_ptr; + jpeg_component_info *compptr; + + MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE); + MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE); + + for (ci = 0; ci < dstinfo->num_components; ci++) { + compptr = dstinfo->comp_info + ci; + comp_width = MCU_cols * compptr->h_samp_factor; + comp_height = MCU_rows * compptr->v_samp_factor; + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; + dst_blk_y += compptr->v_samp_factor) { + dst_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, + (JDIMENSION) compptr->v_samp_factor, TRUE); + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; + dst_blk_x += compptr->h_samp_factor) { + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x, + (JDIMENSION) compptr->h_samp_factor, FALSE); + for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { + if (dst_blk_y < comp_height) { + src_ptr = src_buffer[offset_x] + [comp_height - dst_blk_y - offset_y - 1]; + if (dst_blk_x < comp_width) { + /* Block is within the mirrorable area. */ + dst_ptr = dst_buffer[offset_y] + [comp_width - dst_blk_x - offset_x - 1]; + for (i = 0; i < DCTSIZE; i++) { + for (j = 0; j < DCTSIZE; j++) { + dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; + j++; + dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; + } + i++; + for (j = 0; j < DCTSIZE; j++) { + dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; + j++; + dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; + } + } + } else { + /* Right-edge blocks are mirrored in y only */ + dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; + for (i = 0; i < DCTSIZE; i++) { + for (j = 0; j < DCTSIZE; j++) { + dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; + j++; + dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; + } + } + } + } else { + src_ptr = src_buffer[offset_x][dst_blk_y + offset_y]; + if (dst_blk_x < comp_width) { + /* Bottom-edge blocks are mirrored in x only */ + dst_ptr = dst_buffer[offset_y] + [comp_width - dst_blk_x - offset_x - 1]; + for (i = 0; i < DCTSIZE; i++) { + for (j = 0; j < DCTSIZE; j++) + dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; + i++; + for (j = 0; j < DCTSIZE; j++) + dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; + } + } else { + /* At lower right corner, just transpose, no mirroring */ + dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; + for (i = 0; i < DCTSIZE; i++) + for (j = 0; j < DCTSIZE; j++) + dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; + } + } + } + } + } + } + } +} + + +/* Request any required workspace. + * + * We allocate the workspace virtual arrays from the source decompression + * object, so that all the arrays (both the original data and the workspace) + * will be taken into account while making memory management decisions. + * Hence, this routine must be called after jpeg_read_header (which reads + * the image dimensions) and before jpeg_read_coefficients (which realizes + * the source's virtual arrays). + */ + +GLOBAL(void) +jtransform_request_workspace (j_decompress_ptr srcinfo, + jpeg_transform_info *info) +{ + jvirt_barray_ptr *coef_arrays = NULL; + jpeg_component_info *compptr; + int ci; + + if (info->force_grayscale && + srcinfo->jpeg_color_space == JCS_YCbCr && + srcinfo->num_components == 3) { + /* We'll only process the first component */ + info->num_components = 1; + } else { + /* Process all the components */ + info->num_components = srcinfo->num_components; + } + + switch (info->transform) { + case JXFORM_NONE: + case JXFORM_FLIP_H: + /* Don't need a workspace array */ + break; + case JXFORM_FLIP_V: + case JXFORM_ROT_180: + /* Need workspace arrays having same dimensions as source image. + * Note that we allocate arrays padded out to the next iMCU boundary, + * so that transform routines need not worry about missing edge blocks. + */ + coef_arrays = (jvirt_barray_ptr *) + (*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE, + SIZEOF(jvirt_barray_ptr) * info->num_components); + for (ci = 0; ci < info->num_components; ci++) { + compptr = srcinfo->comp_info + ci; + coef_arrays[ci] = (*srcinfo->mem->request_virt_barray) + ((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE, + (JDIMENSION) jround_up((long) compptr->width_in_blocks, + (long) compptr->h_samp_factor), + (JDIMENSION) jround_up((long) compptr->height_in_blocks, + (long) compptr->v_samp_factor), + (JDIMENSION) compptr->v_samp_factor); + } + break; + case JXFORM_TRANSPOSE: + case JXFORM_TRANSVERSE: + case JXFORM_ROT_90: + case JXFORM_ROT_270: + /* Need workspace arrays having transposed dimensions. + * Note that we allocate arrays padded out to the next iMCU boundary, + * so that transform routines need not worry about missing edge blocks. + */ + coef_arrays = (jvirt_barray_ptr *) + (*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE, + SIZEOF(jvirt_barray_ptr) * info->num_components); + for (ci = 0; ci < info->num_components; ci++) { + compptr = srcinfo->comp_info + ci; + coef_arrays[ci] = (*srcinfo->mem->request_virt_barray) + ((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE, + (JDIMENSION) jround_up((long) compptr->height_in_blocks, + (long) compptr->v_samp_factor), + (JDIMENSION) jround_up((long) compptr->width_in_blocks, + (long) compptr->h_samp_factor), + (JDIMENSION) compptr->h_samp_factor); + } + break; + } + info->workspace_coef_arrays = coef_arrays; +} + + +/* Transpose destination image parameters */ + +LOCAL(void) +transpose_critical_parameters (j_compress_ptr dstinfo) +{ + int tblno, i, j, ci, itemp; + jpeg_component_info *compptr; + JQUANT_TBL *qtblptr; + JDIMENSION dtemp; + UINT16 qtemp; + + /* Transpose basic image dimensions */ + dtemp = dstinfo->image_width; + dstinfo->image_width = dstinfo->image_height; + dstinfo->image_height = dtemp; + + /* Transpose sampling factors */ + for (ci = 0; ci < dstinfo->num_components; ci++) { + compptr = dstinfo->comp_info + ci; + itemp = compptr->h_samp_factor; + compptr->h_samp_factor = compptr->v_samp_factor; + compptr->v_samp_factor = itemp; + } + + /* Transpose quantization tables */ + for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) { + qtblptr = dstinfo->quant_tbl_ptrs[tblno]; + if (qtblptr != NULL) { + for (i = 0; i < DCTSIZE; i++) { + for (j = 0; j < i; j++) { + qtemp = qtblptr->quantval[i*DCTSIZE+j]; + qtblptr->quantval[i*DCTSIZE+j] = qtblptr->quantval[j*DCTSIZE+i]; + qtblptr->quantval[j*DCTSIZE+i] = qtemp; + } + } + } + } +} + + +/* Trim off any partial iMCUs on the indicated destination edge */ + +LOCAL(void) +trim_right_edge (j_compress_ptr dstinfo) +{ + int ci, max_h_samp_factor; + JDIMENSION MCU_cols; + + /* We have to compute max_h_samp_factor ourselves, + * because it hasn't been set yet in the destination + * (and we don't want to use the source's value). + */ + max_h_samp_factor = 1; + for (ci = 0; ci < dstinfo->num_components; ci++) { + int h_samp_factor = dstinfo->comp_info[ci].h_samp_factor; + max_h_samp_factor = MAX(max_h_samp_factor, h_samp_factor); + } + MCU_cols = dstinfo->image_width / (max_h_samp_factor * DCTSIZE); + if (MCU_cols > 0) /* can't trim to 0 pixels */ + dstinfo->image_width = MCU_cols * (max_h_samp_factor * DCTSIZE); +} + +LOCAL(void) +trim_bottom_edge (j_compress_ptr dstinfo) +{ + int ci, max_v_samp_factor; + JDIMENSION MCU_rows; + + /* We have to compute max_v_samp_factor ourselves, + * because it hasn't been set yet in the destination + * (and we don't want to use the source's value). + */ + max_v_samp_factor = 1; + for (ci = 0; ci < dstinfo->num_components; ci++) { + int v_samp_factor = dstinfo->comp_info[ci].v_samp_factor; + max_v_samp_factor = MAX(max_v_samp_factor, v_samp_factor); + } + MCU_rows = dstinfo->image_height / (max_v_samp_factor * DCTSIZE); + if (MCU_rows > 0) /* can't trim to 0 pixels */ + dstinfo->image_height = MCU_rows * (max_v_samp_factor * DCTSIZE); +} + + +/* Adjust output image parameters as needed. + * + * This must be called after jpeg_copy_critical_parameters() + * and before jpeg_write_coefficients(). + * + * The return value is the set of virtual coefficient arrays to be written + * (either the ones allocated by jtransform_request_workspace, or the + * original source data arrays). The caller will need to pass this value + * to jpeg_write_coefficients(). + */ + +GLOBAL(jvirt_barray_ptr *) +jtransform_adjust_parameters (j_decompress_ptr srcinfo, + j_compress_ptr dstinfo, + jvirt_barray_ptr *src_coef_arrays, + jpeg_transform_info *info) +{ + /* If force-to-grayscale is requested, adjust destination parameters */ + if (info->force_grayscale) { + /* We use jpeg_set_colorspace to make sure subsidiary settings get fixed + * properly. Among other things, the target h_samp_factor & v_samp_factor + * will get set to 1, which typically won't match the source. + * In fact we do this even if the source is already grayscale; that + * provides an easy way of coercing a grayscale JPEG with funny sampling + * factors to the customary 1,1. (Some decoders fail on other factors.) + */ + if ((dstinfo->jpeg_color_space == JCS_YCbCr && + dstinfo->num_components == 3) || + (dstinfo->jpeg_color_space == JCS_GRAYSCALE && + dstinfo->num_components == 1)) { + /* We have to preserve the source's quantization table number. */ + int sv_quant_tbl_no = dstinfo->comp_info[0].quant_tbl_no; + jpeg_set_colorspace(dstinfo, JCS_GRAYSCALE); + dstinfo->comp_info[0].quant_tbl_no = sv_quant_tbl_no; + } else { + /* Sorry, can't do it */ + ERREXIT(dstinfo, JERR_CONVERSION_NOTIMPL); + } + } + + /* Correct the destination's image dimensions etc if necessary */ + switch (info->transform) { + case JXFORM_NONE: + /* Nothing to do */ + break; + case JXFORM_FLIP_H: + if (info->trim) + trim_right_edge(dstinfo); + break; + case JXFORM_FLIP_V: + if (info->trim) + trim_bottom_edge(dstinfo); + break; + case JXFORM_TRANSPOSE: + transpose_critical_parameters(dstinfo); + /* transpose does NOT have to trim anything */ + break; + case JXFORM_TRANSVERSE: + transpose_critical_parameters(dstinfo); + if (info->trim) { + trim_right_edge(dstinfo); + trim_bottom_edge(dstinfo); + } + break; + case JXFORM_ROT_90: + transpose_critical_parameters(dstinfo); + if (info->trim) + trim_right_edge(dstinfo); + break; + case JXFORM_ROT_180: + if (info->trim) { + trim_right_edge(dstinfo); + trim_bottom_edge(dstinfo); + } + break; + case JXFORM_ROT_270: + transpose_critical_parameters(dstinfo); + if (info->trim) + trim_bottom_edge(dstinfo); + break; + } + + /* Return the appropriate output data set */ + if (info->workspace_coef_arrays != NULL) + return info->workspace_coef_arrays; + return src_coef_arrays; +} + + +/* Execute the actual transformation, if any. + * + * This must be called *after* jpeg_write_coefficients, because it depends + * on jpeg_write_coefficients to have computed subsidiary values such as + * the per-component width and height fields in the destination object. + * + * Note that some transformations will modify the source data arrays! + */ + +GLOBAL(void) +jtransform_execute_transformation (j_decompress_ptr srcinfo, + j_compress_ptr dstinfo, + jvirt_barray_ptr *src_coef_arrays, + jpeg_transform_info *info) +{ + jvirt_barray_ptr *dst_coef_arrays = info->workspace_coef_arrays; + + switch (info->transform) { + case JXFORM_NONE: + break; + case JXFORM_FLIP_H: + do_flip_h(srcinfo, dstinfo, src_coef_arrays); + break; + case JXFORM_FLIP_V: + do_flip_v(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays); + break; + case JXFORM_TRANSPOSE: + do_transpose(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays); + break; + case JXFORM_TRANSVERSE: + do_transverse(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays); + break; + case JXFORM_ROT_90: + do_rot_90(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays); + break; + case JXFORM_ROT_180: + do_rot_180(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays); + break; + case JXFORM_ROT_270: + do_rot_270(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays); + break; + } +} + +#endif /* TRANSFORMS_SUPPORTED */ + + +/* Setup decompression object to save desired markers in memory. + * This must be called before jpeg_read_header() to have the desired effect. + */ + +GLOBAL(void) +jcopy_markers_setup (j_decompress_ptr srcinfo, JCOPY_OPTION option) +{ +#ifdef SAVE_MARKERS_SUPPORTED + int m; + + /* Save comments except under NONE option */ + if (option != JCOPYOPT_NONE) { + jpeg_save_markers(srcinfo, JPEG_COM, 0xFFFF); + } + /* Save all types of APPn markers iff ALL option */ + if (option == JCOPYOPT_ALL) { + for (m = 0; m < 16; m++) + jpeg_save_markers(srcinfo, JPEG_APP0 + m, 0xFFFF); + } +#endif /* SAVE_MARKERS_SUPPORTED */ +} + +/* Copy markers saved in the given source object to the destination object. + * This should be called just after jpeg_start_compress() or + * jpeg_write_coefficients(). + * Note that those routines will have written the SOI, and also the + * JFIF APP0 or Adobe APP14 markers if selected. + */ + +GLOBAL(void) +jcopy_markers_execute (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + JCOPY_OPTION option) +{ + jpeg_saved_marker_ptr marker; + + /* In the current implementation, we don't actually need to examine the + * option flag here; we just copy everything that got saved. + * But to avoid confusion, we do not output JFIF and Adobe APP14 markers + * if the encoder library already wrote one. + */ + for (marker = srcinfo->marker_list; marker != NULL; marker = marker->next) { + if (dstinfo->write_JFIF_header && + marker->marker == JPEG_APP0 && + marker->data_length >= 5 && + GETJOCTET(marker->data[0]) == 0x4A && + GETJOCTET(marker->data[1]) == 0x46 && + GETJOCTET(marker->data[2]) == 0x49 && + GETJOCTET(marker->data[3]) == 0x46 && + GETJOCTET(marker->data[4]) == 0) + continue; /* reject duplicate JFIF */ + if (dstinfo->write_Adobe_marker && + marker->marker == JPEG_APP0+14 && + marker->data_length >= 5 && + GETJOCTET(marker->data[0]) == 0x41 && + GETJOCTET(marker->data[1]) == 0x64 && + GETJOCTET(marker->data[2]) == 0x6F && + GETJOCTET(marker->data[3]) == 0x62 && + GETJOCTET(marker->data[4]) == 0x65) + continue; /* reject duplicate Adobe */ +#ifdef NEED_FAR_POINTERS + /* We could use jpeg_write_marker if the data weren't FAR... */ + { + unsigned int i; + jpeg_write_m_header(dstinfo, marker->marker, marker->data_length); + for (i = 0; i < marker->data_length; i++) + jpeg_write_m_byte(dstinfo, marker->data[i]); + } +#else + jpeg_write_marker(dstinfo, marker->marker, + marker->data, marker->data_length); +#endif + } +} diff --git a/lc-continuity/mk4/modimage/jpeg-6b/transupp.h b/lc-continuity/mk4/modimage/jpeg-6b/transupp.h new file mode 100644 index 0000000000000000000000000000000000000000..5c2d32aff50122873e78f5f3030d7135e257073a --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/transupp.h @@ -0,0 +1,135 @@ +/* + * transupp.h + * + * Copyright (C) 1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains declarations for image transformation routines and + * other utility code used by the jpegtran sample application. These are + * NOT part of the core JPEG library. But we keep these routines separate + * from jpegtran.c to ease the task of maintaining jpegtran-like programs + * that have other user interfaces. + * + * NOTE: all the routines declared here have very specific requirements + * about when they are to be executed during the reading and writing of the + * source and destination files. See the comments in transupp.c, or see + * jpegtran.c for an example of correct usage. + */ + +/* If you happen not to want the image transform support, disable it here */ +#ifndef TRANSFORMS_SUPPORTED +#define TRANSFORMS_SUPPORTED 1 /* 0 disables transform code */ +#endif + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jtransform_request_workspace jTrRequest +#define jtransform_adjust_parameters jTrAdjust +#define jtransform_execute_transformation jTrExec +#define jcopy_markers_setup jCMrkSetup +#define jcopy_markers_execute jCMrkExec +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* + * Codes for supported types of image transformations. + */ + +typedef enum { + JXFORM_NONE, /* no transformation */ + JXFORM_FLIP_H, /* horizontal flip */ + JXFORM_FLIP_V, /* vertical flip */ + JXFORM_TRANSPOSE, /* transpose across UL-to-LR axis */ + JXFORM_TRANSVERSE, /* transpose across UR-to-LL axis */ + JXFORM_ROT_90, /* 90-degree clockwise rotation */ + JXFORM_ROT_180, /* 180-degree rotation */ + JXFORM_ROT_270 /* 270-degree clockwise (or 90 ccw) */ +} JXFORM_CODE; + +/* + * Although rotating and flipping data expressed as DCT coefficients is not + * hard, there is an asymmetry in the JPEG format specification for images + * whose dimensions aren't multiples of the iMCU size. The right and bottom + * image edges are padded out to the next iMCU boundary with junk data; but + * no padding is possible at the top and left edges. If we were to flip + * the whole image including the pad data, then pad garbage would become + * visible at the top and/or left, and real pixels would disappear into the + * pad margins --- perhaps permanently, since encoders & decoders may not + * bother to preserve DCT blocks that appear to be completely outside the + * nominal image area. So, we have to exclude any partial iMCUs from the + * basic transformation. + * + * Transpose is the only transformation that can handle partial iMCUs at the + * right and bottom edges completely cleanly. flip_h can flip partial iMCUs + * at the bottom, but leaves any partial iMCUs at the right edge untouched. + * Similarly flip_v leaves any partial iMCUs at the bottom edge untouched. + * The other transforms are defined as combinations of these basic transforms + * and process edge blocks in a way that preserves the equivalence. + * + * The "trim" option causes untransformable partial iMCUs to be dropped; + * this is not strictly lossless, but it usually gives the best-looking + * result for odd-size images. Note that when this option is active, + * the expected mathematical equivalences between the transforms may not hold. + * (For example, -rot 270 -trim trims only the bottom edge, but -rot 90 -trim + * followed by -rot 180 -trim trims both edges.) + * + * We also offer a "force to grayscale" option, which simply discards the + * chrominance channels of a YCbCr image. This is lossless in the sense that + * the luminance channel is preserved exactly. It's not the same kind of + * thing as the rotate/flip transformations, but it's convenient to handle it + * as part of this package, mainly because the transformation routines have to + * be aware of the option to know how many components to work on. + */ + +typedef struct { + /* Options: set by caller */ + JXFORM_CODE transform; /* image transform operator */ + boolean trim; /* if TRUE, trim partial MCUs as needed */ + boolean force_grayscale; /* if TRUE, convert color image to grayscale */ + + /* Internal workspace: caller should not touch these */ + int num_components; /* # of components in workspace */ + jvirt_barray_ptr * workspace_coef_arrays; /* workspace for transformations */ +} jpeg_transform_info; + + +#if TRANSFORMS_SUPPORTED + +/* Request any required workspace */ +EXTERN(void) jtransform_request_workspace + JPP((j_decompress_ptr srcinfo, jpeg_transform_info *info)); +/* Adjust output image parameters */ +EXTERN(jvirt_barray_ptr *) jtransform_adjust_parameters + JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + jvirt_barray_ptr *src_coef_arrays, + jpeg_transform_info *info)); +/* Execute the actual transformation, if any */ +EXTERN(void) jtransform_execute_transformation + JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + jvirt_barray_ptr *src_coef_arrays, + jpeg_transform_info *info)); + +#endif /* TRANSFORMS_SUPPORTED */ + + +/* + * Support for copying optional markers from source to destination file. + */ + +typedef enum { + JCOPYOPT_NONE, /* copy no optional markers */ + JCOPYOPT_COMMENTS, /* copy only comment (COM) markers */ + JCOPYOPT_ALL /* copy all optional markers */ +} JCOPY_OPTION; + +#define JCOPYOPT_DEFAULT JCOPYOPT_COMMENTS /* recommended default */ + +/* Setup decompression object to save desired markers in memory */ +EXTERN(void) jcopy_markers_setup + JPP((j_decompress_ptr srcinfo, JCOPY_OPTION option)); +/* Copy markers saved in the given source object to the destination object */ +EXTERN(void) jcopy_markers_execute + JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + JCOPY_OPTION option)); diff --git a/lc-continuity/mk4/modimage/jpeg-6b/usage.doc b/lc-continuity/mk4/modimage/jpeg-6b/usage.doc new file mode 100644 index 0000000000000000000000000000000000000000..8c4970af0518f212e386805c125009faba7089e3 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/usage.doc @@ -0,0 +1,562 @@ +USAGE instructions for the Independent JPEG Group's JPEG software +================================================================= + +This file describes usage of the JPEG conversion programs cjpeg and djpeg, +as well as the utility programs jpegtran, rdjpgcom and wrjpgcom. (See +the other documentation files if you wish to use the JPEG library within +your own programs.) + +If you are on a Unix machine you may prefer to read the Unix-style manual +pages in files cjpeg.1, djpeg.1, jpegtran.1, rdjpgcom.1, wrjpgcom.1. + + +INTRODUCTION + +These programs implement JPEG image compression and decompression. JPEG +(pronounced "jay-peg") is a standardized compression method for full-color +and gray-scale images. JPEG is designed to handle "real-world" scenes, +for example scanned photographs. Cartoons, line drawings, and other +non-realistic images are not JPEG's strong suit; on that sort of material +you may get poor image quality and/or little compression. + +JPEG is lossy, meaning that the output image is not necessarily identical to +the input image. Hence you should not use JPEG if you have to have identical +output bits. However, on typical real-world images, very good compression +levels can be obtained with no visible change, and amazingly high compression +is possible if you can tolerate a low-quality image. You can trade off image +quality against file size by adjusting the compressor's "quality" setting. + + +GENERAL USAGE + +We provide two programs, cjpeg to compress an image file into JPEG format, +and djpeg to decompress a JPEG file back into a conventional image format. + +On Unix-like systems, you say: + cjpeg [switches] [imagefile] >jpegfile +or + djpeg [switches] [jpegfile] >imagefile +The programs read the specified input file, or standard input if none is +named. They always write to standard output (with trace/error messages to +standard error). These conventions are handy for piping images between +programs. + +On most non-Unix systems, you say: + cjpeg [switches] imagefile jpegfile +or + djpeg [switches] jpegfile imagefile +i.e., both the input and output files are named on the command line. This +style is a little more foolproof, and it loses no functionality if you don't +have pipes. (You can get this style on Unix too, if you prefer, by defining +TWO_FILE_COMMANDLINE when you compile the programs; see install.doc.) + +You can also say: + cjpeg [switches] -outfile jpegfile imagefile +or + djpeg [switches] -outfile imagefile jpegfile +This syntax works on all systems, so it is useful for scripts. + +The currently supported image file formats are: PPM (PBMPLUS color format), +PGM (PBMPLUS gray-scale format), BMP, Targa, and RLE (Utah Raster Toolkit +format). (RLE is supported only if the URT library is available.) +cjpeg recognizes the input image format automatically, with the exception +of some Targa-format files. You have to tell djpeg which format to generate. + +JPEG files are in the defacto standard JFIF file format. There are other, +less widely used JPEG-based file formats, but we don't support them. + +All switch names may be abbreviated; for example, -grayscale may be written +-gray or -gr. Most of the "basic" switches can be abbreviated to as little as +one letter. Upper and lower case are equivalent (-BMP is the same as -bmp). +British spellings are also accepted (e.g., -greyscale), though for brevity +these are not mentioned below. + + +CJPEG DETAILS + +The basic command line switches for cjpeg are: + + -quality N Scale quantization tables to adjust image quality. + Quality is 0 (worst) to 100 (best); default is 75. + (See below for more info.) + + -grayscale Create monochrome JPEG file from color input. + Be sure to use this switch when compressing a grayscale + BMP file, because cjpeg isn't bright enough to notice + whether a BMP file uses only shades of gray. By + saying -grayscale, you'll get a smaller JPEG file that + takes less time to process. + + -optimize Perform optimization of entropy encoding parameters. + Without this, default encoding parameters are used. + -optimize usually makes the JPEG file a little smaller, + but cjpeg runs somewhat slower and needs much more + memory. Image quality and speed of decompression are + unaffected by -optimize. + + -progressive Create progressive JPEG file (see below). + + -targa Input file is Targa format. Targa files that contain + an "identification" field will not be automatically + recognized by cjpeg; for such files you must specify + -targa to make cjpeg treat the input as Targa format. + For most Targa files, you won't need this switch. + +The -quality switch lets you trade off compressed file size against quality of +the reconstructed image: the higher the quality setting, the larger the JPEG +file, and the closer the output image will be to the original input. Normally +you want to use the lowest quality setting (smallest file) that decompresses +into something visually indistinguishable from the original image. For this +purpose the quality setting should be between 50 and 95; the default of 75 is +often about right. If you see defects at -quality 75, then go up 5 or 10 +counts at a time until you are happy with the output image. (The optimal +setting will vary from one image to another.) + +-quality 100 will generate a quantization table of all 1's, minimizing loss +in the quantization step (but there is still information loss in subsampling, +as well as roundoff error). This setting is mainly of interest for +experimental purposes. Quality values above about 95 are NOT recommended for +normal use; the compressed file size goes up dramatically for hardly any gain +in output image quality. + +In the other direction, quality values below 50 will produce very small files +of low image quality. Settings around 5 to 10 might be useful in preparing an +index of a large image library, for example. Try -quality 2 (or so) for some +amusing Cubist effects. (Note: quality values below about 25 generate 2-byte +quantization tables, which are considered optional in the JPEG standard. +cjpeg emits a warning message when you give such a quality value, because some +other JPEG programs may be unable to decode the resulting file. Use -baseline +if you need to ensure compatibility at low quality values.) + +The -progressive switch creates a "progressive JPEG" file. In this type of +JPEG file, the data is stored in multiple scans of increasing quality. If the +file is being transmitted over a slow communications link, the decoder can use +the first scan to display a low-quality image very quickly, and can then +improve the display with each subsequent scan. The final image is exactly +equivalent to a standard JPEG file of the same quality setting, and the total +file size is about the same --- often a little smaller. CAUTION: progressive +JPEG is not yet widely implemented, so many decoders will be unable to view a +progressive JPEG file at all. + +Switches for advanced users: + + -dct int Use integer DCT method (default). + -dct fast Use fast integer DCT (less accurate). + -dct float Use floating-point DCT method. + The float method is very slightly more accurate than + the int method, but is much slower unless your machine + has very fast floating-point hardware. Also note that + results of the floating-point method may vary slightly + across machines, while the integer methods should give + the same results everywhere. The fast integer method + is much less accurate than the other two. + + -restart N Emit a JPEG restart marker every N MCU rows, or every + N MCU blocks if "B" is attached to the number. + -restart 0 (the default) means no restart markers. + + -smooth N Smooth the input image to eliminate dithering noise. + N, ranging from 1 to 100, indicates the strength of + smoothing. 0 (the default) means no smoothing. + + -maxmemory N Set limit for amount of memory to use in processing + large images. Value is in thousands of bytes, or + millions of bytes if "M" is attached to the number. + For example, -max 4m selects 4000000 bytes. If more + space is needed, temporary files will be used. + + -verbose Enable debug printout. More -v's give more printout. + or -debug Also, version information is printed at startup. + +The -restart option inserts extra markers that allow a JPEG decoder to +resynchronize after a transmission error. Without restart markers, any damage +to a compressed file will usually ruin the image from the point of the error +to the end of the image; with restart markers, the damage is usually confined +to the portion of the image up to the next restart marker. Of course, the +restart markers occupy extra space. We recommend -restart 1 for images that +will be transmitted across unreliable networks such as Usenet. + +The -smooth option filters the input to eliminate fine-scale noise. This is +often useful when converting dithered images to JPEG: a moderate smoothing +factor of 10 to 50 gets rid of dithering patterns in the input file, resulting +in a smaller JPEG file and a better-looking image. Too large a smoothing +factor will visibly blur the image, however. + +Switches for wizards: + + -baseline Force baseline-compatible quantization tables to be + generated. This clamps quantization values to 8 bits + even at low quality settings. (This switch is poorly + named, since it does not ensure that the output is + actually baseline JPEG. For example, you can use + -baseline and -progressive together.) + + -qtables file Use the quantization tables given in the specified + text file. + + -qslots N[,...] Select which quantization table to use for each color + component. + + -sample HxV[,...] Set JPEG sampling factors for each color component. + + -scans file Use the scan script given in the specified text file. + +The "wizard" switches are intended for experimentation with JPEG. If you +don't know what you are doing, DON'T USE THEM. These switches are documented +further in the file wizard.doc. + + +DJPEG DETAILS + +The basic command line switches for djpeg are: + + -colors N Reduce image to at most N colors. This reduces the + or -quantize N number of colors used in the output image, so that it + can be displayed on a colormapped display or stored in + a colormapped file format. For example, if you have + an 8-bit display, you'd need to reduce to 256 or fewer + colors. (-colors is the recommended name, -quantize + is provided only for backwards compatibility.) + + -fast Select recommended processing options for fast, low + quality output. (The default options are chosen for + highest quality output.) Currently, this is equivalent + to "-dct fast -nosmooth -onepass -dither ordered". + + -grayscale Force gray-scale output even if JPEG file is color. + Useful for viewing on monochrome displays; also, + djpeg runs noticeably faster in this mode. + + -scale M/N Scale the output image by a factor M/N. Currently + the scale factor must be 1/1, 1/2, 1/4, or 1/8. + Scaling is handy if the image is larger than your + screen; also, djpeg runs much faster when scaling + down the output. + + -bmp Select BMP output format (Windows flavor). 8-bit + colormapped format is emitted if -colors or -grayscale + is specified, or if the JPEG file is gray-scale; + otherwise, 24-bit full-color format is emitted. + + -gif Select GIF output format. Since GIF does not support + more than 256 colors, -colors 256 is assumed (unless + you specify a smaller number of colors). If you + specify -fast, the default number of colors is 216. + + -os2 Select BMP output format (OS/2 1.x flavor). 8-bit + colormapped format is emitted if -colors or -grayscale + is specified, or if the JPEG file is gray-scale; + otherwise, 24-bit full-color format is emitted. + + -pnm Select PBMPLUS (PPM/PGM) output format (this is the + default format). PGM is emitted if the JPEG file is + gray-scale or if -grayscale is specified; otherwise + PPM is emitted. + + -rle Select RLE output format. (Requires URT library.) + + -targa Select Targa output format. Gray-scale format is + emitted if the JPEG file is gray-scale or if + -grayscale is specified; otherwise, colormapped format + is emitted if -colors is specified; otherwise, 24-bit + full-color format is emitted. + +Switches for advanced users: + + -dct int Use integer DCT method (default). + -dct fast Use fast integer DCT (less accurate). + -dct float Use floating-point DCT method. + The float method is very slightly more accurate than + the int method, but is much slower unless your machine + has very fast floating-point hardware. Also note that + results of the floating-point method may vary slightly + across machines, while the integer methods should give + the same results everywhere. The fast integer method + is much less accurate than the other two. + + -dither fs Use Floyd-Steinberg dithering in color quantization. + -dither ordered Use ordered dithering in color quantization. + -dither none Do not use dithering in color quantization. + By default, Floyd-Steinberg dithering is applied when + quantizing colors; this is slow but usually produces + the best results. Ordered dither is a compromise + between speed and quality; no dithering is fast but + usually looks awful. Note that these switches have + no effect unless color quantization is being done. + Ordered dither is only available in -onepass mode. + + -map FILE Quantize to the colors used in the specified image + file. This is useful for producing multiple files + with identical color maps, or for forcing a predefined + set of colors to be used. The FILE must be a GIF + or PPM file. This option overrides -colors and + -onepass. + + -nosmooth Use a faster, lower-quality upsampling routine. + + -onepass Use one-pass instead of two-pass color quantization. + The one-pass method is faster and needs less memory, + but it produces a lower-quality image. -onepass is + ignored unless you also say -colors N. Also, + the one-pass method is always used for gray-scale + output (the two-pass method is no improvement then). + + -maxmemory N Set limit for amount of memory to use in processing + large images. Value is in thousands of bytes, or + millions of bytes if "M" is attached to the number. + For example, -max 4m selects 4000000 bytes. If more + space is needed, temporary files will be used. + + -verbose Enable debug printout. More -v's give more printout. + or -debug Also, version information is printed at startup. + + +HINTS FOR CJPEG + +Color GIF files are not the ideal input for JPEG; JPEG is really intended for +compressing full-color (24-bit) images. In particular, don't try to convert +cartoons, line drawings, and other images that have only a few distinct +colors. GIF works great on these, JPEG does not. If you want to convert a +GIF to JPEG, you should experiment with cjpeg's -quality and -smooth options +to get a satisfactory conversion. -smooth 10 or so is often helpful. + +Avoid running an image through a series of JPEG compression/decompression +cycles. Image quality loss will accumulate; after ten or so cycles the image +may be noticeably worse than it was after one cycle. It's best to use a +lossless format while manipulating an image, then convert to JPEG format when +you are ready to file the image away. + +The -optimize option to cjpeg is worth using when you are making a "final" +version for posting or archiving. It's also a win when you are using low +quality settings to make very small JPEG files; the percentage improvement +is often a lot more than it is on larger files. (At present, -optimize +mode is always selected when generating progressive JPEG files.) + +GIF input files are no longer supported, to avoid the Unisys LZW patent. +Use a Unisys-licensed program if you need to read a GIF file. (Conversion +of GIF files to JPEG is usually a bad idea anyway.) + + +HINTS FOR DJPEG + +To get a quick preview of an image, use the -grayscale and/or -scale switches. +"-grayscale -scale 1/8" is the fastest case. + +Several options are available that trade off image quality to gain speed. +"-fast" turns on the recommended settings. + +"-dct fast" and/or "-nosmooth" gain speed at a small sacrifice in quality. +When producing a color-quantized image, "-onepass -dither ordered" is fast but +much lower quality than the default behavior. "-dither none" may give +acceptable results in two-pass mode, but is seldom tolerable in one-pass mode. + +If you are fortunate enough to have very fast floating point hardware, +"-dct float" may be even faster than "-dct fast". But on most machines +"-dct float" is slower than "-dct int"; in this case it is not worth using, +because its theoretical accuracy advantage is too small to be significant +in practice. + +Two-pass color quantization requires a good deal of memory; on MS-DOS machines +it may run out of memory even with -maxmemory 0. In that case you can still +decompress, with some loss of image quality, by specifying -onepass for +one-pass quantization. + +To avoid the Unisys LZW patent, djpeg produces uncompressed GIF files. These +are larger than they should be, but are readable by standard GIF decoders. + + +HINTS FOR BOTH PROGRAMS + +If more space is needed than will fit in the available main memory (as +determined by -maxmemory), temporary files will be used. (MS-DOS versions +will try to get extended or expanded memory first.) The temporary files are +often rather large: in typical cases they occupy three bytes per pixel, for +example 3*800*600 = 1.44Mb for an 800x600 image. If you don't have enough +free disk space, leave out -progressive and -optimize (for cjpeg) or specify +-onepass (for djpeg). + +On MS-DOS, the temporary files are created in the directory named by the TMP +or TEMP environment variable, or in the current directory if neither of those +exist. Amiga implementations put the temp files in the directory named by +JPEGTMP:, so be sure to assign JPEGTMP: to a disk partition with adequate free +space. + +The default memory usage limit (-maxmemory) is set when the software is +compiled. If you get an "insufficient memory" error, try specifying a smaller +-maxmemory value, even -maxmemory 0 to use the absolute minimum space. You +may want to recompile with a smaller default value if this happens often. + +On machines that have "environment" variables, you can define the environment +variable JPEGMEM to set the default memory limit. The value is specified as +described for the -maxmemory switch. JPEGMEM overrides the default value +specified when the program was compiled, and itself is overridden by an +explicit -maxmemory switch. + +On MS-DOS machines, -maxmemory is the amount of main (conventional) memory to +use. (Extended or expanded memory is also used if available.) Most +DOS-specific versions of this software do their own memory space estimation +and do not need you to specify -maxmemory. + + +JPEGTRAN + +jpegtran performs various useful transformations of JPEG files. +It can translate the coded representation from one variant of JPEG to another, +for example from baseline JPEG to progressive JPEG or vice versa. It can also +perform some rearrangements of the image data, for example turning an image +from landscape to portrait format by rotation. + +jpegtran works by rearranging the compressed data (DCT coefficients), without +ever fully decoding the image. Therefore, its transformations are lossless: +there is no image degradation at all, which would not be true if you used +djpeg followed by cjpeg to accomplish the same conversion. But by the same +token, jpegtran cannot perform lossy operations such as changing the image +quality. + +jpegtran uses a command line syntax similar to cjpeg or djpeg. +On Unix-like systems, you say: + jpegtran [switches] [inputfile] >outputfile +On most non-Unix systems, you say: + jpegtran [switches] inputfile outputfile +where both the input and output files are JPEG files. + +To specify the coded JPEG representation used in the output file, +jpegtran accepts a subset of the switches recognized by cjpeg: + -optimize Perform optimization of entropy encoding parameters. + -progressive Create progressive JPEG file. + -restart N Emit a JPEG restart marker every N MCU rows, or every + N MCU blocks if "B" is attached to the number. + -scans file Use the scan script given in the specified text file. +See the previous discussion of cjpeg for more details about these switches. +If you specify none of these switches, you get a plain baseline-JPEG output +file. The quality setting and so forth are determined by the input file. + +The image can be losslessly transformed by giving one of these switches: + -flip horizontal Mirror image horizontally (left-right). + -flip vertical Mirror image vertically (top-bottom). + -rotate 90 Rotate image 90 degrees clockwise. + -rotate 180 Rotate image 180 degrees. + -rotate 270 Rotate image 270 degrees clockwise (or 90 ccw). + -transpose Transpose image (across UL-to-LR axis). + -transverse Transverse transpose (across UR-to-LL axis). + +The transpose transformation has no restrictions regarding image dimensions. +The other transformations operate rather oddly if the image dimensions are not +a multiple of the iMCU size (usually 8 or 16 pixels), because they can only +transform complete blocks of DCT coefficient data in the desired way. + +jpegtran's default behavior when transforming an odd-size image is designed +to preserve exact reversibility and mathematical consistency of the +transformation set. As stated, transpose is able to flip the entire image +area. Horizontal mirroring leaves any partial iMCU column at the right edge +untouched, but is able to flip all rows of the image. Similarly, vertical +mirroring leaves any partial iMCU row at the bottom edge untouched, but is +able to flip all columns. The other transforms can be built up as sequences +of transpose and flip operations; for consistency, their actions on edge +pixels are defined to be the same as the end result of the corresponding +transpose-and-flip sequence. + +For practical use, you may prefer to discard any untransformable edge pixels +rather than having a strange-looking strip along the right and/or bottom edges +of a transformed image. To do this, add the -trim switch: + -trim Drop non-transformable edge blocks. +Obviously, a transformation with -trim is not reversible, so strictly speaking +jpegtran with this switch is not lossless. Also, the expected mathematical +equivalences between the transformations no longer hold. For example, +"-rot 270 -trim" trims only the bottom edge, but "-rot 90 -trim" followed by +"-rot 180 -trim" trims both edges. + +Another not-strictly-lossless transformation switch is: + -grayscale Force grayscale output. +This option discards the chrominance channels if the input image is YCbCr +(ie, a standard color JPEG), resulting in a grayscale JPEG file. The +luminance channel is preserved exactly, so this is a better method of reducing +to grayscale than decompression, conversion, and recompression. This switch +is particularly handy for fixing a monochrome picture that was mistakenly +encoded as a color JPEG. (In such a case, the space savings from getting rid +of the near-empty chroma channels won't be large; but the decoding time for +a grayscale JPEG is substantially less than that for a color JPEG.) + +jpegtran also recognizes these switches that control what to do with "extra" +markers, such as comment blocks: + -copy none Copy no extra markers from source file. This setting + suppresses all comments and other excess baggage + present in the source file. + -copy comments Copy only comment markers. This setting copies + comments from the source file, but discards + any other inessential data. + -copy all Copy all extra markers. This setting preserves + miscellaneous markers found in the source file, such + as JFIF thumbnails and Photoshop settings. In some + files these extra markers can be sizable. +The default behavior is -copy comments. (Note: in IJG releases v6 and v6a, +jpegtran always did the equivalent of -copy none.) + +Additional switches recognized by jpegtran are: + -outfile filename + -maxmemory N + -verbose + -debug +These work the same as in cjpeg or djpeg. + + +THE COMMENT UTILITIES + +The JPEG standard allows "comment" (COM) blocks to occur within a JPEG file. +Although the standard doesn't actually define what COM blocks are for, they +are widely used to hold user-supplied text strings. This lets you add +annotations, titles, index terms, etc to your JPEG files, and later retrieve +them as text. COM blocks do not interfere with the image stored in the JPEG +file. The maximum size of a COM block is 64K, but you can have as many of +them as you like in one JPEG file. + +We provide two utility programs to display COM block contents and add COM +blocks to a JPEG file. + +rdjpgcom searches a JPEG file and prints the contents of any COM blocks on +standard output. The command line syntax is + rdjpgcom [-verbose] [inputfilename] +The switch "-verbose" (or just "-v") causes rdjpgcom to also display the JPEG +image dimensions. If you omit the input file name from the command line, +the JPEG file is read from standard input. (This may not work on some +operating systems, if binary data can't be read from stdin.) + +wrjpgcom adds a COM block, containing text you provide, to a JPEG file. +Ordinarily, the COM block is added after any existing COM blocks, but you +can delete the old COM blocks if you wish. wrjpgcom produces a new JPEG +file; it does not modify the input file. DO NOT try to overwrite the input +file by directing wrjpgcom's output back into it; on most systems this will +just destroy your file. + +The command line syntax for wrjpgcom is similar to cjpeg's. On Unix-like +systems, it is + wrjpgcom [switches] [inputfilename] +The output file is written to standard output. The input file comes from +the named file, or from standard input if no input file is named. + +On most non-Unix systems, the syntax is + wrjpgcom [switches] inputfilename outputfilename +where both input and output file names must be given explicitly. + +wrjpgcom understands three switches: + -replace Delete any existing COM blocks from the file. + -comment "Comment text" Supply new COM text on command line. + -cfile name Read text for new COM block from named file. +(Switch names can be abbreviated.) If you have only one line of comment text +to add, you can provide it on the command line with -comment. The comment +text must be surrounded with quotes so that it is treated as a single +argument. Longer comments can be read from a text file. + +If you give neither -comment nor -cfile, then wrjpgcom will read the comment +text from standard input. (In this case an input image file name MUST be +supplied, so that the source JPEG file comes from somewhere else.) You can +enter multiple lines, up to 64KB worth. Type an end-of-file indicator +(usually control-D or control-Z) to terminate the comment text entry. + +wrjpgcom will not add a COM block if the provided comment string is empty. +Therefore -replace -comment "" can be used to delete all COM blocks from a +file. + +These utility programs do not depend on the IJG JPEG library. In +particular, the source code for rdjpgcom is intended as an illustration of +the minimum amount of code required to parse a JPEG file header correctly. diff --git a/lc-continuity/mk4/modimage/jpeg-6b/wizard.doc b/lc-continuity/mk4/modimage/jpeg-6b/wizard.doc new file mode 100644 index 0000000000000000000000000000000000000000..54170b227df0b22d3c011ec16b72826464200a5f --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/wizard.doc @@ -0,0 +1,211 @@ +Advanced usage instructions for the Independent JPEG Group's JPEG software +========================================================================== + +This file describes cjpeg's "switches for wizards". + +The "wizard" switches are intended for experimentation with JPEG by persons +who are reasonably knowledgeable about the JPEG standard. If you don't know +what you are doing, DON'T USE THESE SWITCHES. You'll likely produce files +with worse image quality and/or poorer compression than you'd get from the +default settings. Furthermore, these switches must be used with caution +when making files intended for general use, because not all JPEG decoders +will support unusual JPEG parameter settings. + + +Quantization Table Adjustment +----------------------------- + +Ordinarily, cjpeg starts with a default set of tables (the same ones given +as examples in the JPEG standard) and scales them up or down according to +the -quality setting. The details of the scaling algorithm can be found in +jcparam.c. At very low quality settings, some quantization table entries +can get scaled up to values exceeding 255. Although 2-byte quantization +values are supported by the IJG software, this feature is not in baseline +JPEG and is not supported by all implementations. If you need to ensure +wide compatibility of low-quality files, you can constrain the scaled +quantization values to no more than 255 by giving the -baseline switch. +Note that use of -baseline will result in poorer quality for the same file +size, since more bits than necessary are expended on higher AC coefficients. + +You can substitute a different set of quantization values by using the +-qtables switch: + + -qtables file Use the quantization tables given in the named file. + +The specified file should be a text file containing decimal quantization +values. The file should contain one to four tables, each of 64 elements. +The tables are implicitly numbered 0,1,etc. in order of appearance. Table +entries appear in normal array order (NOT in the zigzag order in which they +will be stored in the JPEG file). + +Quantization table files are free format, in that arbitrary whitespace can +appear between numbers. Also, comments can be included: a comment starts +with '#' and extends to the end of the line. Here is an example file that +duplicates the default quantization tables: + + # Quantization tables given in JPEG spec, section K.1 + + # This is table 0 (the luminance table): + 16 11 10 16 24 40 51 61 + 12 12 14 19 26 58 60 55 + 14 13 16 24 40 57 69 56 + 14 17 22 29 51 87 80 62 + 18 22 37 56 68 109 103 77 + 24 35 55 64 81 104 113 92 + 49 64 78 87 103 121 120 101 + 72 92 95 98 112 100 103 99 + + # This is table 1 (the chrominance table): + 17 18 24 47 99 99 99 99 + 18 21 26 66 99 99 99 99 + 24 26 56 99 99 99 99 99 + 47 66 99 99 99 99 99 99 + 99 99 99 99 99 99 99 99 + 99 99 99 99 99 99 99 99 + 99 99 99 99 99 99 99 99 + 99 99 99 99 99 99 99 99 + +If the -qtables switch is used without -quality, then the specified tables +are used exactly as-is. If both -qtables and -quality are used, then the +tables taken from the file are scaled in the same fashion that the default +tables would be scaled for that quality setting. If -baseline appears, then +the quantization values are constrained to the range 1-255. + +By default, cjpeg will use quantization table 0 for luminance components and +table 1 for chrominance components. To override this choice, use the -qslots +switch: + + -qslots N[,...] Select which quantization table to use for + each color component. + +The -qslots switch specifies a quantization table number for each color +component, in the order in which the components appear in the JPEG SOF marker. +For example, to create a separate table for each of Y,Cb,Cr, you could +provide a -qtables file that defines three quantization tables and say +"-qslots 0,1,2". If -qslots gives fewer table numbers than there are color +components, then the last table number is repeated as necessary. + + +Sampling Factor Adjustment +-------------------------- + +By default, cjpeg uses 2:1 horizontal and vertical downsampling when +compressing YCbCr data, and no downsampling for all other color spaces. +You can override this default with the -sample switch: + + -sample HxV[,...] Set JPEG sampling factors for each color + component. + +The -sample switch specifies the JPEG sampling factors for each color +component, in the order in which they appear in the JPEG SOF marker. +If you specify fewer HxV pairs than there are components, the remaining +components are set to 1x1 sampling. For example, the default YCbCr setting +is equivalent to "-sample 2x2,1x1,1x1", which can be abbreviated to +"-sample 2x2". + +There are still some JPEG decoders in existence that support only 2x1 +sampling (also called 4:2:2 sampling). Compatibility with such decoders can +be achieved by specifying "-sample 2x1". This is not recommended unless +really necessary, since it increases file size and encoding/decoding time +with very little quality gain. + + +Multiple Scan / Progression Control +----------------------------------- + +By default, cjpeg emits a single-scan sequential JPEG file. The +-progressive switch generates a progressive JPEG file using a default series +of progression parameters. You can create multiple-scan sequential JPEG +files or progressive JPEG files with custom progression parameters by using +the -scans switch: + + -scans file Use the scan sequence given in the named file. + +The specified file should be a text file containing a "scan script". +The script specifies the contents and ordering of the scans to be emitted. +Each entry in the script defines one scan. A scan definition specifies +the components to be included in the scan, and for progressive JPEG it also +specifies the progression parameters Ss,Se,Ah,Al for the scan. Scan +definitions are separated by semicolons (';'). A semicolon after the last +scan definition is optional. + +Each scan definition contains one to four component indexes, optionally +followed by a colon (':') and the four progressive-JPEG parameters. The +component indexes denote which color component(s) are to be transmitted in +the scan. Components are numbered in the order in which they appear in the +JPEG SOF marker, with the first component being numbered 0. (Note that these +indexes are not the "component ID" codes assigned to the components, just +positional indexes.) + +The progression parameters for each scan are: + Ss Zigzag index of first coefficient included in scan + Se Zigzag index of last coefficient included in scan + Ah Zero for first scan of a coefficient, else Al of prior scan + Al Successive approximation low bit position for scan +If the progression parameters are omitted, the values 0,63,0,0 are used, +producing a sequential JPEG file. cjpeg automatically determines whether +the script represents a progressive or sequential file, by observing whether +Ss and Se values other than 0 and 63 appear. (The -progressive switch is +not needed to specify this; in fact, it is ignored when -scans appears.) +The scan script must meet the JPEG restrictions on progression sequences. +(cjpeg checks that the spec's requirements are obeyed.) + +Scan script files are free format, in that arbitrary whitespace can appear +between numbers and around punctuation. Also, comments can be included: a +comment starts with '#' and extends to the end of the line. For additional +legibility, commas or dashes can be placed between values. (Actually, any +single punctuation character other than ':' or ';' can be inserted.) For +example, the following two scan definitions are equivalent: + 0 1 2: 0 63 0 0; + 0,1,2 : 0-63, 0,0 ; + +Here is an example of a scan script that generates a partially interleaved +sequential JPEG file: + + 0; # Y only in first scan + 1 2; # Cb and Cr in second scan + +Here is an example of a progressive scan script using only spectral selection +(no successive approximation): + + # Interleaved DC scan for Y,Cb,Cr: + 0,1,2: 0-0, 0, 0 ; + # AC scans: + 0: 1-2, 0, 0 ; # First two Y AC coefficients + 0: 3-5, 0, 0 ; # Three more + 1: 1-63, 0, 0 ; # All AC coefficients for Cb + 2: 1-63, 0, 0 ; # All AC coefficients for Cr + 0: 6-9, 0, 0 ; # More Y coefficients + 0: 10-63, 0, 0 ; # Remaining Y coefficients + +Here is an example of a successive-approximation script. This is equivalent +to the default script used by "cjpeg -progressive" for YCbCr images: + + # Initial DC scan for Y,Cb,Cr (lowest bit not sent) + 0,1,2: 0-0, 0, 1 ; + # First AC scan: send first 5 Y AC coefficients, minus 2 lowest bits: + 0: 1-5, 0, 2 ; + # Send all Cr,Cb AC coefficients, minus lowest bit: + # (chroma data is usually too small to be worth subdividing further; + # but note we send Cr first since eye is least sensitive to Cb) + 2: 1-63, 0, 1 ; + 1: 1-63, 0, 1 ; + # Send remaining Y AC coefficients, minus 2 lowest bits: + 0: 6-63, 0, 2 ; + # Send next-to-lowest bit of all Y AC coefficients: + 0: 1-63, 2, 1 ; + # At this point we've sent all but the lowest bit of all coefficients. + # Send lowest bit of DC coefficients + 0,1,2: 0-0, 1, 0 ; + # Send lowest bit of AC coefficients + 2: 1-63, 1, 0 ; + 1: 1-63, 1, 0 ; + # Y AC lowest bit scan is last; it's usually the largest scan + 0: 1-63, 1, 0 ; + +It may be worth pointing out that this script is tuned for quality settings +of around 50 to 75. For lower quality settings, you'd probably want to use +a script with fewer stages of successive approximation (otherwise the +initial scans will be really bad). For higher quality settings, you might +want to use more stages of successive approximation (so that the initial +scans are not too large). diff --git a/lc-continuity/mk4/modimage/jpeg-6b/wrbmp.c b/lc-continuity/mk4/modimage/jpeg-6b/wrbmp.c new file mode 100644 index 0000000000000000000000000000000000000000..3283b0f15c20ae86b64bc2d021b4f9760cb9de3e --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/wrbmp.c @@ -0,0 +1,442 @@ +/* + * wrbmp.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains routines to write output images in Microsoft "BMP" + * format (MS Windows 3.x and OS/2 1.x flavors). + * Either 8-bit colormapped or 24-bit full-color format can be written. + * No compression is supported. + * + * These routines may need modification for non-Unix environments or + * specialized applications. As they stand, they assume output to + * an ordinary stdio stream. + * + * This code contributed by James Arthur Boucher. + */ + +#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ + +#ifdef BMP_SUPPORTED + + +/* + * To support 12-bit JPEG data, we'd have to scale output down to 8 bits. + * This is not yet implemented. + */ + +#if BITS_IN_JSAMPLE != 8 + Sorry, this code only copes with 8-bit JSAMPLEs. /* deliberate syntax err */ +#endif + +/* + * Since BMP stores scanlines bottom-to-top, we have to invert the image + * from JPEG's top-to-bottom order. To do this, we save the outgoing data + * in a virtual array during put_pixel_row calls, then actually emit the + * BMP file during finish_output. The virtual array contains one JSAMPLE per + * pixel if the output is grayscale or colormapped, three if it is full color. + */ + +/* Private version of data destination object */ + +typedef struct { + struct djpeg_dest_struct pub; /* public fields */ + + boolean is_os2; /* saves the OS2 format request flag */ + + jvirt_sarray_ptr whole_image; /* needed to reverse row order */ + JDIMENSION data_width; /* JSAMPLEs per row */ + JDIMENSION row_width; /* physical width of one row in the BMP file */ + int pad_bytes; /* number of padding bytes needed per row */ + JDIMENSION cur_output_row; /* next row# to write to virtual array */ +} bmp_dest_struct; + +typedef bmp_dest_struct * bmp_dest_ptr; + + +/* Forward declarations */ +LOCAL(void) write_colormap + JPP((j_decompress_ptr cinfo, bmp_dest_ptr dest, + int map_colors, int map_entry_size)); + + +/* + * Write some pixel data. + * In this module rows_supplied will always be 1. + */ + +METHODDEF(void) +put_pixel_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo, + JDIMENSION rows_supplied) +/* This version is for writing 24-bit pixels */ +{ + bmp_dest_ptr dest = (bmp_dest_ptr) dinfo; + JSAMPARRAY image_ptr; + register JSAMPROW inptr, outptr; + register JDIMENSION col; + int pad; + + /* Access next row in virtual array */ + image_ptr = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, dest->whole_image, + dest->cur_output_row, (JDIMENSION) 1, TRUE); + dest->cur_output_row++; + + /* Transfer data. Note destination values must be in BGR order + * (even though Microsoft's own documents say the opposite). + */ + inptr = dest->pub.buffer[0]; + outptr = image_ptr[0]; + for (col = cinfo->output_width; col > 0; col--) { + outptr[2] = *inptr++; /* can omit GETJSAMPLE() safely */ + outptr[1] = *inptr++; + outptr[0] = *inptr++; + outptr += 3; + } + + /* Zero out the pad bytes. */ + pad = dest->pad_bytes; + while (--pad >= 0) + *outptr++ = 0; +} + +METHODDEF(void) +put_gray_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo, + JDIMENSION rows_supplied) +/* This version is for grayscale OR quantized color output */ +{ + bmp_dest_ptr dest = (bmp_dest_ptr) dinfo; + JSAMPARRAY image_ptr; + register JSAMPROW inptr, outptr; + register JDIMENSION col; + int pad; + + /* Access next row in virtual array */ + image_ptr = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, dest->whole_image, + dest->cur_output_row, (JDIMENSION) 1, TRUE); + dest->cur_output_row++; + + /* Transfer data. */ + inptr = dest->pub.buffer[0]; + outptr = image_ptr[0]; + for (col = cinfo->output_width; col > 0; col--) { + *outptr++ = *inptr++; /* can omit GETJSAMPLE() safely */ + } + + /* Zero out the pad bytes. */ + pad = dest->pad_bytes; + while (--pad >= 0) + *outptr++ = 0; +} + + +/* + * Startup: normally writes the file header. + * In this module we may as well postpone everything until finish_output. + */ + +METHODDEF(void) +start_output_bmp (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo) +{ + /* no work here */ +} + + +/* + * Finish up at the end of the file. + * + * Here is where we really output the BMP file. + * + * First, routines to write the Windows and OS/2 variants of the file header. + */ + +LOCAL(void) +write_bmp_header (j_decompress_ptr cinfo, bmp_dest_ptr dest) +/* Write a Windows-style BMP file header, including colormap if needed */ +{ + char bmpfileheader[14]; + char bmpinfoheader[40]; +#define PUT_2B(array,offset,value) \ + (array[offset] = (char) ((value) & 0xFF), \ + array[offset+1] = (char) (((value) >> 8) & 0xFF)) +#define PUT_4B(array,offset,value) \ + (array[offset] = (char) ((value) & 0xFF), \ + array[offset+1] = (char) (((value) >> 8) & 0xFF), \ + array[offset+2] = (char) (((value) >> 16) & 0xFF), \ + array[offset+3] = (char) (((value) >> 24) & 0xFF)) + INT32 headersize, bfSize; + int bits_per_pixel, cmap_entries; + + /* Compute colormap size and total file size */ + if (cinfo->out_color_space == JCS_RGB) { + if (cinfo->quantize_colors) { + /* Colormapped RGB */ + bits_per_pixel = 8; + cmap_entries = 256; + } else { + /* Unquantized, full color RGB */ + bits_per_pixel = 24; + cmap_entries = 0; + } + } else { + /* Grayscale output. We need to fake a 256-entry colormap. */ + bits_per_pixel = 8; + cmap_entries = 256; + } + /* File size */ + headersize = 14 + 40 + cmap_entries * 4; /* Header and colormap */ + bfSize = headersize + (INT32) dest->row_width * (INT32) cinfo->output_height; + + /* Set unused fields of header to 0 */ + MEMZERO(bmpfileheader, SIZEOF(bmpfileheader)); + MEMZERO(bmpinfoheader, SIZEOF(bmpinfoheader)); + + /* Fill the file header */ + bmpfileheader[0] = 0x42; /* first 2 bytes are ASCII 'B', 'M' */ + bmpfileheader[1] = 0x4D; + PUT_4B(bmpfileheader, 2, bfSize); /* bfSize */ + /* we leave bfReserved1 & bfReserved2 = 0 */ + PUT_4B(bmpfileheader, 10, headersize); /* bfOffBits */ + + /* Fill the info header (Microsoft calls this a BITMAPINFOHEADER) */ + PUT_2B(bmpinfoheader, 0, 40); /* biSize */ + PUT_4B(bmpinfoheader, 4, cinfo->output_width); /* biWidth */ + PUT_4B(bmpinfoheader, 8, cinfo->output_height); /* biHeight */ + PUT_2B(bmpinfoheader, 12, 1); /* biPlanes - must be 1 */ + PUT_2B(bmpinfoheader, 14, bits_per_pixel); /* biBitCount */ + /* we leave biCompression = 0, for none */ + /* we leave biSizeImage = 0; this is correct for uncompressed data */ + if (cinfo->density_unit == 2) { /* if have density in dots/cm, then */ + PUT_4B(bmpinfoheader, 24, (INT32) (cinfo->X_density*100)); /* XPels/M */ + PUT_4B(bmpinfoheader, 28, (INT32) (cinfo->Y_density*100)); /* XPels/M */ + } + PUT_2B(bmpinfoheader, 32, cmap_entries); /* biClrUsed */ + /* we leave biClrImportant = 0 */ + + if (JFWRITE(dest->pub.output_file, bmpfileheader, 14) != (size_t) 14) + ERREXIT(cinfo, JERR_FILE_WRITE); + if (JFWRITE(dest->pub.output_file, bmpinfoheader, 40) != (size_t) 40) + ERREXIT(cinfo, JERR_FILE_WRITE); + + if (cmap_entries > 0) + write_colormap(cinfo, dest, cmap_entries, 4); +} + + +LOCAL(void) +write_os2_header (j_decompress_ptr cinfo, bmp_dest_ptr dest) +/* Write an OS2-style BMP file header, including colormap if needed */ +{ + char bmpfileheader[14]; + char bmpcoreheader[12]; + INT32 headersize, bfSize; + int bits_per_pixel, cmap_entries; + + /* Compute colormap size and total file size */ + if (cinfo->out_color_space == JCS_RGB) { + if (cinfo->quantize_colors) { + /* Colormapped RGB */ + bits_per_pixel = 8; + cmap_entries = 256; + } else { + /* Unquantized, full color RGB */ + bits_per_pixel = 24; + cmap_entries = 0; + } + } else { + /* Grayscale output. We need to fake a 256-entry colormap. */ + bits_per_pixel = 8; + cmap_entries = 256; + } + /* File size */ + headersize = 14 + 12 + cmap_entries * 3; /* Header and colormap */ + bfSize = headersize + (INT32) dest->row_width * (INT32) cinfo->output_height; + + /* Set unused fields of header to 0 */ + MEMZERO(bmpfileheader, SIZEOF(bmpfileheader)); + MEMZERO(bmpcoreheader, SIZEOF(bmpcoreheader)); + + /* Fill the file header */ + bmpfileheader[0] = 0x42; /* first 2 bytes are ASCII 'B', 'M' */ + bmpfileheader[1] = 0x4D; + PUT_4B(bmpfileheader, 2, bfSize); /* bfSize */ + /* we leave bfReserved1 & bfReserved2 = 0 */ + PUT_4B(bmpfileheader, 10, headersize); /* bfOffBits */ + + /* Fill the info header (Microsoft calls this a BITMAPCOREHEADER) */ + PUT_2B(bmpcoreheader, 0, 12); /* bcSize */ + PUT_2B(bmpcoreheader, 4, cinfo->output_width); /* bcWidth */ + PUT_2B(bmpcoreheader, 6, cinfo->output_height); /* bcHeight */ + PUT_2B(bmpcoreheader, 8, 1); /* bcPlanes - must be 1 */ + PUT_2B(bmpcoreheader, 10, bits_per_pixel); /* bcBitCount */ + + if (JFWRITE(dest->pub.output_file, bmpfileheader, 14) != (size_t) 14) + ERREXIT(cinfo, JERR_FILE_WRITE); + if (JFWRITE(dest->pub.output_file, bmpcoreheader, 12) != (size_t) 12) + ERREXIT(cinfo, JERR_FILE_WRITE); + + if (cmap_entries > 0) + write_colormap(cinfo, dest, cmap_entries, 3); +} + + +/* + * Write the colormap. + * Windows uses BGR0 map entries; OS/2 uses BGR entries. + */ + +LOCAL(void) +write_colormap (j_decompress_ptr cinfo, bmp_dest_ptr dest, + int map_colors, int map_entry_size) +{ + JSAMPARRAY colormap = cinfo->colormap; + int num_colors = cinfo->actual_number_of_colors; + FILE * outfile = dest->pub.output_file; + int i; + + if (colormap != NULL) { + if (cinfo->out_color_components == 3) { + /* Normal case with RGB colormap */ + for (i = 0; i < num_colors; i++) { + putc(GETJSAMPLE(colormap[2][i]), outfile); + putc(GETJSAMPLE(colormap[1][i]), outfile); + putc(GETJSAMPLE(colormap[0][i]), outfile); + if (map_entry_size == 4) + putc(0, outfile); + } + } else { + /* Grayscale colormap (only happens with grayscale quantization) */ + for (i = 0; i < num_colors; i++) { + putc(GETJSAMPLE(colormap[0][i]), outfile); + putc(GETJSAMPLE(colormap[0][i]), outfile); + putc(GETJSAMPLE(colormap[0][i]), outfile); + if (map_entry_size == 4) + putc(0, outfile); + } + } + } else { + /* If no colormap, must be grayscale data. Generate a linear "map". */ + for (i = 0; i < 256; i++) { + putc(i, outfile); + putc(i, outfile); + putc(i, outfile); + if (map_entry_size == 4) + putc(0, outfile); + } + } + /* Pad colormap with zeros to ensure specified number of colormap entries */ + if (i > map_colors) + ERREXIT1(cinfo, JERR_TOO_MANY_COLORS, i); + for (; i < map_colors; i++) { + putc(0, outfile); + putc(0, outfile); + putc(0, outfile); + if (map_entry_size == 4) + putc(0, outfile); + } +} + + +METHODDEF(void) +finish_output_bmp (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo) +{ + bmp_dest_ptr dest = (bmp_dest_ptr) dinfo; + register FILE * outfile = dest->pub.output_file; + JSAMPARRAY image_ptr; + register JSAMPROW data_ptr; + JDIMENSION row; + register JDIMENSION col; + cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress; + + /* Write the header and colormap */ + if (dest->is_os2) + write_os2_header(cinfo, dest); + else + write_bmp_header(cinfo, dest); + + /* Write the file body from our virtual array */ + for (row = cinfo->output_height; row > 0; row--) { + if (progress != NULL) { + progress->pub.pass_counter = (long) (cinfo->output_height - row); + progress->pub.pass_limit = (long) cinfo->output_height; + (*progress->pub.progress_monitor) ((j_common_ptr) cinfo); + } + image_ptr = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, dest->whole_image, row-1, (JDIMENSION) 1, FALSE); + data_ptr = image_ptr[0]; + for (col = dest->row_width; col > 0; col--) { + putc(GETJSAMPLE(*data_ptr), outfile); + data_ptr++; + } + } + if (progress != NULL) + progress->completed_extra_passes++; + + /* Make sure we wrote the output file OK */ + fflush(outfile); + if (ferror(outfile)) + ERREXIT(cinfo, JERR_FILE_WRITE); +} + + +/* + * The module selection routine for BMP format output. + */ + +GLOBAL(djpeg_dest_ptr) +jinit_write_bmp (j_decompress_ptr cinfo, boolean is_os2) +{ + bmp_dest_ptr dest; + JDIMENSION row_width; + + /* Create module interface object, fill in method pointers */ + dest = (bmp_dest_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(bmp_dest_struct)); + dest->pub.start_output = start_output_bmp; + dest->pub.finish_output = finish_output_bmp; + dest->is_os2 = is_os2; + + if (cinfo->out_color_space == JCS_GRAYSCALE) { + dest->pub.put_pixel_rows = put_gray_rows; + } else if (cinfo->out_color_space == JCS_RGB) { + if (cinfo->quantize_colors) + dest->pub.put_pixel_rows = put_gray_rows; + else + dest->pub.put_pixel_rows = put_pixel_rows; + } else { + ERREXIT(cinfo, JERR_BMP_COLORSPACE); + } + + /* Calculate output image dimensions so we can allocate space */ + jpeg_calc_output_dimensions(cinfo); + + /* Determine width of rows in the BMP file (padded to 4-byte boundary). */ + row_width = cinfo->output_width * cinfo->output_components; + dest->data_width = row_width; + while ((row_width & 3) != 0) row_width++; + dest->row_width = row_width; + dest->pad_bytes = (int) (row_width - dest->data_width); + + /* Allocate space for inversion array, prepare for write pass */ + dest->whole_image = (*cinfo->mem->request_virt_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, + row_width, cinfo->output_height, (JDIMENSION) 1); + dest->cur_output_row = 0; + if (cinfo->progress != NULL) { + cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress; + progress->total_extra_passes++; /* count file input as separate pass */ + } + + /* Create decompressor output buffer. */ + dest->pub.buffer = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, row_width, (JDIMENSION) 1); + dest->pub.buffer_height = 1; + + return (djpeg_dest_ptr) dest; +} + +#endif /* BMP_SUPPORTED */ diff --git a/lc-continuity/mk4/modimage/jpeg-6b/wrgif.c b/lc-continuity/mk4/modimage/jpeg-6b/wrgif.c new file mode 100644 index 0000000000000000000000000000000000000000..5fe8328391973ee0276cff75ae7fb07e6cc6cd44 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/wrgif.c @@ -0,0 +1,399 @@ +/* + * wrgif.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains routines to write output images in GIF format. + * + ************************************************************************** + * NOTE: to avoid entanglements with Unisys' patent on LZW compression, * + * this code has been modified to output "uncompressed GIF" files. * + * There is no trace of the LZW algorithm in this file. * + ************************************************************************** + * + * These routines may need modification for non-Unix environments or + * specialized applications. As they stand, they assume output to + * an ordinary stdio stream. + */ + +/* + * This code is loosely based on ppmtogif from the PBMPLUS distribution + * of Feb. 1991. That file contains the following copyright notice: + * Based on GIFENCODE by David Rowley . + * Lempel-Ziv compression based on "compress" by Spencer W. Thomas et al. + * Copyright (C) 1989 by Jef Poskanzer. + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation. This software is provided "as is" without express or + * implied warranty. + * + * We are also required to state that + * "The Graphics Interchange Format(c) is the Copyright property of + * CompuServe Incorporated. GIF(sm) is a Service Mark property of + * CompuServe Incorporated." + */ + +#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ + +#ifdef GIF_SUPPORTED + + +/* Private version of data destination object */ + +typedef struct { + struct djpeg_dest_struct pub; /* public fields */ + + j_decompress_ptr cinfo; /* back link saves passing separate parm */ + + /* State for packing variable-width codes into a bitstream */ + int n_bits; /* current number of bits/code */ + int maxcode; /* maximum code, given n_bits */ + INT32 cur_accum; /* holds bits not yet output */ + int cur_bits; /* # of bits in cur_accum */ + + /* State for GIF code assignment */ + int ClearCode; /* clear code (doesn't change) */ + int EOFCode; /* EOF code (ditto) */ + int code_counter; /* counts output symbols */ + + /* GIF data packet construction buffer */ + int bytesinpkt; /* # of bytes in current packet */ + char packetbuf[256]; /* workspace for accumulating packet */ + +} gif_dest_struct; + +typedef gif_dest_struct * gif_dest_ptr; + +/* Largest value that will fit in N bits */ +#define MAXCODE(n_bits) ((1 << (n_bits)) - 1) + + +/* + * Routines to package finished data bytes into GIF data blocks. + * A data block consists of a count byte (1..255) and that many data bytes. + */ + +LOCAL(void) +flush_packet (gif_dest_ptr dinfo) +/* flush any accumulated data */ +{ + if (dinfo->bytesinpkt > 0) { /* never write zero-length packet */ + dinfo->packetbuf[0] = (char) dinfo->bytesinpkt++; + if (JFWRITE(dinfo->pub.output_file, dinfo->packetbuf, dinfo->bytesinpkt) + != (size_t) dinfo->bytesinpkt) + ERREXIT(dinfo->cinfo, JERR_FILE_WRITE); + dinfo->bytesinpkt = 0; + } +} + + +/* Add a character to current packet; flush to disk if necessary */ +#define CHAR_OUT(dinfo,c) \ + { (dinfo)->packetbuf[++(dinfo)->bytesinpkt] = (char) (c); \ + if ((dinfo)->bytesinpkt >= 255) \ + flush_packet(dinfo); \ + } + + +/* Routine to convert variable-width codes into a byte stream */ + +LOCAL(void) +output (gif_dest_ptr dinfo, int code) +/* Emit a code of n_bits bits */ +/* Uses cur_accum and cur_bits to reblock into 8-bit bytes */ +{ + dinfo->cur_accum |= ((INT32) code) << dinfo->cur_bits; + dinfo->cur_bits += dinfo->n_bits; + + while (dinfo->cur_bits >= 8) { + CHAR_OUT(dinfo, dinfo->cur_accum & 0xFF); + dinfo->cur_accum >>= 8; + dinfo->cur_bits -= 8; + } +} + + +/* The pseudo-compression algorithm. + * + * In this module we simply output each pixel value as a separate symbol; + * thus, no compression occurs. In fact, there is expansion of one bit per + * pixel, because we use a symbol width one bit wider than the pixel width. + * + * GIF ordinarily uses variable-width symbols, and the decoder will expect + * to ratchet up the symbol width after a fixed number of symbols. + * To simplify the logic and keep the expansion penalty down, we emit a + * GIF Clear code to reset the decoder just before the width would ratchet up. + * Thus, all the symbols in the output file will have the same bit width. + * Note that emitting the Clear codes at the right times is a mere matter of + * counting output symbols and is in no way dependent on the LZW patent. + * + * With a small basic pixel width (low color count), Clear codes will be + * needed very frequently, causing the file to expand even more. So this + * simplistic approach wouldn't work too well on bilevel images, for example. + * But for output of JPEG conversions the pixel width will usually be 8 bits + * (129 to 256 colors), so the overhead added by Clear symbols is only about + * one symbol in every 256. + */ + +LOCAL(void) +compress_init (gif_dest_ptr dinfo, int i_bits) +/* Initialize pseudo-compressor */ +{ + /* init all the state variables */ + dinfo->n_bits = i_bits; + dinfo->maxcode = MAXCODE(dinfo->n_bits); + dinfo->ClearCode = (1 << (i_bits - 1)); + dinfo->EOFCode = dinfo->ClearCode + 1; + dinfo->code_counter = dinfo->ClearCode + 2; + /* init output buffering vars */ + dinfo->bytesinpkt = 0; + dinfo->cur_accum = 0; + dinfo->cur_bits = 0; + /* GIF specifies an initial Clear code */ + output(dinfo, dinfo->ClearCode); +} + + +LOCAL(void) +compress_pixel (gif_dest_ptr dinfo, int c) +/* Accept and "compress" one pixel value. + * The given value must be less than n_bits wide. + */ +{ + /* Output the given pixel value as a symbol. */ + output(dinfo, c); + /* Issue Clear codes often enough to keep the reader from ratcheting up + * its symbol size. + */ + if (dinfo->code_counter < dinfo->maxcode) { + dinfo->code_counter++; + } else { + output(dinfo, dinfo->ClearCode); + dinfo->code_counter = dinfo->ClearCode + 2; /* reset the counter */ + } +} + + +LOCAL(void) +compress_term (gif_dest_ptr dinfo) +/* Clean up at end */ +{ + /* Send an EOF code */ + output(dinfo, dinfo->EOFCode); + /* Flush the bit-packing buffer */ + if (dinfo->cur_bits > 0) { + CHAR_OUT(dinfo, dinfo->cur_accum & 0xFF); + } + /* Flush the packet buffer */ + flush_packet(dinfo); +} + + +/* GIF header construction */ + + +LOCAL(void) +put_word (gif_dest_ptr dinfo, unsigned int w) +/* Emit a 16-bit word, LSB first */ +{ + putc(w & 0xFF, dinfo->pub.output_file); + putc((w >> 8) & 0xFF, dinfo->pub.output_file); +} + + +LOCAL(void) +put_3bytes (gif_dest_ptr dinfo, int val) +/* Emit 3 copies of same byte value --- handy subr for colormap construction */ +{ + putc(val, dinfo->pub.output_file); + putc(val, dinfo->pub.output_file); + putc(val, dinfo->pub.output_file); +} + + +LOCAL(void) +emit_header (gif_dest_ptr dinfo, int num_colors, JSAMPARRAY colormap) +/* Output the GIF file header, including color map */ +/* If colormap==NULL, synthesize a gray-scale colormap */ +{ + int BitsPerPixel, ColorMapSize, InitCodeSize, FlagByte; + int cshift = dinfo->cinfo->data_precision - 8; + int i; + + if (num_colors > 256) + ERREXIT1(dinfo->cinfo, JERR_TOO_MANY_COLORS, num_colors); + /* Compute bits/pixel and related values */ + BitsPerPixel = 1; + while (num_colors > (1 << BitsPerPixel)) + BitsPerPixel++; + ColorMapSize = 1 << BitsPerPixel; + if (BitsPerPixel <= 1) + InitCodeSize = 2; + else + InitCodeSize = BitsPerPixel; + /* + * Write the GIF header. + * Note that we generate a plain GIF87 header for maximum compatibility. + */ + putc('G', dinfo->pub.output_file); + putc('I', dinfo->pub.output_file); + putc('F', dinfo->pub.output_file); + putc('8', dinfo->pub.output_file); + putc('7', dinfo->pub.output_file); + putc('a', dinfo->pub.output_file); + /* Write the Logical Screen Descriptor */ + put_word(dinfo, (unsigned int) dinfo->cinfo->output_width); + put_word(dinfo, (unsigned int) dinfo->cinfo->output_height); + FlagByte = 0x80; /* Yes, there is a global color table */ + FlagByte |= (BitsPerPixel-1) << 4; /* color resolution */ + FlagByte |= (BitsPerPixel-1); /* size of global color table */ + putc(FlagByte, dinfo->pub.output_file); + putc(0, dinfo->pub.output_file); /* Background color index */ + putc(0, dinfo->pub.output_file); /* Reserved (aspect ratio in GIF89) */ + /* Write the Global Color Map */ + /* If the color map is more than 8 bits precision, */ + /* we reduce it to 8 bits by shifting */ + for (i=0; i < ColorMapSize; i++) { + if (i < num_colors) { + if (colormap != NULL) { + if (dinfo->cinfo->out_color_space == JCS_RGB) { + /* Normal case: RGB color map */ + putc(GETJSAMPLE(colormap[0][i]) >> cshift, dinfo->pub.output_file); + putc(GETJSAMPLE(colormap[1][i]) >> cshift, dinfo->pub.output_file); + putc(GETJSAMPLE(colormap[2][i]) >> cshift, dinfo->pub.output_file); + } else { + /* Grayscale "color map": possible if quantizing grayscale image */ + put_3bytes(dinfo, GETJSAMPLE(colormap[0][i]) >> cshift); + } + } else { + /* Create a gray-scale map of num_colors values, range 0..255 */ + put_3bytes(dinfo, (i * 255 + (num_colors-1)/2) / (num_colors-1)); + } + } else { + /* fill out the map to a power of 2 */ + put_3bytes(dinfo, 0); + } + } + /* Write image separator and Image Descriptor */ + putc(',', dinfo->pub.output_file); /* separator */ + put_word(dinfo, 0); /* left/top offset */ + put_word(dinfo, 0); + put_word(dinfo, (unsigned int) dinfo->cinfo->output_width); /* image size */ + put_word(dinfo, (unsigned int) dinfo->cinfo->output_height); + /* flag byte: not interlaced, no local color map */ + putc(0x00, dinfo->pub.output_file); + /* Write Initial Code Size byte */ + putc(InitCodeSize, dinfo->pub.output_file); + + /* Initialize for "compression" of image data */ + compress_init(dinfo, InitCodeSize+1); +} + + +/* + * Startup: write the file header. + */ + +METHODDEF(void) +start_output_gif (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo) +{ + gif_dest_ptr dest = (gif_dest_ptr) dinfo; + + if (cinfo->quantize_colors) + emit_header(dest, cinfo->actual_number_of_colors, cinfo->colormap); + else + emit_header(dest, 256, (JSAMPARRAY) NULL); +} + + +/* + * Write some pixel data. + * In this module rows_supplied will always be 1. + */ + +METHODDEF(void) +put_pixel_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo, + JDIMENSION rows_supplied) +{ + gif_dest_ptr dest = (gif_dest_ptr) dinfo; + register JSAMPROW ptr; + register JDIMENSION col; + + ptr = dest->pub.buffer[0]; + for (col = cinfo->output_width; col > 0; col--) { + compress_pixel(dest, GETJSAMPLE(*ptr++)); + } +} + + +/* + * Finish up at the end of the file. + */ + +METHODDEF(void) +finish_output_gif (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo) +{ + gif_dest_ptr dest = (gif_dest_ptr) dinfo; + + /* Flush "compression" mechanism */ + compress_term(dest); + /* Write a zero-length data block to end the series */ + putc(0, dest->pub.output_file); + /* Write the GIF terminator mark */ + putc(';', dest->pub.output_file); + /* Make sure we wrote the output file OK */ + fflush(dest->pub.output_file); + if (ferror(dest->pub.output_file)) + ERREXIT(cinfo, JERR_FILE_WRITE); +} + + +/* + * The module selection routine for GIF format output. + */ + +GLOBAL(djpeg_dest_ptr) +jinit_write_gif (j_decompress_ptr cinfo) +{ + gif_dest_ptr dest; + + /* Create module interface object, fill in method pointers */ + dest = (gif_dest_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(gif_dest_struct)); + dest->cinfo = cinfo; /* make back link for subroutines */ + dest->pub.start_output = start_output_gif; + dest->pub.put_pixel_rows = put_pixel_rows; + dest->pub.finish_output = finish_output_gif; + + if (cinfo->out_color_space != JCS_GRAYSCALE && + cinfo->out_color_space != JCS_RGB) + ERREXIT(cinfo, JERR_GIF_COLORSPACE); + + /* Force quantization if color or if > 8 bits input */ + if (cinfo->out_color_space != JCS_GRAYSCALE || cinfo->data_precision > 8) { + /* Force quantization to at most 256 colors */ + cinfo->quantize_colors = TRUE; + if (cinfo->desired_number_of_colors > 256) + cinfo->desired_number_of_colors = 256; + } + + /* Calculate output image dimensions so we can allocate space */ + jpeg_calc_output_dimensions(cinfo); + + if (cinfo->output_components != 1) /* safety check: just one component? */ + ERREXIT(cinfo, JERR_GIF_BUG); + + /* Create decompressor output buffer. */ + dest->pub.buffer = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, cinfo->output_width, (JDIMENSION) 1); + dest->pub.buffer_height = 1; + + return (djpeg_dest_ptr) dest; +} + +#endif /* GIF_SUPPORTED */ diff --git a/lc-continuity/mk4/modimage/jpeg-6b/wrjpgcom.1 b/lc-continuity/mk4/modimage/jpeg-6b/wrjpgcom.1 new file mode 100644 index 0000000000000000000000000000000000000000..d419a99993695c7f19091f270e6a197da36e73c9 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/wrjpgcom.1 @@ -0,0 +1,103 @@ +.TH WRJPGCOM 1 "15 June 1995" +.SH NAME +wrjpgcom \- insert text comments into a JPEG file +.SH SYNOPSIS +.B wrjpgcom +[ +.B \-replace +] +[ +.BI \-comment " text" +] +[ +.BI \-cfile " name" +] +[ +.I filename +] +.LP +.SH DESCRIPTION +.LP +.B wrjpgcom +reads the named JPEG/JFIF file, or the standard input if no file is named, +and generates a new JPEG/JFIF file on standard output. A comment block is +added to the file. +.PP +The JPEG standard allows "comment" (COM) blocks to occur within a JPEG file. +Although the standard doesn't actually define what COM blocks are for, they +are widely used to hold user-supplied text strings. This lets you add +annotations, titles, index terms, etc to your JPEG files, and later retrieve +them as text. COM blocks do not interfere with the image stored in the JPEG +file. The maximum size of a COM block is 64K, but you can have as many of +them as you like in one JPEG file. +.PP +.B wrjpgcom +adds a COM block, containing text you provide, to a JPEG file. +Ordinarily, the COM block is added after any existing COM blocks; but you +can delete the old COM blocks if you wish. +.SH OPTIONS +Switch names may be abbreviated, and are not case sensitive. +.TP +.B \-replace +Delete any existing COM blocks from the file. +.TP +.BI \-comment " text" +Supply text for new COM block on command line. +.TP +.BI \-cfile " name" +Read text for new COM block from named file. +.PP +If you have only one line of comment text to add, you can provide it on the +command line with +.BR \-comment . +The comment text must be surrounded with quotes so that it is treated as a +single argument. Longer comments can be read from a text file. +.PP +If you give neither +.B \-comment +nor +.BR \-cfile , +then +.B wrjpgcom +will read the comment text from standard input. (In this case an input image +file name MUST be supplied, so that the source JPEG file comes from somewhere +else.) You can enter multiple lines, up to 64KB worth. Type an end-of-file +indicator (usually control-D) to terminate the comment text entry. +.PP +.B wrjpgcom +will not add a COM block if the provided comment string is empty. Therefore +\fB\-replace \-comment ""\fR can be used to delete all COM blocks from a file. +.SH EXAMPLES +.LP +Add a short comment to in.jpg, producing out.jpg: +.IP +.B wrjpgcom \-c +\fI"View of my back yard" in.jpg +.B > +.I out.jpg +.PP +Attach a long comment previously stored in comment.txt: +.IP +.B wrjpgcom +.I in.jpg +.B < +.I comment.txt +.B > +.I out.jpg +.PP +or equivalently +.IP +.B wrjpgcom +.B -cfile +.I comment.txt +.B < +.I in.jpg +.B > +.I out.jpg +.SH SEE ALSO +.BR cjpeg (1), +.BR djpeg (1), +.BR jpegtran (1), +.BR rdjpgcom (1) +.SH AUTHOR +Independent JPEG Group diff --git a/lc-continuity/mk4/modimage/jpeg-6b/wrjpgcom.c b/lc-continuity/mk4/modimage/jpeg-6b/wrjpgcom.c new file mode 100644 index 0000000000000000000000000000000000000000..8c04b055120fd58cc96664b1bb89edd0f355aa55 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/wrjpgcom.c @@ -0,0 +1,583 @@ +/* + * wrjpgcom.c + * + * Copyright (C) 1994-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a very simple stand-alone application that inserts + * user-supplied text as a COM (comment) marker in a JFIF file. + * This may be useful as an example of the minimum logic needed to parse + * JPEG markers. + */ + +#define JPEG_CJPEG_DJPEG /* to get the command-line config symbols */ +#include "jinclude.h" /* get auto-config symbols, */ + +#ifndef HAVE_STDLIB_H /* should declare malloc() */ +extern void * malloc (); +#endif +#include /* to declare isupper(), tolower() */ +#ifdef USE_SETMODE +#include /* to declare setmode()'s parameter macros */ +/* If you have setmode() but not , just delete this line: */ +#include /* to declare setmode() */ +#endif + +#ifdef USE_CCOMMAND /* command-line reader for Macintosh */ +#ifdef __MWERKS__ +#include /* Metrowerks needs this */ +#include /* ... and this */ +#endif +#ifdef THINK_C +#include /* Think declares it here */ +#endif +#endif + +#ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */ +#define READ_BINARY "r" +#define WRITE_BINARY "w" +#else +#ifdef VMS /* VMS is very nonstandard */ +#define READ_BINARY "rb", "ctx=stm" +#define WRITE_BINARY "wb", "ctx=stm" +#else /* standard ANSI-compliant case */ +#define READ_BINARY "rb" +#define WRITE_BINARY "wb" +#endif +#endif + +#ifndef EXIT_FAILURE /* define exit() codes if not provided */ +#define EXIT_FAILURE 1 +#endif +#ifndef EXIT_SUCCESS +#ifdef VMS +#define EXIT_SUCCESS 1 /* VMS is very nonstandard */ +#else +#define EXIT_SUCCESS 0 +#endif +#endif + +/* Reduce this value if your malloc() can't allocate blocks up to 64K. + * On DOS, compiling in large model is usually a better solution. + */ + +#ifndef MAX_COM_LENGTH +#define MAX_COM_LENGTH 65000L /* must be <= 65533 in any case */ +#endif + + +/* + * These macros are used to read the input file and write the output file. + * To reuse this code in another application, you might need to change these. + */ + +static FILE * infile; /* input JPEG file */ + +/* Return next input byte, or EOF if no more */ +#define NEXTBYTE() getc(infile) + +static FILE * outfile; /* output JPEG file */ + +/* Emit an output byte */ +#define PUTBYTE(x) putc((x), outfile) + + +/* Error exit handler */ +#define ERREXIT(msg) (fprintf(stderr, "%s\n", msg), exit(EXIT_FAILURE)) + + +/* Read one byte, testing for EOF */ +static int +read_1_byte (void) +{ + int c; + + c = NEXTBYTE(); + if (c == EOF) + ERREXIT("Premature EOF in JPEG file"); + return c; +} + +/* Read 2 bytes, convert to unsigned int */ +/* All 2-byte quantities in JPEG markers are MSB first */ +static unsigned int +read_2_bytes (void) +{ + int c1, c2; + + c1 = NEXTBYTE(); + if (c1 == EOF) + ERREXIT("Premature EOF in JPEG file"); + c2 = NEXTBYTE(); + if (c2 == EOF) + ERREXIT("Premature EOF in JPEG file"); + return (((unsigned int) c1) << 8) + ((unsigned int) c2); +} + + +/* Routines to write data to output file */ + +static void +write_1_byte (int c) +{ + PUTBYTE(c); +} + +static void +write_2_bytes (unsigned int val) +{ + PUTBYTE((val >> 8) & 0xFF); + PUTBYTE(val & 0xFF); +} + +static void +write_marker (int marker) +{ + PUTBYTE(0xFF); + PUTBYTE(marker); +} + +static void +copy_rest_of_file (void) +{ + int c; + + while ((c = NEXTBYTE()) != EOF) + PUTBYTE(c); +} + + +/* + * JPEG markers consist of one or more 0xFF bytes, followed by a marker + * code byte (which is not an FF). Here are the marker codes of interest + * in this program. (See jdmarker.c for a more complete list.) + */ + +#define M_SOF0 0xC0 /* Start Of Frame N */ +#define M_SOF1 0xC1 /* N indicates which compression process */ +#define M_SOF2 0xC2 /* Only SOF0-SOF2 are now in common use */ +#define M_SOF3 0xC3 +#define M_SOF5 0xC5 /* NB: codes C4 and CC are NOT SOF markers */ +#define M_SOF6 0xC6 +#define M_SOF7 0xC7 +#define M_SOF9 0xC9 +#define M_SOF10 0xCA +#define M_SOF11 0xCB +#define M_SOF13 0xCD +#define M_SOF14 0xCE +#define M_SOF15 0xCF +#define M_SOI 0xD8 /* Start Of Image (beginning of datastream) */ +#define M_EOI 0xD9 /* End Of Image (end of datastream) */ +#define M_SOS 0xDA /* Start Of Scan (begins compressed data) */ +#define M_COM 0xFE /* COMment */ + + +/* + * Find the next JPEG marker and return its marker code. + * We expect at least one FF byte, possibly more if the compressor used FFs + * to pad the file. (Padding FFs will NOT be replicated in the output file.) + * There could also be non-FF garbage between markers. The treatment of such + * garbage is unspecified; we choose to skip over it but emit a warning msg. + * NB: this routine must not be used after seeing SOS marker, since it will + * not deal correctly with FF/00 sequences in the compressed image data... + */ + +static int +next_marker (void) +{ + int c; + int discarded_bytes = 0; + + /* Find 0xFF byte; count and skip any non-FFs. */ + c = read_1_byte(); + while (c != 0xFF) { + discarded_bytes++; + c = read_1_byte(); + } + /* Get marker code byte, swallowing any duplicate FF bytes. Extra FFs + * are legal as pad bytes, so don't count them in discarded_bytes. + */ + do { + c = read_1_byte(); + } while (c == 0xFF); + + if (discarded_bytes != 0) { + fprintf(stderr, "Warning: garbage data found in JPEG file\n"); + } + + return c; +} + + +/* + * Read the initial marker, which should be SOI. + * For a JFIF file, the first two bytes of the file should be literally + * 0xFF M_SOI. To be more general, we could use next_marker, but if the + * input file weren't actually JPEG at all, next_marker might read the whole + * file and then return a misleading error message... + */ + +static int +first_marker (void) +{ + int c1, c2; + + c1 = NEXTBYTE(); + c2 = NEXTBYTE(); + if (c1 != 0xFF || c2 != M_SOI) + ERREXIT("Not a JPEG file"); + return c2; +} + + +/* + * Most types of marker are followed by a variable-length parameter segment. + * This routine skips over the parameters for any marker we don't otherwise + * want to process. + * Note that we MUST skip the parameter segment explicitly in order not to + * be fooled by 0xFF bytes that might appear within the parameter segment; + * such bytes do NOT introduce new markers. + */ + +static void +copy_variable (void) +/* Copy an unknown or uninteresting variable-length marker */ +{ + unsigned int length; + + /* Get the marker parameter length count */ + length = read_2_bytes(); + write_2_bytes(length); + /* Length includes itself, so must be at least 2 */ + if (length < 2) + ERREXIT("Erroneous JPEG marker length"); + length -= 2; + /* Skip over the remaining bytes */ + while (length > 0) { + write_1_byte(read_1_byte()); + length--; + } +} + +static void +skip_variable (void) +/* Skip over an unknown or uninteresting variable-length marker */ +{ + unsigned int length; + + /* Get the marker parameter length count */ + length = read_2_bytes(); + /* Length includes itself, so must be at least 2 */ + if (length < 2) + ERREXIT("Erroneous JPEG marker length"); + length -= 2; + /* Skip over the remaining bytes */ + while (length > 0) { + (void) read_1_byte(); + length--; + } +} + + +/* + * Parse the marker stream until SOFn or EOI is seen; + * copy data to output, but discard COM markers unless keep_COM is true. + */ + +static int +scan_JPEG_header (int keep_COM) +{ + int marker; + + /* Expect SOI at start of file */ + if (first_marker() != M_SOI) + ERREXIT("Expected SOI marker first"); + write_marker(M_SOI); + + /* Scan miscellaneous markers until we reach SOFn. */ + for (;;) { + marker = next_marker(); + switch (marker) { + /* Note that marker codes 0xC4, 0xC8, 0xCC are not, and must not be, + * treated as SOFn. C4 in particular is actually DHT. + */ + case M_SOF0: /* Baseline */ + case M_SOF1: /* Extended sequential, Huffman */ + case M_SOF2: /* Progressive, Huffman */ + case M_SOF3: /* Lossless, Huffman */ + case M_SOF5: /* Differential sequential, Huffman */ + case M_SOF6: /* Differential progressive, Huffman */ + case M_SOF7: /* Differential lossless, Huffman */ + case M_SOF9: /* Extended sequential, arithmetic */ + case M_SOF10: /* Progressive, arithmetic */ + case M_SOF11: /* Lossless, arithmetic */ + case M_SOF13: /* Differential sequential, arithmetic */ + case M_SOF14: /* Differential progressive, arithmetic */ + case M_SOF15: /* Differential lossless, arithmetic */ + return marker; + + case M_SOS: /* should not see compressed data before SOF */ + ERREXIT("SOS without prior SOFn"); + break; + + case M_EOI: /* in case it's a tables-only JPEG stream */ + return marker; + + case M_COM: /* Existing COM: conditionally discard */ + if (keep_COM) { + write_marker(marker); + copy_variable(); + } else { + skip_variable(); + } + break; + + default: /* Anything else just gets copied */ + write_marker(marker); + copy_variable(); /* we assume it has a parameter count... */ + break; + } + } /* end loop */ +} + + +/* Command line parsing code */ + +static const char * progname; /* program name for error messages */ + + +static void +usage (void) +/* complain about bad command line */ +{ + fprintf(stderr, "wrjpgcom inserts a textual comment in a JPEG file.\n"); + fprintf(stderr, "You can add to or replace any existing comment(s).\n"); + + fprintf(stderr, "Usage: %s [switches] ", progname); +#ifdef TWO_FILE_COMMANDLINE + fprintf(stderr, "inputfile outputfile\n"); +#else + fprintf(stderr, "[inputfile]\n"); +#endif + + fprintf(stderr, "Switches (names may be abbreviated):\n"); + fprintf(stderr, " -replace Delete any existing comments\n"); + fprintf(stderr, " -comment \"text\" Insert comment with given text\n"); + fprintf(stderr, " -cfile name Read comment from named file\n"); + fprintf(stderr, "Notice that you must put quotes around the comment text\n"); + fprintf(stderr, "when you use -comment.\n"); + fprintf(stderr, "If you do not give either -comment or -cfile on the command line,\n"); + fprintf(stderr, "then the comment text is read from standard input.\n"); + fprintf(stderr, "It can be multiple lines, up to %u characters total.\n", + (unsigned int) MAX_COM_LENGTH); +#ifndef TWO_FILE_COMMANDLINE + fprintf(stderr, "You must specify an input JPEG file name when supplying\n"); + fprintf(stderr, "comment text from standard input.\n"); +#endif + + exit(EXIT_FAILURE); +} + + +static int +keymatch (char * arg, const char * keyword, int minchars) +/* Case-insensitive matching of (possibly abbreviated) keyword switches. */ +/* keyword is the constant keyword (must be lower case already), */ +/* minchars is length of minimum legal abbreviation. */ +{ + register int ca, ck; + register int nmatched = 0; + + while ((ca = *arg++) != '\0') { + if ((ck = *keyword++) == '\0') + return 0; /* arg longer than keyword, no good */ + if (isupper(ca)) /* force arg to lcase (assume ck is already) */ + ca = tolower(ca); + if (ca != ck) + return 0; /* no good */ + nmatched++; /* count matched characters */ + } + /* reached end of argument; fail if it's too short for unique abbrev */ + if (nmatched < minchars) + return 0; + return 1; /* A-OK */ +} + + +/* + * The main program. + */ + +int +main (int argc, char **argv) +{ + int argn; + char * arg; + int keep_COM = 1; + char * comment_arg = NULL; + FILE * comment_file = NULL; + unsigned int comment_length = 0; + int marker; + + /* On Mac, fetch a command line. */ +#ifdef USE_CCOMMAND + argc = ccommand(&argv); +#endif + + progname = argv[0]; + if (progname == NULL || progname[0] == 0) + progname = "wrjpgcom"; /* in case C library doesn't provide it */ + + /* Parse switches, if any */ + for (argn = 1; argn < argc; argn++) { + arg = argv[argn]; + if (arg[0] != '-') + break; /* not switch, must be file name */ + arg++; /* advance over '-' */ + if (keymatch(arg, "replace", 1)) { + keep_COM = 0; + } else if (keymatch(arg, "cfile", 2)) { + if (++argn >= argc) usage(); + if ((comment_file = fopen(argv[argn], "r")) == NULL) { + fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]); + exit(EXIT_FAILURE); + } + } else if (keymatch(arg, "comment", 1)) { + if (++argn >= argc) usage(); + comment_arg = argv[argn]; + /* If the comment text starts with '"', then we are probably running + * under MS-DOG and must parse out the quoted string ourselves. Sigh. + */ + if (comment_arg[0] == '"') { + comment_arg = (char *) malloc((size_t) MAX_COM_LENGTH); + if (comment_arg == NULL) + ERREXIT("Insufficient memory"); + strcpy(comment_arg, argv[argn]+1); + for (;;) { + comment_length = (unsigned int) strlen(comment_arg); + if (comment_length > 0 && comment_arg[comment_length-1] == '"') { + comment_arg[comment_length-1] = '\0'; /* zap terminating quote */ + break; + } + if (++argn >= argc) + ERREXIT("Missing ending quote mark"); + strcat(comment_arg, " "); + strcat(comment_arg, argv[argn]); + } + } + comment_length = (unsigned int) strlen(comment_arg); + } else + usage(); + } + + /* Cannot use both -comment and -cfile. */ + if (comment_arg != NULL && comment_file != NULL) + usage(); + /* If there is neither -comment nor -cfile, we will read the comment text + * from stdin; in this case there MUST be an input JPEG file name. + */ + if (comment_arg == NULL && comment_file == NULL && argn >= argc) + usage(); + + /* Open the input file. */ + if (argn < argc) { + if ((infile = fopen(argv[argn], READ_BINARY)) == NULL) { + fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]); + exit(EXIT_FAILURE); + } + } else { + /* default input file is stdin */ +#ifdef USE_SETMODE /* need to hack file mode? */ + setmode(fileno(stdin), O_BINARY); +#endif +#ifdef USE_FDOPEN /* need to re-open in binary mode? */ + if ((infile = fdopen(fileno(stdin), READ_BINARY)) == NULL) { + fprintf(stderr, "%s: can't open stdin\n", progname); + exit(EXIT_FAILURE); + } +#else + infile = stdin; +#endif + } + + /* Open the output file. */ +#ifdef TWO_FILE_COMMANDLINE + /* Must have explicit output file name */ + if (argn != argc-2) { + fprintf(stderr, "%s: must name one input and one output file\n", + progname); + usage(); + } + if ((outfile = fopen(argv[argn+1], WRITE_BINARY)) == NULL) { + fprintf(stderr, "%s: can't open %s\n", progname, argv[argn+1]); + exit(EXIT_FAILURE); + } +#else + /* Unix style: expect zero or one file name */ + if (argn < argc-1) { + fprintf(stderr, "%s: only one input file\n", progname); + usage(); + } + /* default output file is stdout */ +#ifdef USE_SETMODE /* need to hack file mode? */ + setmode(fileno(stdout), O_BINARY); +#endif +#ifdef USE_FDOPEN /* need to re-open in binary mode? */ + if ((outfile = fdopen(fileno(stdout), WRITE_BINARY)) == NULL) { + fprintf(stderr, "%s: can't open stdout\n", progname); + exit(EXIT_FAILURE); + } +#else + outfile = stdout; +#endif +#endif /* TWO_FILE_COMMANDLINE */ + + /* Collect comment text from comment_file or stdin, if necessary */ + if (comment_arg == NULL) { + FILE * src_file; + int c; + + comment_arg = (char *) malloc((size_t) MAX_COM_LENGTH); + if (comment_arg == NULL) + ERREXIT("Insufficient memory"); + comment_length = 0; + src_file = (comment_file != NULL ? comment_file : stdin); + while ((c = getc(src_file)) != EOF) { + if (comment_length >= (unsigned int) MAX_COM_LENGTH) { + fprintf(stderr, "Comment text may not exceed %u bytes\n", + (unsigned int) MAX_COM_LENGTH); + exit(EXIT_FAILURE); + } + comment_arg[comment_length++] = (char) c; + } + if (comment_file != NULL) + fclose(comment_file); + } + + /* Copy JPEG headers until SOFn marker; + * we will insert the new comment marker just before SOFn. + * This (a) causes the new comment to appear after, rather than before, + * existing comments; and (b) ensures that comments come after any JFIF + * or JFXX markers, as required by the JFIF specification. + */ + marker = scan_JPEG_header(keep_COM); + /* Insert the new COM marker, but only if nonempty text has been supplied */ + if (comment_length > 0) { + write_marker(M_COM); + write_2_bytes(comment_length + 2); + while (comment_length > 0) { + write_1_byte(*comment_arg++); + comment_length--; + } + } + /* Duplicate the remainder of the source file. + * Note that any COM markers occuring after SOF will not be touched. + */ + write_marker(marker); + copy_rest_of_file(); + + /* All done. */ + exit(EXIT_SUCCESS); + return 0; /* suppress no-return-value warnings */ +} diff --git a/lc-continuity/mk4/modimage/jpeg-6b/wrppm.c b/lc-continuity/mk4/modimage/jpeg-6b/wrppm.c new file mode 100644 index 0000000000000000000000000000000000000000..6c6d908817c9c3dd253f3432ec1a5a8d7251923c --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/wrppm.c @@ -0,0 +1,268 @@ +/* + * wrppm.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains routines to write output images in PPM/PGM format. + * The extended 2-byte-per-sample raw PPM/PGM formats are supported. + * The PBMPLUS library is NOT required to compile this software + * (but it is highly useful as a set of PPM image manipulation programs). + * + * These routines may need modification for non-Unix environments or + * specialized applications. As they stand, they assume output to + * an ordinary stdio stream. + */ + +#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ + +#ifdef PPM_SUPPORTED + + +/* + * For 12-bit JPEG data, we either downscale the values to 8 bits + * (to write standard byte-per-sample PPM/PGM files), or output + * nonstandard word-per-sample PPM/PGM files. Downscaling is done + * if PPM_NORAWWORD is defined (this can be done in the Makefile + * or in jconfig.h). + * (When the core library supports data precision reduction, a cleaner + * implementation will be to ask for that instead.) + */ + +#if BITS_IN_JSAMPLE == 8 +#define PUTPPMSAMPLE(ptr,v) *ptr++ = (char) (v) +#define BYTESPERSAMPLE 1 +#define PPM_MAXVAL 255 +#else +#ifdef PPM_NORAWWORD +#define PUTPPMSAMPLE(ptr,v) *ptr++ = (char) ((v) >> (BITS_IN_JSAMPLE-8)) +#define BYTESPERSAMPLE 1 +#define PPM_MAXVAL 255 +#else +/* The word-per-sample format always puts the LSB first. */ +#define PUTPPMSAMPLE(ptr,v) \ + { register int val_ = v; \ + *ptr++ = (char) (val_ & 0xFF); \ + *ptr++ = (char) ((val_ >> 8) & 0xFF); \ + } +#define BYTESPERSAMPLE 2 +#define PPM_MAXVAL ((1<pub.output_file, dest->iobuffer, dest->buffer_width); +} + + +/* + * This code is used when we have to copy the data and apply a pixel + * format translation. Typically this only happens in 12-bit mode. + */ + +METHODDEF(void) +copy_pixel_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo, + JDIMENSION rows_supplied) +{ + ppm_dest_ptr dest = (ppm_dest_ptr) dinfo; + register char * bufferptr; + register JSAMPROW ptr; + register JDIMENSION col; + + ptr = dest->pub.buffer[0]; + bufferptr = dest->iobuffer; + for (col = dest->samples_per_row; col > 0; col--) { + PUTPPMSAMPLE(bufferptr, GETJSAMPLE(*ptr++)); + } + (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width); +} + + +/* + * Write some pixel data when color quantization is in effect. + * We have to demap the color index values to straight data. + */ + +METHODDEF(void) +put_demapped_rgb (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo, + JDIMENSION rows_supplied) +{ + ppm_dest_ptr dest = (ppm_dest_ptr) dinfo; + register char * bufferptr; + register int pixval; + register JSAMPROW ptr; + register JSAMPROW color_map0 = cinfo->colormap[0]; + register JSAMPROW color_map1 = cinfo->colormap[1]; + register JSAMPROW color_map2 = cinfo->colormap[2]; + register JDIMENSION col; + + ptr = dest->pub.buffer[0]; + bufferptr = dest->iobuffer; + for (col = cinfo->output_width; col > 0; col--) { + pixval = GETJSAMPLE(*ptr++); + PUTPPMSAMPLE(bufferptr, GETJSAMPLE(color_map0[pixval])); + PUTPPMSAMPLE(bufferptr, GETJSAMPLE(color_map1[pixval])); + PUTPPMSAMPLE(bufferptr, GETJSAMPLE(color_map2[pixval])); + } + (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width); +} + + +METHODDEF(void) +put_demapped_gray (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo, + JDIMENSION rows_supplied) +{ + ppm_dest_ptr dest = (ppm_dest_ptr) dinfo; + register char * bufferptr; + register JSAMPROW ptr; + register JSAMPROW color_map = cinfo->colormap[0]; + register JDIMENSION col; + + ptr = dest->pub.buffer[0]; + bufferptr = dest->iobuffer; + for (col = cinfo->output_width; col > 0; col--) { + PUTPPMSAMPLE(bufferptr, GETJSAMPLE(color_map[GETJSAMPLE(*ptr++)])); + } + (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width); +} + + +/* + * Startup: write the file header. + */ + +METHODDEF(void) +start_output_ppm (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo) +{ + ppm_dest_ptr dest = (ppm_dest_ptr) dinfo; + + /* Emit file header */ + switch (cinfo->out_color_space) { + case JCS_GRAYSCALE: + /* emit header for raw PGM format */ + fprintf(dest->pub.output_file, "P5\n%ld %ld\n%d\n", + (long) cinfo->output_width, (long) cinfo->output_height, + PPM_MAXVAL); + break; + case JCS_RGB: + /* emit header for raw PPM format */ + fprintf(dest->pub.output_file, "P6\n%ld %ld\n%d\n", + (long) cinfo->output_width, (long) cinfo->output_height, + PPM_MAXVAL); + break; + default: + ERREXIT(cinfo, JERR_PPM_COLORSPACE); + } +} + + +/* + * Finish up at the end of the file. + */ + +METHODDEF(void) +finish_output_ppm (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo) +{ + /* Make sure we wrote the output file OK */ + fflush(dinfo->output_file); + if (ferror(dinfo->output_file)) + ERREXIT(cinfo, JERR_FILE_WRITE); +} + + +/* + * The module selection routine for PPM format output. + */ + +GLOBAL(djpeg_dest_ptr) +jinit_write_ppm (j_decompress_ptr cinfo) +{ + ppm_dest_ptr dest; + + /* Create module interface object, fill in method pointers */ + dest = (ppm_dest_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(ppm_dest_struct)); + dest->pub.start_output = start_output_ppm; + dest->pub.finish_output = finish_output_ppm; + + /* Calculate output image dimensions so we can allocate space */ + jpeg_calc_output_dimensions(cinfo); + + /* Create physical I/O buffer. Note we make this near on a PC. */ + dest->samples_per_row = cinfo->output_width * cinfo->out_color_components; + dest->buffer_width = dest->samples_per_row * (BYTESPERSAMPLE * SIZEOF(char)); + dest->iobuffer = (char *) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, dest->buffer_width); + + if (cinfo->quantize_colors || BITS_IN_JSAMPLE != 8 || + SIZEOF(JSAMPLE) != SIZEOF(char)) { + /* When quantizing, we need an output buffer for colormap indexes + * that's separate from the physical I/O buffer. We also need a + * separate buffer if pixel format translation must take place. + */ + dest->pub.buffer = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + cinfo->output_width * cinfo->output_components, (JDIMENSION) 1); + dest->pub.buffer_height = 1; + if (! cinfo->quantize_colors) + dest->pub.put_pixel_rows = copy_pixel_rows; + else if (cinfo->out_color_space == JCS_GRAYSCALE) + dest->pub.put_pixel_rows = put_demapped_gray; + else + dest->pub.put_pixel_rows = put_demapped_rgb; + } else { + /* We will fwrite() directly from decompressor output buffer. */ + /* Synthesize a JSAMPARRAY pointer structure */ + /* Cast here implies near->far pointer conversion on PCs */ + dest->pixrow = (JSAMPROW) dest->iobuffer; + dest->pub.buffer = & dest->pixrow; + dest->pub.buffer_height = 1; + dest->pub.put_pixel_rows = put_pixel_rows; + } + + return (djpeg_dest_ptr) dest; +} + +#endif /* PPM_SUPPORTED */ diff --git a/lc-continuity/mk4/modimage/jpeg-6b/wrrle.c b/lc-continuity/mk4/modimage/jpeg-6b/wrrle.c new file mode 100644 index 0000000000000000000000000000000000000000..a4e73372de66f86d0e8b4046f716b25cb1d5ad74 --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/wrrle.c @@ -0,0 +1,305 @@ +/* + * wrrle.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains routines to write output images in RLE format. + * The Utah Raster Toolkit library is required (version 3.1 or later). + * + * These routines may need modification for non-Unix environments or + * specialized applications. As they stand, they assume output to + * an ordinary stdio stream. + * + * Based on code contributed by Mike Lijewski, + * with updates from Robert Hutchinson. + */ + +#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ + +#ifdef RLE_SUPPORTED + +/* rle.h is provided by the Utah Raster Toolkit. */ + +#include + +/* + * We assume that JSAMPLE has the same representation as rle_pixel, + * to wit, "unsigned char". Hence we can't cope with 12- or 16-bit samples. + */ + +#if BITS_IN_JSAMPLE != 8 + Sorry, this code only copes with 8-bit JSAMPLEs. /* deliberate syntax err */ +#endif + + +/* + * Since RLE stores scanlines bottom-to-top, we have to invert the image + * from JPEG's top-to-bottom order. To do this, we save the outgoing data + * in a virtual array during put_pixel_row calls, then actually emit the + * RLE file during finish_output. + */ + + +/* + * For now, if we emit an RLE color map then it is always 256 entries long, + * though not all of the entries need be used. + */ + +#define CMAPBITS 8 +#define CMAPLENGTH (1<<(CMAPBITS)) + +typedef struct { + struct djpeg_dest_struct pub; /* public fields */ + + jvirt_sarray_ptr image; /* virtual array to store the output image */ + rle_map *colormap; /* RLE-style color map, or NULL if none */ + rle_pixel **rle_row; /* To pass rows to rle_putrow() */ + +} rle_dest_struct; + +typedef rle_dest_struct * rle_dest_ptr; + +/* Forward declarations */ +METHODDEF(void) rle_put_pixel_rows + JPP((j_decompress_ptr cinfo, djpeg_dest_ptr dinfo, + JDIMENSION rows_supplied)); + + +/* + * Write the file header. + * + * In this module it's easier to wait till finish_output to write anything. + */ + +METHODDEF(void) +start_output_rle (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo) +{ + rle_dest_ptr dest = (rle_dest_ptr) dinfo; + size_t cmapsize; + int i, ci; +#ifdef PROGRESS_REPORT + cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress; +#endif + + /* + * Make sure the image can be stored in RLE format. + * + * - RLE stores image dimensions as *signed* 16 bit integers. JPEG + * uses unsigned, so we have to check the width. + * + * - Colorspace is expected to be grayscale or RGB. + * + * - The number of channels (components) is expected to be 1 (grayscale/ + * pseudocolor) or 3 (truecolor/directcolor). + * (could be 2 or 4 if using an alpha channel, but we aren't) + */ + + if (cinfo->output_width > 32767 || cinfo->output_height > 32767) + ERREXIT2(cinfo, JERR_RLE_DIMENSIONS, cinfo->output_width, + cinfo->output_height); + + if (cinfo->out_color_space != JCS_GRAYSCALE && + cinfo->out_color_space != JCS_RGB) + ERREXIT(cinfo, JERR_RLE_COLORSPACE); + + if (cinfo->output_components != 1 && cinfo->output_components != 3) + ERREXIT1(cinfo, JERR_RLE_TOOMANYCHANNELS, cinfo->num_components); + + /* Convert colormap, if any, to RLE format. */ + + dest->colormap = NULL; + + if (cinfo->quantize_colors) { + /* Allocate storage for RLE-style cmap, zero any extra entries */ + cmapsize = cinfo->out_color_components * CMAPLENGTH * SIZEOF(rle_map); + dest->colormap = (rle_map *) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, cmapsize); + MEMZERO(dest->colormap, cmapsize); + + /* Save away data in RLE format --- note 8-bit left shift! */ + /* Shifting would need adjustment for JSAMPLEs wider than 8 bits. */ + for (ci = 0; ci < cinfo->out_color_components; ci++) { + for (i = 0; i < cinfo->actual_number_of_colors; i++) { + dest->colormap[ci * CMAPLENGTH + i] = + GETJSAMPLE(cinfo->colormap[ci][i]) << 8; + } + } + } + + /* Set the output buffer to the first row */ + dest->pub.buffer = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, dest->image, (JDIMENSION) 0, (JDIMENSION) 1, TRUE); + dest->pub.buffer_height = 1; + + dest->pub.put_pixel_rows = rle_put_pixel_rows; + +#ifdef PROGRESS_REPORT + if (progress != NULL) { + progress->total_extra_passes++; /* count file writing as separate pass */ + } +#endif +} + + +/* + * Write some pixel data. + * + * This routine just saves the data away in a virtual array. + */ + +METHODDEF(void) +rle_put_pixel_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo, + JDIMENSION rows_supplied) +{ + rle_dest_ptr dest = (rle_dest_ptr) dinfo; + + if (cinfo->output_scanline < cinfo->output_height) { + dest->pub.buffer = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, dest->image, + cinfo->output_scanline, (JDIMENSION) 1, TRUE); + } +} + +/* + * Finish up at the end of the file. + * + * Here is where we really output the RLE file. + */ + +METHODDEF(void) +finish_output_rle (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo) +{ + rle_dest_ptr dest = (rle_dest_ptr) dinfo; + rle_hdr header; /* Output file information */ + rle_pixel **rle_row, *red, *green, *blue; + JSAMPROW output_row; + char cmapcomment[80]; + int row, col; + int ci; +#ifdef PROGRESS_REPORT + cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress; +#endif + + /* Initialize the header info */ + header = *rle_hdr_init(NULL); + header.rle_file = dest->pub.output_file; + header.xmin = 0; + header.xmax = cinfo->output_width - 1; + header.ymin = 0; + header.ymax = cinfo->output_height - 1; + header.alpha = 0; + header.ncolors = cinfo->output_components; + for (ci = 0; ci < cinfo->output_components; ci++) { + RLE_SET_BIT(header, ci); + } + if (cinfo->quantize_colors) { + header.ncmap = cinfo->out_color_components; + header.cmaplen = CMAPBITS; + header.cmap = dest->colormap; + /* Add a comment to the output image with the true colormap length. */ + sprintf(cmapcomment, "color_map_length=%d", cinfo->actual_number_of_colors); + rle_putcom(cmapcomment, &header); + } + + /* Emit the RLE header and color map (if any) */ + rle_put_setup(&header); + + /* Now output the RLE data from our virtual array. + * We assume here that (a) rle_pixel is represented the same as JSAMPLE, + * and (b) we are not on a machine where FAR pointers differ from regular. + */ + +#ifdef PROGRESS_REPORT + if (progress != NULL) { + progress->pub.pass_limit = cinfo->output_height; + progress->pub.pass_counter = 0; + (*progress->pub.progress_monitor) ((j_common_ptr) cinfo); + } +#endif + + if (cinfo->output_components == 1) { + for (row = cinfo->output_height-1; row >= 0; row--) { + rle_row = (rle_pixel **) (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, dest->image, + (JDIMENSION) row, (JDIMENSION) 1, FALSE); + rle_putrow(rle_row, (int) cinfo->output_width, &header); +#ifdef PROGRESS_REPORT + if (progress != NULL) { + progress->pub.pass_counter++; + (*progress->pub.progress_monitor) ((j_common_ptr) cinfo); + } +#endif + } + } else { + for (row = cinfo->output_height-1; row >= 0; row--) { + rle_row = (rle_pixel **) dest->rle_row; + output_row = * (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, dest->image, + (JDIMENSION) row, (JDIMENSION) 1, FALSE); + red = rle_row[0]; + green = rle_row[1]; + blue = rle_row[2]; + for (col = cinfo->output_width; col > 0; col--) { + *red++ = GETJSAMPLE(*output_row++); + *green++ = GETJSAMPLE(*output_row++); + *blue++ = GETJSAMPLE(*output_row++); + } + rle_putrow(rle_row, (int) cinfo->output_width, &header); +#ifdef PROGRESS_REPORT + if (progress != NULL) { + progress->pub.pass_counter++; + (*progress->pub.progress_monitor) ((j_common_ptr) cinfo); + } +#endif + } + } + +#ifdef PROGRESS_REPORT + if (progress != NULL) + progress->completed_extra_passes++; +#endif + + /* Emit file trailer */ + rle_puteof(&header); + fflush(dest->pub.output_file); + if (ferror(dest->pub.output_file)) + ERREXIT(cinfo, JERR_FILE_WRITE); +} + + +/* + * The module selection routine for RLE format output. + */ + +GLOBAL(djpeg_dest_ptr) +jinit_write_rle (j_decompress_ptr cinfo) +{ + rle_dest_ptr dest; + + /* Create module interface object, fill in method pointers */ + dest = (rle_dest_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(rle_dest_struct)); + dest->pub.start_output = start_output_rle; + dest->pub.finish_output = finish_output_rle; + + /* Calculate output image dimensions so we can allocate space */ + jpeg_calc_output_dimensions(cinfo); + + /* Allocate a work array for output to the RLE library. */ + dest->rle_row = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + cinfo->output_width, (JDIMENSION) cinfo->output_components); + + /* Allocate a virtual array to hold the image. */ + dest->image = (*cinfo->mem->request_virt_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, + (JDIMENSION) (cinfo->output_width * cinfo->output_components), + cinfo->output_height, (JDIMENSION) 1); + + return (djpeg_dest_ptr) dest; +} + +#endif /* RLE_SUPPORTED */ diff --git a/lc-continuity/mk4/modimage/jpeg-6b/wrtarga.c b/lc-continuity/mk4/modimage/jpeg-6b/wrtarga.c new file mode 100644 index 0000000000000000000000000000000000000000..cf104d2debd0ffbbfc67bbe00b332dc8ad77980d --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeg-6b/wrtarga.c @@ -0,0 +1,253 @@ +/* + * wrtarga.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains routines to write output images in Targa format. + * + * These routines may need modification for non-Unix environments or + * specialized applications. As they stand, they assume output to + * an ordinary stdio stream. + * + * Based on code contributed by Lee Daniel Crocker. + */ + +#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ + +#ifdef TARGA_SUPPORTED + + +/* + * To support 12-bit JPEG data, we'd have to scale output down to 8 bits. + * This is not yet implemented. + */ + +#if BITS_IN_JSAMPLE != 8 + Sorry, this code only copes with 8-bit JSAMPLEs. /* deliberate syntax err */ +#endif + +/* + * The output buffer needs to be writable by fwrite(). On PCs, we must + * allocate the buffer in near data space, because we are assuming small-data + * memory model, wherein fwrite() can't reach far memory. If you need to + * process very wide images on a PC, you might have to compile in large-memory + * model, or else replace fwrite() with a putc() loop --- which will be much + * slower. + */ + + +/* Private version of data destination object */ + +typedef struct { + struct djpeg_dest_struct pub; /* public fields */ + + char *iobuffer; /* physical I/O buffer */ + JDIMENSION buffer_width; /* width of one row */ +} tga_dest_struct; + +typedef tga_dest_struct * tga_dest_ptr; + + +LOCAL(void) +write_header (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo, int num_colors) +/* Create and write a Targa header */ +{ + char targaheader[18]; + + /* Set unused fields of header to 0 */ + MEMZERO(targaheader, SIZEOF(targaheader)); + + if (num_colors > 0) { + targaheader[1] = 1; /* color map type 1 */ + targaheader[5] = (char) (num_colors & 0xFF); + targaheader[6] = (char) (num_colors >> 8); + targaheader[7] = 24; /* 24 bits per cmap entry */ + } + + targaheader[12] = (char) (cinfo->output_width & 0xFF); + targaheader[13] = (char) (cinfo->output_width >> 8); + targaheader[14] = (char) (cinfo->output_height & 0xFF); + targaheader[15] = (char) (cinfo->output_height >> 8); + targaheader[17] = 0x20; /* Top-down, non-interlaced */ + + if (cinfo->out_color_space == JCS_GRAYSCALE) { + targaheader[2] = 3; /* image type = uncompressed gray-scale */ + targaheader[16] = 8; /* bits per pixel */ + } else { /* must be RGB */ + if (num_colors > 0) { + targaheader[2] = 1; /* image type = colormapped RGB */ + targaheader[16] = 8; + } else { + targaheader[2] = 2; /* image type = uncompressed RGB */ + targaheader[16] = 24; + } + } + + if (JFWRITE(dinfo->output_file, targaheader, 18) != (size_t) 18) + ERREXIT(cinfo, JERR_FILE_WRITE); +} + + +/* + * Write some pixel data. + * In this module rows_supplied will always be 1. + */ + +METHODDEF(void) +put_pixel_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo, + JDIMENSION rows_supplied) +/* used for unquantized full-color output */ +{ + tga_dest_ptr dest = (tga_dest_ptr) dinfo; + register JSAMPROW inptr; + register char * outptr; + register JDIMENSION col; + + inptr = dest->pub.buffer[0]; + outptr = dest->iobuffer; + for (col = cinfo->output_width; col > 0; col--) { + outptr[0] = (char) GETJSAMPLE(inptr[2]); /* RGB to BGR order */ + outptr[1] = (char) GETJSAMPLE(inptr[1]); + outptr[2] = (char) GETJSAMPLE(inptr[0]); + inptr += 3, outptr += 3; + } + (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width); +} + +METHODDEF(void) +put_gray_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo, + JDIMENSION rows_supplied) +/* used for grayscale OR quantized color output */ +{ + tga_dest_ptr dest = (tga_dest_ptr) dinfo; + register JSAMPROW inptr; + register char * outptr; + register JDIMENSION col; + + inptr = dest->pub.buffer[0]; + outptr = dest->iobuffer; + for (col = cinfo->output_width; col > 0; col--) { + *outptr++ = (char) GETJSAMPLE(*inptr++); + } + (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width); +} + + +/* + * Write some demapped pixel data when color quantization is in effect. + * For Targa, this is only applied to grayscale data. + */ + +METHODDEF(void) +put_demapped_gray (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo, + JDIMENSION rows_supplied) +{ + tga_dest_ptr dest = (tga_dest_ptr) dinfo; + register JSAMPROW inptr; + register char * outptr; + register JSAMPROW color_map0 = cinfo->colormap[0]; + register JDIMENSION col; + + inptr = dest->pub.buffer[0]; + outptr = dest->iobuffer; + for (col = cinfo->output_width; col > 0; col--) { + *outptr++ = (char) GETJSAMPLE(color_map0[GETJSAMPLE(*inptr++)]); + } + (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width); +} + + +/* + * Startup: write the file header. + */ + +METHODDEF(void) +start_output_tga (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo) +{ + tga_dest_ptr dest = (tga_dest_ptr) dinfo; + int num_colors, i; + FILE *outfile; + + if (cinfo->out_color_space == JCS_GRAYSCALE) { + /* Targa doesn't have a mapped grayscale format, so we will */ + /* demap quantized gray output. Never emit a colormap. */ + write_header(cinfo, dinfo, 0); + if (cinfo->quantize_colors) + dest->pub.put_pixel_rows = put_demapped_gray; + else + dest->pub.put_pixel_rows = put_gray_rows; + } else if (cinfo->out_color_space == JCS_RGB) { + if (cinfo->quantize_colors) { + /* We only support 8-bit colormap indexes, so only 256 colors */ + num_colors = cinfo->actual_number_of_colors; + if (num_colors > 256) + ERREXIT1(cinfo, JERR_TOO_MANY_COLORS, num_colors); + write_header(cinfo, dinfo, num_colors); + /* Write the colormap. Note Targa uses BGR byte order */ + outfile = dest->pub.output_file; + for (i = 0; i < num_colors; i++) { + putc(GETJSAMPLE(cinfo->colormap[2][i]), outfile); + putc(GETJSAMPLE(cinfo->colormap[1][i]), outfile); + putc(GETJSAMPLE(cinfo->colormap[0][i]), outfile); + } + dest->pub.put_pixel_rows = put_gray_rows; + } else { + write_header(cinfo, dinfo, 0); + dest->pub.put_pixel_rows = put_pixel_rows; + } + } else { + ERREXIT(cinfo, JERR_TGA_COLORSPACE); + } +} + + +/* + * Finish up at the end of the file. + */ + +METHODDEF(void) +finish_output_tga (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo) +{ + /* Make sure we wrote the output file OK */ + fflush(dinfo->output_file); + if (ferror(dinfo->output_file)) + ERREXIT(cinfo, JERR_FILE_WRITE); +} + + +/* + * The module selection routine for Targa format output. + */ + +GLOBAL(djpeg_dest_ptr) +jinit_write_targa (j_decompress_ptr cinfo) +{ + tga_dest_ptr dest; + + /* Create module interface object, fill in method pointers */ + dest = (tga_dest_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(tga_dest_struct)); + dest->pub.start_output = start_output_tga; + dest->pub.finish_output = finish_output_tga; + + /* Calculate output image dimensions so we can allocate space */ + jpeg_calc_output_dimensions(cinfo); + + /* Create I/O buffer. Note we make this near on a PC. */ + dest->buffer_width = cinfo->output_width * cinfo->output_components; + dest->iobuffer = (char *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (size_t) (dest->buffer_width * SIZEOF(char))); + + /* Create decompressor output buffer. */ + dest->pub.buffer = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, dest->buffer_width, (JDIMENSION) 1); + dest->pub.buffer_height = 1; + + return (djpeg_dest_ptr) dest; +} + +#endif /* TARGA_SUPPORTED */ diff --git a/lc-continuity/mk4/modimage/jpegint.h b/lc-continuity/mk4/modimage/jpegint.h new file mode 100644 index 0000000000000000000000000000000000000000..95b00d405caeca1dc971b37a94bbadc566f3074b --- /dev/null +++ b/lc-continuity/mk4/modimage/jpegint.h @@ -0,0 +1,392 @@ +/* + * jpegint.h + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file provides common declarations for the various JPEG modules. + * These declarations are considered internal to the JPEG library; most + * applications using the library shouldn't need to include this file. + */ + + +/* Declarations for both compression & decompression */ + +typedef enum { /* Operating modes for buffer controllers */ + JBUF_PASS_THRU, /* Plain stripwise operation */ + /* Remaining modes require a full-image buffer to have been created */ + JBUF_SAVE_SOURCE, /* Run source subobject only, save output */ + JBUF_CRANK_DEST, /* Run dest subobject only, using saved data */ + JBUF_SAVE_AND_PASS /* Run both subobjects, save output */ +} J_BUF_MODE; + +/* Values of global_state field (jdapi.c has some dependencies on ordering!) */ +#define CSTATE_START 100 /* after create_compress */ +#define CSTATE_SCANNING 101 /* start_compress done, write_scanlines OK */ +#define CSTATE_RAW_OK 102 /* start_compress done, write_raw_data OK */ +#define CSTATE_WRCOEFS 103 /* jpeg_write_coefficients done */ +#define DSTATE_START 200 /* after create_decompress */ +#define DSTATE_INHEADER 201 /* reading header markers, no SOS yet */ +#define DSTATE_READY 202 /* found SOS, ready for start_decompress */ +#define DSTATE_PRELOAD 203 /* reading multiscan file in start_decompress*/ +#define DSTATE_PRESCAN 204 /* performing dummy pass for 2-pass quant */ +#define DSTATE_SCANNING 205 /* start_decompress done, read_scanlines OK */ +#define DSTATE_RAW_OK 206 /* start_decompress done, read_raw_data OK */ +#define DSTATE_BUFIMAGE 207 /* expecting jpeg_start_output */ +#define DSTATE_BUFPOST 208 /* looking for SOS/EOI in jpeg_finish_output */ +#define DSTATE_RDCOEFS 209 /* reading file in jpeg_read_coefficients */ +#define DSTATE_STOPPING 210 /* looking for EOI in jpeg_finish_decompress */ + + +/* Declarations for compression modules */ + +/* Master control module */ +struct jpeg_comp_master { + JMETHOD(void, prepare_for_pass, (j_compress_ptr cinfo)); + JMETHOD(void, pass_startup, (j_compress_ptr cinfo)); + JMETHOD(void, finish_pass, (j_compress_ptr cinfo)); + + /* State variables made visible to other modules */ + boolean call_pass_startup; /* True if pass_startup must be called */ + boolean is_last_pass; /* True during last pass */ +}; + +/* Main buffer control (downsampled-data buffer) */ +struct jpeg_c_main_controller { + JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(void, process_data, (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail)); +}; + +/* Compression preprocessing (downsampling input buffer control) */ +struct jpeg_c_prep_controller { + JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(void, pre_process_data, (j_compress_ptr cinfo, + JSAMPARRAY input_buf, + JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail, + JSAMPIMAGE output_buf, + JDIMENSION *out_row_group_ctr, + JDIMENSION out_row_groups_avail)); +}; + +/* Coefficient buffer control */ +struct jpeg_c_coef_controller { + JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(boolean, compress_data, (j_compress_ptr cinfo, + JSAMPIMAGE input_buf)); +}; + +/* Colorspace conversion */ +struct jpeg_color_converter { + JMETHOD(void, start_pass, (j_compress_ptr cinfo)); + JMETHOD(void, color_convert, (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows)); +}; + +/* Downsampling */ +struct jpeg_downsampler { + JMETHOD(void, start_pass, (j_compress_ptr cinfo)); + JMETHOD(void, downsample, (j_compress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION in_row_index, + JSAMPIMAGE output_buf, + JDIMENSION out_row_group_index)); + + boolean need_context_rows; /* TRUE if need rows above & below */ +}; + +/* Forward DCT (also controls coefficient quantization) */ +struct jpeg_forward_dct { + JMETHOD(void, start_pass, (j_compress_ptr cinfo)); + /* perhaps this should be an array??? */ + JMETHOD(void, forward_DCT, (j_compress_ptr cinfo, + jpeg_component_info * compptr, + JSAMPARRAY sample_data, JBLOCKROW coef_blocks, + JDIMENSION start_row, JDIMENSION start_col, + JDIMENSION num_blocks)); +}; + +/* Entropy encoding */ +struct jpeg_entropy_encoder { + JMETHOD(void, start_pass, (j_compress_ptr cinfo, boolean gather_statistics)); + JMETHOD(boolean, encode_mcu, (j_compress_ptr cinfo, JBLOCKROW *MCU_data)); + JMETHOD(void, finish_pass, (j_compress_ptr cinfo)); +}; + +/* Marker writing */ +struct jpeg_marker_writer { + JMETHOD(void, write_file_header, (j_compress_ptr cinfo)); + JMETHOD(void, write_frame_header, (j_compress_ptr cinfo)); + JMETHOD(void, write_scan_header, (j_compress_ptr cinfo)); + JMETHOD(void, write_file_trailer, (j_compress_ptr cinfo)); + JMETHOD(void, write_tables_only, (j_compress_ptr cinfo)); + /* These routines are exported to allow insertion of extra markers */ + /* Probably only COM and APPn markers should be written this way */ + JMETHOD(void, write_marker_header, (j_compress_ptr cinfo, int marker, + unsigned int datalen)); + JMETHOD(void, write_marker_byte, (j_compress_ptr cinfo, int val)); +}; + + +/* Declarations for decompression modules */ + +/* Master control module */ +struct jpeg_decomp_master { + JMETHOD(void, prepare_for_output_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, finish_output_pass, (j_decompress_ptr cinfo)); + + /* State variables made visible to other modules */ + boolean is_dummy_pass; /* True during 1st pass for 2-pass quant */ +}; + +/* Input control module */ +struct jpeg_input_controller { + JMETHOD(int, consume_input, (j_decompress_ptr cinfo)); + JMETHOD(void, reset_input_controller, (j_decompress_ptr cinfo)); + JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, finish_input_pass, (j_decompress_ptr cinfo)); + + /* State variables made visible to other modules */ + boolean has_multiple_scans; /* True if file has multiple scans */ + boolean eoi_reached; /* True when EOI has been consumed */ +}; + +/* Main buffer control (downsampled-data buffer) */ +struct jpeg_d_main_controller { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(void, process_data, (j_decompress_ptr cinfo, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); +}; + +/* Coefficient buffer control */ +struct jpeg_d_coef_controller { + JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo)); + JMETHOD(int, consume_data, (j_decompress_ptr cinfo)); + JMETHOD(void, start_output_pass, (j_decompress_ptr cinfo)); + JMETHOD(int, decompress_data, (j_decompress_ptr cinfo, + JSAMPIMAGE output_buf)); + /* Pointer to array of coefficient virtual arrays, or NULL if none */ + jvirt_barray_ptr *coef_arrays; +}; + +/* Decompression postprocessing (color quantization buffer control) */ +struct jpeg_d_post_controller { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(void, post_process_data, (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, + JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); +}; + +/* Marker reading & parsing */ +struct jpeg_marker_reader { + JMETHOD(void, reset_marker_reader, (j_decompress_ptr cinfo)); + /* Read markers until SOS or EOI. + * Returns same codes as are defined for jpeg_consume_input: + * JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. + */ + JMETHOD(int, read_markers, (j_decompress_ptr cinfo)); + /* Read a restart marker --- exported for use by entropy decoder only */ + jpeg_marker_parser_method read_restart_marker; + + /* State of marker reader --- nominally internal, but applications + * supplying COM or APPn handlers might like to know the state. + */ + boolean saw_SOI; /* found SOI? */ + boolean saw_SOF; /* found SOF? */ + int next_restart_num; /* next restart number expected (0-7) */ + unsigned int discarded_bytes; /* # of bytes skipped looking for a marker */ +}; + +/* Entropy decoding */ +struct jpeg_entropy_decoder { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); + JMETHOD(boolean, decode_mcu, (j_decompress_ptr cinfo, + JBLOCKROW *MCU_data)); + + /* This is here to share code between baseline and progressive decoders; */ + /* other modules probably should not use it */ + boolean insufficient_data; /* set TRUE after emitting warning */ +}; + +/* Inverse DCT (also performs dequantization) */ +typedef JMETHOD(void, inverse_DCT_method_ptr, + (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col)); + +struct jpeg_inverse_dct { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); + /* It is useful to allow each component to have a separate IDCT method. */ + inverse_DCT_method_ptr inverse_DCT[MAX_COMPONENTS]; +}; + +/* Upsampling (note that upsampler must also call color converter) */ +struct jpeg_upsampler { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, upsample, (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, + JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); + + boolean need_context_rows; /* TRUE if need rows above & below */ +}; + +/* Colorspace conversion */ +struct jpeg_color_deconverter { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, color_convert, (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows)); +}; + +/* Color quantization or color precision reduction */ +struct jpeg_color_quantizer { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo, boolean is_pre_scan)); + JMETHOD(void, color_quantize, (j_decompress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPARRAY output_buf, + int num_rows)); + JMETHOD(void, finish_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, new_color_map, (j_decompress_ptr cinfo)); +}; + + +/* Miscellaneous useful macros */ + +#undef MAX +#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#undef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) + + +/* We assume that right shift corresponds to signed division by 2 with + * rounding towards minus infinity. This is correct for typical "arithmetic + * shift" instructions that shift in copies of the sign bit. But some + * C compilers implement >> with an unsigned shift. For these machines you + * must define RIGHT_SHIFT_IS_UNSIGNED. + * RIGHT_SHIFT provides a proper signed right shift of an INT32 quantity. + * It is only applied with constant shift counts. SHIFT_TEMPS must be + * included in the variables of any routine using RIGHT_SHIFT. + */ + +#ifdef RIGHT_SHIFT_IS_UNSIGNED +#define SHIFT_TEMPS INT32 shift_temp; +#define RIGHT_SHIFT(x,shft) \ + ((shift_temp = (x)) < 0 ? \ + (shift_temp >> (shft)) | ((~((INT32) 0)) << (32-(shft))) : \ + (shift_temp >> (shft))) +#else +#define SHIFT_TEMPS +#define RIGHT_SHIFT(x,shft) ((x) >> (shft)) +#endif + + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jinit_compress_master jICompress +#define jinit_c_master_control jICMaster +#define jinit_c_main_controller jICMainC +#define jinit_c_prep_controller jICPrepC +#define jinit_c_coef_controller jICCoefC +#define jinit_color_converter jICColor +#define jinit_downsampler jIDownsampler +#define jinit_forward_dct jIFDCT +#define jinit_huff_encoder jIHEncoder +#define jinit_phuff_encoder jIPHEncoder +#define jinit_marker_writer jIMWriter +#define jinit_master_decompress jIDMaster +#define jinit_d_main_controller jIDMainC +#define jinit_d_coef_controller jIDCoefC +#define jinit_d_post_controller jIDPostC +#define jinit_input_controller jIInCtlr +#define jinit_marker_reader jIMReader +#define jinit_huff_decoder jIHDecoder +#define jinit_phuff_decoder jIPHDecoder +#define jinit_inverse_dct jIIDCT +#define jinit_upsampler jIUpsampler +#define jinit_color_deconverter jIDColor +#define jinit_1pass_quantizer jI1Quant +#define jinit_2pass_quantizer jI2Quant +#define jinit_merged_upsampler jIMUpsampler +#define jinit_memory_mgr jIMemMgr +#define jdiv_round_up jDivRound +#define jround_up jRound +#define jcopy_sample_rows jCopySamples +#define jcopy_block_row jCopyBlocks +#define jzero_far jZeroFar +#define jpeg_zigzag_order jZIGTable +#define jpeg_natural_order jZAGTable +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* Compression module initialization routines */ +EXTERN(void) jinit_compress_master JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_c_master_control JPP((j_compress_ptr cinfo, + boolean transcode_only)); +EXTERN(void) jinit_c_main_controller JPP((j_compress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_c_prep_controller JPP((j_compress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_c_coef_controller JPP((j_compress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_color_converter JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_downsampler JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_forward_dct JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_huff_encoder JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_phuff_encoder JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_marker_writer JPP((j_compress_ptr cinfo)); +/* Decompression module initialization routines */ +EXTERN(void) jinit_master_decompress JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_d_main_controller JPP((j_decompress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_d_coef_controller JPP((j_decompress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_d_post_controller JPP((j_decompress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_input_controller JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_marker_reader JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_huff_decoder JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_phuff_decoder JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_inverse_dct JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_upsampler JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_color_deconverter JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_1pass_quantizer JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_2pass_quantizer JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_merged_upsampler JPP((j_decompress_ptr cinfo)); +/* Memory manager initialization */ +EXTERN(void) jinit_memory_mgr JPP((j_common_ptr cinfo)); + +/* Utility routines in jutils.c */ +EXTERN(long) jdiv_round_up JPP((long a, long b)); +EXTERN(long) jround_up JPP((long a, long b)); +EXTERN(void) jcopy_sample_rows JPP((JSAMPARRAY input_array, int source_row, + JSAMPARRAY output_array, int dest_row, + int num_rows, JDIMENSION num_cols)); +EXTERN(void) jcopy_block_row JPP((JBLOCKROW input_row, JBLOCKROW output_row, + JDIMENSION num_blocks)); +EXTERN(void) jzero_far JPP((void FAR * target, size_t bytestozero)); +/* Constant tables in jutils.c */ +#if 0 /* This table is not actually needed in v6a */ +extern const int jpeg_zigzag_order[]; /* natural coef order to zigzag order */ +#endif +extern const int jpeg_natural_order[]; /* zigzag coef order to natural order */ + +/* Suppress undefined-structure complaints if necessary. */ + +#ifdef INCOMPLETE_TYPES_BROKEN +#ifndef AM_MEMORY_MANAGER /* only jmemmgr.c defines these */ +struct jvirt_sarray_control { long dummy; }; +struct jvirt_barray_control { long dummy; }; +#endif +#endif /* INCOMPLETE_TYPES_BROKEN */ diff --git a/lc-continuity/mk4/modimage/jpeglib.h b/lc-continuity/mk4/modimage/jpeglib.h new file mode 100644 index 0000000000000000000000000000000000000000..d1be8ddeff1bfee59f56d3ea04379f4b6f4d1c0e --- /dev/null +++ b/lc-continuity/mk4/modimage/jpeglib.h @@ -0,0 +1,1096 @@ +/* + * jpeglib.h + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file defines the application interface for the JPEG library. + * Most applications using the library need only include this file, + * and perhaps jerror.h if they want to know the exact error codes. + */ + +#ifndef JPEGLIB_H +#define JPEGLIB_H + +/* + * First we include the configuration files that record how this + * installation of the JPEG library is set up. jconfig.h can be + * generated automatically for many systems. jmorecfg.h contains + * manual configuration options that most people need not worry about. + */ + +#ifndef JCONFIG_INCLUDED /* in case jinclude.h already did */ +#include "jconfig.h" /* widely used configuration options */ +#endif +#include "jmorecfg.h" /* seldom changed options */ + + +/* Version ID for the JPEG library. + * Might be useful for tests like "#if JPEG_LIB_VERSION >= 60". + */ + +#define JPEG_LIB_VERSION 62 /* Version 6b */ + + +/* Various constants determining the sizes of things. + * All of these are specified by the JPEG standard, so don't change them + * if you want to be compatible. + */ + +#define DCTSIZE 8 /* The basic DCT block is 8x8 samples */ +#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */ +#define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */ +#define NUM_HUFF_TBLS 4 /* Huffman tables are numbered 0..3 */ +#define NUM_ARITH_TBLS 16 /* Arith-coding tables are numbered 0..15 */ +#define MAX_COMPS_IN_SCAN 4 /* JPEG limit on # of components in one scan */ +#define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */ +/* Unfortunately, some bozo at Adobe saw no reason to be bound by the standard; + * the PostScript DCT filter can emit files with many more than 10 blocks/MCU. + * If you happen to run across such a file, you can up D_MAX_BLOCKS_IN_MCU + * to handle it. We even let you do this from the jconfig.h file. However, + * we strongly discourage changing C_MAX_BLOCKS_IN_MCU; just because Adobe + * sometimes emits noncompliant files doesn't mean you should too. + */ +#define C_MAX_BLOCKS_IN_MCU 10 /* compressor's limit on blocks per MCU */ +#ifndef D_MAX_BLOCKS_IN_MCU +#define D_MAX_BLOCKS_IN_MCU 10 /* decompressor's limit on blocks per MCU */ +#endif + + +/* Data structures for images (arrays of samples and of DCT coefficients). + * On 80x86 machines, the image arrays are too big for near pointers, + * but the pointer arrays can fit in near memory. + */ + +typedef JSAMPLE FAR *JSAMPROW; /* ptr to one image row of pixel samples. */ +typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */ +typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D sample array: top index is color */ + +typedef JCOEF JBLOCK[DCTSIZE2]; /* one block of coefficients */ +typedef JBLOCK FAR *JBLOCKROW; /* pointer to one row of coefficient blocks */ +typedef JBLOCKROW *JBLOCKARRAY; /* a 2-D array of coefficient blocks */ +typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */ + +typedef JCOEF FAR *JCOEFPTR; /* useful in a couple of places */ + + +/* Types for JPEG compression parameters and working tables. */ + + +/* DCT coefficient quantization tables. */ + +typedef struct { + /* This array gives the coefficient quantizers in natural array order + * (not the zigzag order in which they are stored in a JPEG DQT marker). + * CAUTION: IJG versions prior to v6a kept this array in zigzag order. + */ + UINT16 quantval[DCTSIZE2]; /* quantization step for each coefficient */ + /* This field is used only during compression. It's initialized FALSE when + * the table is created, and set TRUE when it's been output to the file. + * You could suppress output of a table by setting this to TRUE. + * (See jpeg_suppress_tables for an example.) + */ + boolean sent_table; /* TRUE when table has been output */ +} JQUANT_TBL; + + +/* Huffman coding tables. */ + +typedef struct { + /* These two fields directly represent the contents of a JPEG DHT marker */ + UINT8 bits[17]; /* bits[k] = # of symbols with codes of */ + /* length k bits; bits[0] is unused */ + UINT8 huffval[256]; /* The symbols, in order of incr code length */ + /* This field is used only during compression. It's initialized FALSE when + * the table is created, and set TRUE when it's been output to the file. + * You could suppress output of a table by setting this to TRUE. + * (See jpeg_suppress_tables for an example.) + */ + boolean sent_table; /* TRUE when table has been output */ +} JHUFF_TBL; + + +/* Basic info about one component (color channel). */ + +typedef struct { + /* These values are fixed over the whole image. */ + /* For compression, they must be supplied by parameter setup; */ + /* for decompression, they are read from the SOF marker. */ + int component_id; /* identifier for this component (0..255) */ + int component_index; /* its index in SOF or cinfo->comp_info[] */ + int h_samp_factor; /* horizontal sampling factor (1..4) */ + int v_samp_factor; /* vertical sampling factor (1..4) */ + int quant_tbl_no; /* quantization table selector (0..3) */ + /* These values may vary between scans. */ + /* For compression, they must be supplied by parameter setup; */ + /* for decompression, they are read from the SOS marker. */ + /* The decompressor output side may not use these variables. */ + int dc_tbl_no; /* DC entropy table selector (0..3) */ + int ac_tbl_no; /* AC entropy table selector (0..3) */ + + /* Remaining fields should be treated as private by applications. */ + + /* These values are computed during compression or decompression startup: */ + /* Component's size in DCT blocks. + * Any dummy blocks added to complete an MCU are not counted; therefore + * these values do not depend on whether a scan is interleaved or not. + */ + JDIMENSION width_in_blocks; + JDIMENSION height_in_blocks; + /* Size of a DCT block in samples. Always DCTSIZE for compression. + * For decompression this is the size of the output from one DCT block, + * reflecting any scaling we choose to apply during the IDCT step. + * Values of 1,2,4,8 are likely to be supported. Note that different + * components may receive different IDCT scalings. + */ + int DCT_scaled_size; + /* The downsampled dimensions are the component's actual, unpadded number + * of samples at the main buffer (preprocessing/compression interface), thus + * downsampled_width = ceil(image_width * Hi/Hmax) + * and similarly for height. For decompression, IDCT scaling is included, so + * downsampled_width = ceil(image_width * Hi/Hmax * DCT_scaled_size/DCTSIZE) + */ + JDIMENSION downsampled_width; /* actual width in samples */ + JDIMENSION downsampled_height; /* actual height in samples */ + /* This flag is used only for decompression. In cases where some of the + * components will be ignored (eg grayscale output from YCbCr image), + * we can skip most computations for the unused components. + */ + boolean component_needed; /* do we need the value of this component? */ + + /* These values are computed before starting a scan of the component. */ + /* The decompressor output side may not use these variables. */ + int MCU_width; /* number of blocks per MCU, horizontally */ + int MCU_height; /* number of blocks per MCU, vertically */ + int MCU_blocks; /* MCU_width * MCU_height */ + int MCU_sample_width; /* MCU width in samples, MCU_width*DCT_scaled_size */ + int last_col_width; /* # of non-dummy blocks across in last MCU */ + int last_row_height; /* # of non-dummy blocks down in last MCU */ + + /* Saved quantization table for component; NULL if none yet saved. + * See jdinput.c comments about the need for this information. + * This field is currently used only for decompression. + */ + JQUANT_TBL * quant_table; + + /* Private per-component storage for DCT or IDCT subsystem. */ + void * dct_table; +} jpeg_component_info; + + +/* The script for encoding a multiple-scan file is an array of these: */ + +typedef struct { + int comps_in_scan; /* number of components encoded in this scan */ + int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */ + int Ss, Se; /* progressive JPEG spectral selection parms */ + int Ah, Al; /* progressive JPEG successive approx. parms */ +} jpeg_scan_info; + +/* The decompressor can save APPn and COM markers in a list of these: */ + +typedef struct jpeg_marker_struct FAR * jpeg_saved_marker_ptr; + +struct jpeg_marker_struct { + jpeg_saved_marker_ptr next; /* next in list, or NULL */ + UINT8 marker; /* marker code: JPEG_COM, or JPEG_APP0+n */ + unsigned int original_length; /* # bytes of data in the file */ + unsigned int data_length; /* # bytes of data saved at data[] */ + JOCTET FAR * data; /* the data contained in the marker */ + /* the marker length word is not counted in data_length or original_length */ +}; + +/* Known color spaces. */ + +typedef enum { + JCS_UNKNOWN, /* error/unspecified */ + JCS_GRAYSCALE, /* monochrome */ + JCS_RGB, /* red/green/blue */ + JCS_YCbCr, /* Y/Cb/Cr (also known as YUV) */ + JCS_CMYK, /* C/M/Y/K */ + JCS_YCCK /* Y/Cb/Cr/K */ +} J_COLOR_SPACE; + +/* DCT/IDCT algorithm options. */ + +typedef enum { + JDCT_ISLOW, /* slow but accurate integer algorithm */ + JDCT_IFAST, /* faster, less accurate integer method */ + JDCT_FLOAT /* floating-point: accurate, fast on fast HW */ +} J_DCT_METHOD; + +#ifndef JDCT_DEFAULT /* may be overridden in jconfig.h */ +#define JDCT_DEFAULT JDCT_ISLOW +#endif +#ifndef JDCT_FASTEST /* may be overridden in jconfig.h */ +#define JDCT_FASTEST JDCT_IFAST +#endif + +/* Dithering options for decompression. */ + +typedef enum { + JDITHER_NONE, /* no dithering */ + JDITHER_ORDERED, /* simple ordered dither */ + JDITHER_FS /* Floyd-Steinberg error diffusion dither */ +} J_DITHER_MODE; + + +/* Common fields between JPEG compression and decompression master structs. */ + +#define jpeg_common_fields \ + struct jpeg_error_mgr * err; /* Error handler module */\ + struct jpeg_memory_mgr * mem; /* Memory manager module */\ + struct jpeg_progress_mgr * progress; /* Progress monitor, or NULL if none */\ + void * client_data; /* Available for use by application */\ + boolean is_decompressor; /* So common code can tell which is which */\ + int global_state /* For checking call sequence validity */ + +/* Routines that are to be used by both halves of the library are declared + * to receive a pointer to this structure. There are no actual instances of + * jpeg_common_struct, only of jpeg_compress_struct and jpeg_decompress_struct. + */ +struct jpeg_common_struct { + jpeg_common_fields; /* Fields common to both master struct types */ + /* Additional fields follow in an actual jpeg_compress_struct or + * jpeg_decompress_struct. All three structs must agree on these + * initial fields! (This would be a lot cleaner in C++.) + */ +}; + +typedef struct jpeg_common_struct * j_common_ptr; +typedef struct jpeg_compress_struct * j_compress_ptr; +typedef struct jpeg_decompress_struct * j_decompress_ptr; + + +/* Master record for a compression instance */ + +struct jpeg_compress_struct { + jpeg_common_fields; /* Fields shared with jpeg_decompress_struct */ + + /* Destination for compressed data */ + struct jpeg_destination_mgr * dest; + + /* Description of source image --- these fields must be filled in by + * outer application before starting compression. in_color_space must + * be correct before you can even call jpeg_set_defaults(). + */ + + JDIMENSION image_width; /* input image width */ + JDIMENSION image_height; /* input image height */ + int input_components; /* # of color components in input image */ + J_COLOR_SPACE in_color_space; /* colorspace of input image */ + + double input_gamma; /* image gamma of input image */ + + /* Compression parameters --- these fields must be set before calling + * jpeg_start_compress(). We recommend calling jpeg_set_defaults() to + * initialize everything to reasonable defaults, then changing anything + * the application specifically wants to change. That way you won't get + * burnt when new parameters are added. Also note that there are several + * helper routines to simplify changing parameters. + */ + + int data_precision; /* bits of precision in image data */ + + int num_components; /* # of color components in JPEG image */ + J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ + + jpeg_component_info * comp_info; + /* comp_info[i] describes component that appears i'th in SOF */ + + JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; + /* ptrs to coefficient quantization tables, or NULL if not defined */ + + JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; + JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; + /* ptrs to Huffman coding tables, or NULL if not defined */ + + UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ + UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ + UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ + + int num_scans; /* # of entries in scan_info array */ + const jpeg_scan_info * scan_info; /* script for multi-scan file, or NULL */ + /* The default value of scan_info is NULL, which causes a single-scan + * sequential JPEG file to be emitted. To create a multi-scan file, + * set num_scans and scan_info to point to an array of scan definitions. + */ + + boolean raw_data_in; /* TRUE=caller supplies downsampled data */ + boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ + boolean optimize_coding; /* TRUE=optimize entropy encoding parms */ + boolean CCIR601_sampling; /* TRUE=first samples are cosited */ + int smoothing_factor; /* 1..100, or 0 for no input smoothing */ + J_DCT_METHOD dct_method; /* DCT algorithm selector */ + + /* The restart interval can be specified in absolute MCUs by setting + * restart_interval, or in MCU rows by setting restart_in_rows + * (in which case the correct restart_interval will be figured + * for each scan). + */ + unsigned int restart_interval; /* MCUs per restart, or 0 for no restart */ + int restart_in_rows; /* if > 0, MCU rows per restart interval */ + + /* Parameters controlling emission of special markers. */ + + boolean write_JFIF_header; /* should a JFIF marker be written? */ + UINT8 JFIF_major_version; /* What to write for the JFIF version number */ + UINT8 JFIF_minor_version; + /* These three values are not used by the JPEG code, merely copied */ + /* into the JFIF APP0 marker. density_unit can be 0 for unknown, */ + /* 1 for dots/inch, or 2 for dots/cm. Note that the pixel aspect */ + /* ratio is defined by X_density/Y_density even when density_unit=0. */ + UINT8 density_unit; /* JFIF code for pixel size units */ + UINT16 X_density; /* Horizontal pixel density */ + UINT16 Y_density; /* Vertical pixel density */ + boolean write_Adobe_marker; /* should an Adobe marker be written? */ + + /* State variable: index of next scanline to be written to + * jpeg_write_scanlines(). Application may use this to control its + * processing loop, e.g., "while (next_scanline < image_height)". + */ + + JDIMENSION next_scanline; /* 0 .. image_height-1 */ + + /* Remaining fields are known throughout compressor, but generally + * should not be touched by a surrounding application. + */ + + /* + * These fields are computed during compression startup + */ + boolean progressive_mode; /* TRUE if scan script uses progressive mode */ + int max_h_samp_factor; /* largest h_samp_factor */ + int max_v_samp_factor; /* largest v_samp_factor */ + + JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to coef ctlr */ + /* The coefficient controller receives data in units of MCU rows as defined + * for fully interleaved scans (whether the JPEG file is interleaved or not). + * There are v_samp_factor * DCTSIZE sample rows of each component in an + * "iMCU" (interleaved MCU) row. + */ + + /* + * These fields are valid during any one scan. + * They describe the components and MCUs actually appearing in the scan. + */ + int comps_in_scan; /* # of JPEG components in this scan */ + jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; + /* *cur_comp_info[i] describes component that appears i'th in SOS */ + + JDIMENSION MCUs_per_row; /* # of MCUs across the image */ + JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ + + int blocks_in_MCU; /* # of DCT blocks per MCU */ + int MCU_membership[C_MAX_BLOCKS_IN_MCU]; + /* MCU_membership[i] is index in cur_comp_info of component owning */ + /* i'th block in an MCU */ + + int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ + + /* + * Links to compression subobjects (methods and private variables of modules) + */ + struct jpeg_comp_master * master; + struct jpeg_c_main_controller * main; + struct jpeg_c_prep_controller * prep; + struct jpeg_c_coef_controller * coef; + struct jpeg_marker_writer * marker; + struct jpeg_color_converter * cconvert; + struct jpeg_downsampler * downsample; + struct jpeg_forward_dct * fdct; + struct jpeg_entropy_encoder * entropy; + jpeg_scan_info * script_space; /* workspace for jpeg_simple_progression */ + int script_space_size; +}; + + +/* Master record for a decompression instance */ + +struct jpeg_decompress_struct { + jpeg_common_fields; /* Fields shared with jpeg_compress_struct */ + + /* Source of compressed data */ + struct jpeg_source_mgr * src; + + /* Basic description of image --- filled in by jpeg_read_header(). */ + /* Application may inspect these values to decide how to process image. */ + + JDIMENSION image_width; /* nominal image width (from SOF marker) */ + JDIMENSION image_height; /* nominal image height */ + int num_components; /* # of color components in JPEG image */ + J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ + + /* Decompression processing parameters --- these fields must be set before + * calling jpeg_start_decompress(). Note that jpeg_read_header() initializes + * them to default values. + */ + + J_COLOR_SPACE out_color_space; /* colorspace for output */ + + unsigned int scale_num, scale_denom; /* fraction by which to scale image */ + + double output_gamma; /* image gamma wanted in output */ + + boolean buffered_image; /* TRUE=multiple output passes */ + boolean raw_data_out; /* TRUE=downsampled data wanted */ + + J_DCT_METHOD dct_method; /* IDCT algorithm selector */ + boolean do_fancy_upsampling; /* TRUE=apply fancy upsampling */ + boolean do_block_smoothing; /* TRUE=apply interblock smoothing */ + + boolean quantize_colors; /* TRUE=colormapped output wanted */ + /* the following are ignored if not quantize_colors: */ + J_DITHER_MODE dither_mode; /* type of color dithering to use */ + boolean two_pass_quantize; /* TRUE=use two-pass color quantization */ + int desired_number_of_colors; /* max # colors to use in created colormap */ + /* these are significant only in buffered-image mode: */ + boolean enable_1pass_quant; /* enable future use of 1-pass quantizer */ + boolean enable_external_quant;/* enable future use of external colormap */ + boolean enable_2pass_quant; /* enable future use of 2-pass quantizer */ + + /* Description of actual output image that will be returned to application. + * These fields are computed by jpeg_start_decompress(). + * You can also use jpeg_calc_output_dimensions() to determine these values + * in advance of calling jpeg_start_decompress(). + */ + + JDIMENSION output_width; /* scaled image width */ + JDIMENSION output_height; /* scaled image height */ + int out_color_components; /* # of color components in out_color_space */ + int output_components; /* # of color components returned */ + /* output_components is 1 (a colormap index) when quantizing colors; + * otherwise it equals out_color_components. + */ + int rec_outbuf_height; /* min recommended height of scanline buffer */ + /* If the buffer passed to jpeg_read_scanlines() is less than this many rows + * high, space and time will be wasted due to unnecessary data copying. + * Usually rec_outbuf_height will be 1 or 2, at most 4. + */ + + /* When quantizing colors, the output colormap is described by these fields. + * The application can supply a colormap by setting colormap non-NULL before + * calling jpeg_start_decompress; otherwise a colormap is created during + * jpeg_start_decompress or jpeg_start_output. + * The map has out_color_components rows and actual_number_of_colors columns. + */ + int actual_number_of_colors; /* number of entries in use */ + JSAMPARRAY colormap; /* The color map as a 2-D pixel array */ + + /* State variables: these variables indicate the progress of decompression. + * The application may examine these but must not modify them. + */ + + /* Row index of next scanline to be read from jpeg_read_scanlines(). + * Application may use this to control its processing loop, e.g., + * "while (output_scanline < output_height)". + */ + JDIMENSION output_scanline; /* 0 .. output_height-1 */ + + /* Current input scan number and number of iMCU rows completed in scan. + * These indicate the progress of the decompressor input side. + */ + int input_scan_number; /* Number of SOS markers seen so far */ + JDIMENSION input_iMCU_row; /* Number of iMCU rows completed */ + + /* The "output scan number" is the notional scan being displayed by the + * output side. The decompressor will not allow output scan/row number + * to get ahead of input scan/row, but it can fall arbitrarily far behind. + */ + int output_scan_number; /* Nominal scan number being displayed */ + JDIMENSION output_iMCU_row; /* Number of iMCU rows read */ + + /* Current progression status. coef_bits[c][i] indicates the precision + * with which component c's DCT coefficient i (in zigzag order) is known. + * It is -1 when no data has yet been received, otherwise it is the point + * transform (shift) value for the most recent scan of the coefficient + * (thus, 0 at completion of the progression). + * This pointer is NULL when reading a non-progressive file. + */ + int (*coef_bits)[DCTSIZE2]; /* -1 or current Al value for each coef */ + + /* Internal JPEG parameters --- the application usually need not look at + * these fields. Note that the decompressor output side may not use + * any parameters that can change between scans. + */ + + /* Quantization and Huffman tables are carried forward across input + * datastreams when processing abbreviated JPEG datastreams. + */ + + JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; + /* ptrs to coefficient quantization tables, or NULL if not defined */ + + JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; + JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; + /* ptrs to Huffman coding tables, or NULL if not defined */ + + /* These parameters are never carried across datastreams, since they + * are given in SOF/SOS markers or defined to be reset by SOI. + */ + + int data_precision; /* bits of precision in image data */ + + jpeg_component_info * comp_info; + /* comp_info[i] describes component that appears i'th in SOF */ + + boolean progressive_mode; /* TRUE if SOFn specifies progressive mode */ + boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ + + UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ + UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ + UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ + + unsigned int restart_interval; /* MCUs per restart interval, or 0 for no restart */ + + /* These fields record data obtained from optional markers recognized by + * the JPEG library. + */ + boolean saw_JFIF_marker; /* TRUE iff a JFIF APP0 marker was found */ + /* Data copied from JFIF marker; only valid if saw_JFIF_marker is TRUE: */ + UINT8 JFIF_major_version; /* JFIF version number */ + UINT8 JFIF_minor_version; + UINT8 density_unit; /* JFIF code for pixel size units */ + UINT16 X_density; /* Horizontal pixel density */ + UINT16 Y_density; /* Vertical pixel density */ + boolean saw_Adobe_marker; /* TRUE iff an Adobe APP14 marker was found */ + UINT8 Adobe_transform; /* Color transform code from Adobe marker */ + + boolean CCIR601_sampling; /* TRUE=first samples are cosited */ + + /* Aside from the specific data retained from APPn markers known to the + * library, the uninterpreted contents of any or all APPn and COM markers + * can be saved in a list for examination by the application. + */ + jpeg_saved_marker_ptr marker_list; /* Head of list of saved markers */ + + /* Remaining fields are known throughout decompressor, but generally + * should not be touched by a surrounding application. + */ + + /* + * These fields are computed during decompression startup + */ + int max_h_samp_factor; /* largest h_samp_factor */ + int max_v_samp_factor; /* largest v_samp_factor */ + + int min_DCT_scaled_size; /* smallest DCT_scaled_size of any component */ + + JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */ + /* The coefficient controller's input and output progress is measured in + * units of "iMCU" (interleaved MCU) rows. These are the same as MCU rows + * in fully interleaved JPEG scans, but are used whether the scan is + * interleaved or not. We define an iMCU row as v_samp_factor DCT block + * rows of each component. Therefore, the IDCT output contains + * v_samp_factor*DCT_scaled_size sample rows of a component per iMCU row. + */ + + JSAMPLE * sample_range_limit; /* table for fast range-limiting */ + + /* + * These fields are valid during any one scan. + * They describe the components and MCUs actually appearing in the scan. + * Note that the decompressor output side must not use these fields. + */ + int comps_in_scan; /* # of JPEG components in this scan */ + jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; + /* *cur_comp_info[i] describes component that appears i'th in SOS */ + + JDIMENSION MCUs_per_row; /* # of MCUs across the image */ + JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ + + int blocks_in_MCU; /* # of DCT blocks per MCU */ + int MCU_membership[D_MAX_BLOCKS_IN_MCU]; + /* MCU_membership[i] is index in cur_comp_info of component owning */ + /* i'th block in an MCU */ + + int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ + + /* This field is shared between entropy decoder and marker parser. + * It is either zero or the code of a JPEG marker that has been + * read from the data source, but has not yet been processed. + */ + int unread_marker; + + /* + * Links to decompression subobjects (methods, private variables of modules) + */ + struct jpeg_decomp_master * master; + struct jpeg_d_main_controller * main; + struct jpeg_d_coef_controller * coef; + struct jpeg_d_post_controller * post; + struct jpeg_input_controller * inputctl; + struct jpeg_marker_reader * marker; + struct jpeg_entropy_decoder * entropy; + struct jpeg_inverse_dct * idct; + struct jpeg_upsampler * upsample; + struct jpeg_color_deconverter * cconvert; + struct jpeg_color_quantizer * cquantize; +}; + + +/* "Object" declarations for JPEG modules that may be supplied or called + * directly by the surrounding application. + * As with all objects in the JPEG library, these structs only define the + * publicly visible methods and state variables of a module. Additional + * private fields may exist after the public ones. + */ + + +/* Error handler object */ + +struct jpeg_error_mgr { + /* Error exit handler: does not return to caller */ + JMETHOD(void, error_exit, (j_common_ptr cinfo)); + /* Conditionally emit a trace or warning message */ + JMETHOD(void, emit_message, (j_common_ptr cinfo, int msg_level)); + /* Routine that actually outputs a trace or error message */ + JMETHOD(void, output_message, (j_common_ptr cinfo)); + /* Format a message string for the most recent JPEG error or message */ + JMETHOD(void, format_message, (j_common_ptr cinfo, char * buffer)); +#define JMSG_LENGTH_MAX 200 /* recommended size of format_message buffer */ + /* Reset error state variables at start of a new image */ + JMETHOD(void, reset_error_mgr, (j_common_ptr cinfo)); + + /* The message ID code and any parameters are saved here. + * A message can have one string parameter or up to 8 int parameters. + */ + int msg_code; +#define JMSG_STR_PARM_MAX 80 + union { + int i[8]; + char s[JMSG_STR_PARM_MAX]; + } msg_parm; + + /* Standard state variables for error facility */ + + int trace_level; /* max msg_level that will be displayed */ + + /* For recoverable corrupt-data errors, we emit a warning message, + * but keep going unless emit_message chooses to abort. emit_message + * should count warnings in num_warnings. The surrounding application + * can check for bad data by seeing if num_warnings is nonzero at the + * end of processing. + */ + long num_warnings; /* number of corrupt-data warnings */ + + /* These fields point to the table(s) of error message strings. + * An application can change the table pointer to switch to a different + * message list (typically, to change the language in which errors are + * reported). Some applications may wish to add additional error codes + * that will be handled by the JPEG library error mechanism; the second + * table pointer is used for this purpose. + * + * First table includes all errors generated by JPEG library itself. + * Error code 0 is reserved for a "no such error string" message. + */ + const char * const * jpeg_message_table; /* Library errors */ + int last_jpeg_message; /* Table contains strings 0..last_jpeg_message */ + /* Second table can be added by application (see cjpeg/djpeg for example). + * It contains strings numbered first_addon_message..last_addon_message. + */ + const char * const * addon_message_table; /* Non-library errors */ + int first_addon_message; /* code for first string in addon table */ + int last_addon_message; /* code for last string in addon table */ +}; + + +/* Progress monitor object */ + +struct jpeg_progress_mgr { + JMETHOD(void, progress_monitor, (j_common_ptr cinfo)); + + long pass_counter; /* work units completed in this pass */ + long pass_limit; /* total number of work units in this pass */ + int completed_passes; /* passes completed so far */ + int total_passes; /* total number of passes expected */ +}; + + +/* Data destination object for compression */ + +struct jpeg_destination_mgr { + JOCTET * next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + + JMETHOD(void, init_destination, (j_compress_ptr cinfo)); + JMETHOD(boolean, empty_output_buffer, (j_compress_ptr cinfo)); + JMETHOD(void, term_destination, (j_compress_ptr cinfo)); +}; + + +/* Data source object for decompression */ + +struct jpeg_source_mgr { + const JOCTET * next_input_byte; /* => next byte to read from buffer */ + size_t bytes_in_buffer; /* # of bytes remaining in buffer */ + + JMETHOD(void, init_source, (j_decompress_ptr cinfo)); + JMETHOD(boolean, fill_input_buffer, (j_decompress_ptr cinfo)); + JMETHOD(void, skip_input_data, (j_decompress_ptr cinfo, long num_bytes)); + JMETHOD(boolean, resync_to_restart, (j_decompress_ptr cinfo, int desired)); + JMETHOD(void, term_source, (j_decompress_ptr cinfo)); +}; + + +/* Memory manager object. + * Allocates "small" objects (a few K total), "large" objects (tens of K), + * and "really big" objects (virtual arrays with backing store if needed). + * The memory manager does not allow individual objects to be freed; rather, + * each created object is assigned to a pool, and whole pools can be freed + * at once. This is faster and more convenient than remembering exactly what + * to free, especially where malloc()/free() are not too speedy. + * NB: alloc routines never return NULL. They exit to error_exit if not + * successful. + */ + +#define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */ +#define JPOOL_IMAGE 1 /* lasts until done with image/datastream */ +#define JPOOL_NUMPOOLS 2 + +typedef struct jvirt_sarray_control * jvirt_sarray_ptr; +typedef struct jvirt_barray_control * jvirt_barray_ptr; + + +struct jpeg_memory_mgr { + /* Method pointers */ + JMETHOD(void *, alloc_small, (j_common_ptr cinfo, int pool_id, + size_t sizeofobject)); + JMETHOD(void FAR *, alloc_large, (j_common_ptr cinfo, int pool_id, + size_t sizeofobject)); + JMETHOD(JSAMPARRAY, alloc_sarray, (j_common_ptr cinfo, int pool_id, + JDIMENSION samplesperrow, + JDIMENSION numrows)); + JMETHOD(JBLOCKARRAY, alloc_barray, (j_common_ptr cinfo, int pool_id, + JDIMENSION blocksperrow, + JDIMENSION numrows)); + JMETHOD(jvirt_sarray_ptr, request_virt_sarray, (j_common_ptr cinfo, + int pool_id, + boolean pre_zero, + JDIMENSION samplesperrow, + JDIMENSION numrows, + JDIMENSION maxaccess)); + JMETHOD(jvirt_barray_ptr, request_virt_barray, (j_common_ptr cinfo, + int pool_id, + boolean pre_zero, + JDIMENSION blocksperrow, + JDIMENSION numrows, + JDIMENSION maxaccess)); + JMETHOD(void, realize_virt_arrays, (j_common_ptr cinfo)); + JMETHOD(JSAMPARRAY, access_virt_sarray, (j_common_ptr cinfo, + jvirt_sarray_ptr ptr, + JDIMENSION start_row, + JDIMENSION num_rows, + boolean writable)); + JMETHOD(JBLOCKARRAY, access_virt_barray, (j_common_ptr cinfo, + jvirt_barray_ptr ptr, + JDIMENSION start_row, + JDIMENSION num_rows, + boolean writable)); + JMETHOD(void, free_pool, (j_common_ptr cinfo, int pool_id)); + JMETHOD(void, self_destruct, (j_common_ptr cinfo)); + + /* Limit on memory allocation for this JPEG object. (Note that this is + * merely advisory, not a guaranteed maximum; it only affects the space + * used for virtual-array buffers.) May be changed by outer application + * after creating the JPEG object. + */ + long max_memory_to_use; + + /* Maximum allocation request accepted by alloc_large. */ + long max_alloc_chunk; +}; + + +/* Routine signature for application-supplied marker processing methods. + * Need not pass marker code since it is stored in cinfo->unread_marker. + */ +typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo)); + + +/* Declarations for routines called by application. + * The JPP macro hides prototype parameters from compilers that can't cope. + * Note JPP requires double parentheses. + */ + +#ifdef HAVE_PROTOTYPES +#define JPP(arglist) arglist +#else +#define JPP(arglist) () +#endif + + +/* Short forms of external names for systems with brain-damaged linkers. + * We shorten external names to be unique in the first six letters, which + * is good enough for all known systems. + * (If your compiler itself needs names to be unique in less than 15 + * characters, you are out of luck. Get a better compiler.) + */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_std_error jStdError +#define jpeg_CreateCompress jCreaCompress +#define jpeg_CreateDecompress jCreaDecompress +#define jpeg_destroy_compress jDestCompress +#define jpeg_destroy_decompress jDestDecompress +#define jpeg_stdio_dest jStdDest +#define jpeg_stdio_src jStdSrc +#define jpeg_set_defaults jSetDefaults +#define jpeg_set_colorspace jSetColorspace +#define jpeg_default_colorspace jDefColorspace +#define jpeg_set_quality jSetQuality +#define jpeg_set_linear_quality jSetLQuality +#define jpeg_add_quant_table jAddQuantTable +#define jpeg_quality_scaling jQualityScaling +#define jpeg_simple_progression jSimProgress +#define jpeg_suppress_tables jSuppressTables +#define jpeg_alloc_quant_table jAlcQTable +#define jpeg_alloc_huff_table jAlcHTable +#define jpeg_start_compress jStrtCompress +#define jpeg_write_scanlines jWrtScanlines +#define jpeg_finish_compress jFinCompress +#define jpeg_write_raw_data jWrtRawData +#define jpeg_write_marker jWrtMarker +#define jpeg_write_m_header jWrtMHeader +#define jpeg_write_m_byte jWrtMByte +#define jpeg_write_tables jWrtTables +#define jpeg_read_header jReadHeader +#define jpeg_start_decompress jStrtDecompress +#define jpeg_read_scanlines jReadScanlines +#define jpeg_finish_decompress jFinDecompress +#define jpeg_read_raw_data jReadRawData +#define jpeg_has_multiple_scans jHasMultScn +#define jpeg_start_output jStrtOutput +#define jpeg_finish_output jFinOutput +#define jpeg_input_complete jInComplete +#define jpeg_new_colormap jNewCMap +#define jpeg_consume_input jConsumeInput +#define jpeg_calc_output_dimensions jCalcDimensions +#define jpeg_save_markers jSaveMarkers +#define jpeg_set_marker_processor jSetMarker +#define jpeg_read_coefficients jReadCoefs +#define jpeg_write_coefficients jWrtCoefs +#define jpeg_copy_critical_parameters jCopyCrit +#define jpeg_abort_compress jAbrtCompress +#define jpeg_abort_decompress jAbrtDecompress +#define jpeg_abort jAbort +#define jpeg_destroy jDestroy +#define jpeg_resync_to_restart jResyncRestart +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* Default error-management setup */ +EXTERN(struct jpeg_error_mgr *) jpeg_std_error + JPP((struct jpeg_error_mgr * err)); + +/* Initialization of JPEG compression objects. + * jpeg_create_compress() and jpeg_create_decompress() are the exported + * names that applications should call. These expand to calls on + * jpeg_CreateCompress and jpeg_CreateDecompress with additional information + * passed for version mismatch checking. + * NB: you must set up the error-manager BEFORE calling jpeg_create_xxx. + */ +#define jpeg_create_compress(cinfo) \ + jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \ + (size_t) sizeof(struct jpeg_compress_struct)) +#define jpeg_create_decompress(cinfo) \ + jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \ + (size_t) sizeof(struct jpeg_decompress_struct)) +EXTERN(void) jpeg_CreateCompress JPP((j_compress_ptr cinfo, + int version, size_t structsize)); +EXTERN(void) jpeg_CreateDecompress JPP((j_decompress_ptr cinfo, + int version, size_t structsize)); +/* Destruction of JPEG compression objects */ +EXTERN(void) jpeg_destroy_compress JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_destroy_decompress JPP((j_decompress_ptr cinfo)); + +/* Standard data source and destination managers: stdio streams. */ +/* Caller is responsible for opening the file before and closing after. */ +EXTERN(void) jpeg_stdio_dest JPP((j_compress_ptr cinfo, FILE * outfile)); +EXTERN(void) jpeg_stdio_src JPP((j_decompress_ptr cinfo, FILE * infile)); + +/* Default parameter setup for compression */ +EXTERN(void) jpeg_set_defaults JPP((j_compress_ptr cinfo)); +/* Compression parameter setup aids */ +EXTERN(void) jpeg_set_colorspace JPP((j_compress_ptr cinfo, + J_COLOR_SPACE colorspace)); +EXTERN(void) jpeg_default_colorspace JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_set_quality JPP((j_compress_ptr cinfo, int quality, + boolean force_baseline)); +EXTERN(void) jpeg_set_linear_quality JPP((j_compress_ptr cinfo, + int scale_factor, + boolean force_baseline)); +EXTERN(void) jpeg_add_quant_table JPP((j_compress_ptr cinfo, int which_tbl, + const unsigned int *basic_table, + int scale_factor, + boolean force_baseline)); +EXTERN(int) jpeg_quality_scaling JPP((int quality)); +EXTERN(void) jpeg_simple_progression JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_suppress_tables JPP((j_compress_ptr cinfo, + boolean suppress)); +EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table JPP((j_common_ptr cinfo)); +EXTERN(JHUFF_TBL *) jpeg_alloc_huff_table JPP((j_common_ptr cinfo)); + +/* Main entry points for compression */ +EXTERN(void) jpeg_start_compress JPP((j_compress_ptr cinfo, + boolean write_all_tables)); +EXTERN(JDIMENSION) jpeg_write_scanlines JPP((j_compress_ptr cinfo, + JSAMPARRAY scanlines, + JDIMENSION num_lines)); +EXTERN(void) jpeg_finish_compress JPP((j_compress_ptr cinfo)); + +/* Replaces jpeg_write_scanlines when writing raw downsampled data. */ +EXTERN(JDIMENSION) jpeg_write_raw_data JPP((j_compress_ptr cinfo, + JSAMPIMAGE data, + JDIMENSION num_lines)); + +/* Write a special marker. See libjpeg.doc concerning safe usage. */ +EXTERN(void) jpeg_write_marker + JPP((j_compress_ptr cinfo, int marker, + const JOCTET * dataptr, unsigned int datalen)); +/* Same, but piecemeal. */ +EXTERN(void) jpeg_write_m_header + JPP((j_compress_ptr cinfo, int marker, unsigned int datalen)); +EXTERN(void) jpeg_write_m_byte + JPP((j_compress_ptr cinfo, int val)); + +/* Alternate compression function: just write an abbreviated table file */ +EXTERN(void) jpeg_write_tables JPP((j_compress_ptr cinfo)); + +/* Decompression startup: read start of JPEG datastream to see what's there */ +EXTERN(int) jpeg_read_header JPP((j_decompress_ptr cinfo, + boolean require_image)); +/* Return value is one of: */ +#define JPEG_SUSPENDED 0 /* Suspended due to lack of input data */ +#define JPEG_HEADER_OK 1 /* Found valid image datastream */ +#define JPEG_HEADER_TABLES_ONLY 2 /* Found valid table-specs-only datastream */ +/* If you pass require_image = TRUE (normal case), you need not check for + * a TABLES_ONLY return code; an abbreviated file will cause an error exit. + * JPEG_SUSPENDED is only possible if you use a data source module that can + * give a suspension return (the stdio source module doesn't). + */ + +/* Main entry points for decompression */ +EXTERN(boolean) jpeg_start_decompress JPP((j_decompress_ptr cinfo)); +EXTERN(JDIMENSION) jpeg_read_scanlines JPP((j_decompress_ptr cinfo, + JSAMPARRAY scanlines, + JDIMENSION max_lines)); +EXTERN(boolean) jpeg_finish_decompress JPP((j_decompress_ptr cinfo)); + +/* Replaces jpeg_read_scanlines when reading raw downsampled data. */ +EXTERN(JDIMENSION) jpeg_read_raw_data JPP((j_decompress_ptr cinfo, + JSAMPIMAGE data, + JDIMENSION max_lines)); + +/* Additional entry points for buffered-image mode. */ +EXTERN(boolean) jpeg_has_multiple_scans JPP((j_decompress_ptr cinfo)); +EXTERN(boolean) jpeg_start_output JPP((j_decompress_ptr cinfo, + int scan_number)); +EXTERN(boolean) jpeg_finish_output JPP((j_decompress_ptr cinfo)); +EXTERN(boolean) jpeg_input_complete JPP((j_decompress_ptr cinfo)); +EXTERN(void) jpeg_new_colormap JPP((j_decompress_ptr cinfo)); +EXTERN(int) jpeg_consume_input JPP((j_decompress_ptr cinfo)); +/* Return value is one of: */ +/* #define JPEG_SUSPENDED 0 Suspended due to lack of input data */ +#define JPEG_REACHED_SOS 1 /* Reached start of new scan */ +#define JPEG_REACHED_EOI 2 /* Reached end of image */ +#define JPEG_ROW_COMPLETED 3 /* Completed one iMCU row */ +#define JPEG_SCAN_COMPLETED 4 /* Completed last iMCU row of a scan */ + +/* Precalculate output dimensions for current decompression parameters. */ +EXTERN(void) jpeg_calc_output_dimensions JPP((j_decompress_ptr cinfo)); + +/* Control saving of COM and APPn markers into marker_list. */ +EXTERN(void) jpeg_save_markers + JPP((j_decompress_ptr cinfo, int marker_code, + unsigned int length_limit)); + +/* Install a special processing method for COM or APPn markers. */ +EXTERN(void) jpeg_set_marker_processor + JPP((j_decompress_ptr cinfo, int marker_code, + jpeg_marker_parser_method routine)); + +/* Read or write raw DCT coefficients --- useful for lossless transcoding. */ +EXTERN(jvirt_barray_ptr *) jpeg_read_coefficients JPP((j_decompress_ptr cinfo)); +EXTERN(void) jpeg_write_coefficients JPP((j_compress_ptr cinfo, + jvirt_barray_ptr * coef_arrays)); +EXTERN(void) jpeg_copy_critical_parameters JPP((j_decompress_ptr srcinfo, + j_compress_ptr dstinfo)); + +/* If you choose to abort compression or decompression before completing + * jpeg_finish_(de)compress, then you need to clean up to release memory, + * temporary files, etc. You can just call jpeg_destroy_(de)compress + * if you're done with the JPEG object, but if you want to clean it up and + * reuse it, call this: + */ +EXTERN(void) jpeg_abort_compress JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_abort_decompress JPP((j_decompress_ptr cinfo)); + +/* Generic versions of jpeg_abort and jpeg_destroy that work on either + * flavor of JPEG object. These may be more convenient in some places. + */ +EXTERN(void) jpeg_abort JPP((j_common_ptr cinfo)); +EXTERN(void) jpeg_destroy JPP((j_common_ptr cinfo)); + +/* Default restart-marker-resync procedure for use by data source modules */ +EXTERN(boolean) jpeg_resync_to_restart JPP((j_decompress_ptr cinfo, + int desired)); + + +/* These marker codes are exported since applications and data source modules + * are likely to want to use them. + */ + +#define JPEG_RST0 0xD0 /* RST0 marker code */ +#define JPEG_EOI 0xD9 /* EOI marker code */ +#define JPEG_APP0 0xE0 /* APP0 marker code */ +#define JPEG_COM 0xFE /* COM marker code */ + + +/* If we have a brain-damaged compiler that emits warnings (or worse, errors) + * for structure definitions that are never filled in, keep it quiet by + * supplying dummy definitions for the various substructures. + */ + +#ifdef INCOMPLETE_TYPES_BROKEN +#ifndef JPEG_INTERNALS /* will be defined in jpegint.h */ +struct jvirt_sarray_control { long dummy; }; +struct jvirt_barray_control { long dummy; }; +struct jpeg_comp_master { long dummy; }; +struct jpeg_c_main_controller { long dummy; }; +struct jpeg_c_prep_controller { long dummy; }; +struct jpeg_c_coef_controller { long dummy; }; +struct jpeg_marker_writer { long dummy; }; +struct jpeg_color_converter { long dummy; }; +struct jpeg_downsampler { long dummy; }; +struct jpeg_forward_dct { long dummy; }; +struct jpeg_entropy_encoder { long dummy; }; +struct jpeg_decomp_master { long dummy; }; +struct jpeg_d_main_controller { long dummy; }; +struct jpeg_d_coef_controller { long dummy; }; +struct jpeg_d_post_controller { long dummy; }; +struct jpeg_input_controller { long dummy; }; +struct jpeg_marker_reader { long dummy; }; +struct jpeg_entropy_decoder { long dummy; }; +struct jpeg_inverse_dct { long dummy; }; +struct jpeg_upsampler { long dummy; }; +struct jpeg_color_deconverter { long dummy; }; +struct jpeg_color_quantizer { long dummy; }; +#endif /* JPEG_INTERNALS */ +#endif /* INCOMPLETE_TYPES_BROKEN */ + + +/* + * The JPEG library modules define JPEG_INTERNALS before including this file. + * The internal structure declarations are read only when that is true. + * Applications using the library should not include jpegint.h, but may wish + * to include jerror.h. + */ + +#ifdef JPEG_INTERNALS +#include "jpegint.h" /* fetch private declarations */ +#include "jerror.h" /* fetch error codes too */ +#endif + +#endif /* JPEGLIB_H */ diff --git a/lc-continuity/mk4/modimage/jversion.h b/lc-continuity/mk4/modimage/jversion.h new file mode 100644 index 0000000000000000000000000000000000000000..6472c58d351ac6a286443f692a8ec07a4a752877 --- /dev/null +++ b/lc-continuity/mk4/modimage/jversion.h @@ -0,0 +1,14 @@ +/* + * jversion.h + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains software version identification. + */ + + +#define JVERSION "6b 27-Mar-1998" + +#define JCOPYRIGHT "Copyright (C) 1998, Thomas G. Lane" diff --git a/lc-continuity/mk4/modimage/transupp.h b/lc-continuity/mk4/modimage/transupp.h new file mode 100644 index 0000000000000000000000000000000000000000..5c2d32aff50122873e78f5f3030d7135e257073a --- /dev/null +++ b/lc-continuity/mk4/modimage/transupp.h @@ -0,0 +1,135 @@ +/* + * transupp.h + * + * Copyright (C) 1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains declarations for image transformation routines and + * other utility code used by the jpegtran sample application. These are + * NOT part of the core JPEG library. But we keep these routines separate + * from jpegtran.c to ease the task of maintaining jpegtran-like programs + * that have other user interfaces. + * + * NOTE: all the routines declared here have very specific requirements + * about when they are to be executed during the reading and writing of the + * source and destination files. See the comments in transupp.c, or see + * jpegtran.c for an example of correct usage. + */ + +/* If you happen not to want the image transform support, disable it here */ +#ifndef TRANSFORMS_SUPPORTED +#define TRANSFORMS_SUPPORTED 1 /* 0 disables transform code */ +#endif + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jtransform_request_workspace jTrRequest +#define jtransform_adjust_parameters jTrAdjust +#define jtransform_execute_transformation jTrExec +#define jcopy_markers_setup jCMrkSetup +#define jcopy_markers_execute jCMrkExec +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* + * Codes for supported types of image transformations. + */ + +typedef enum { + JXFORM_NONE, /* no transformation */ + JXFORM_FLIP_H, /* horizontal flip */ + JXFORM_FLIP_V, /* vertical flip */ + JXFORM_TRANSPOSE, /* transpose across UL-to-LR axis */ + JXFORM_TRANSVERSE, /* transpose across UR-to-LL axis */ + JXFORM_ROT_90, /* 90-degree clockwise rotation */ + JXFORM_ROT_180, /* 180-degree rotation */ + JXFORM_ROT_270 /* 270-degree clockwise (or 90 ccw) */ +} JXFORM_CODE; + +/* + * Although rotating and flipping data expressed as DCT coefficients is not + * hard, there is an asymmetry in the JPEG format specification for images + * whose dimensions aren't multiples of the iMCU size. The right and bottom + * image edges are padded out to the next iMCU boundary with junk data; but + * no padding is possible at the top and left edges. If we were to flip + * the whole image including the pad data, then pad garbage would become + * visible at the top and/or left, and real pixels would disappear into the + * pad margins --- perhaps permanently, since encoders & decoders may not + * bother to preserve DCT blocks that appear to be completely outside the + * nominal image area. So, we have to exclude any partial iMCUs from the + * basic transformation. + * + * Transpose is the only transformation that can handle partial iMCUs at the + * right and bottom edges completely cleanly. flip_h can flip partial iMCUs + * at the bottom, but leaves any partial iMCUs at the right edge untouched. + * Similarly flip_v leaves any partial iMCUs at the bottom edge untouched. + * The other transforms are defined as combinations of these basic transforms + * and process edge blocks in a way that preserves the equivalence. + * + * The "trim" option causes untransformable partial iMCUs to be dropped; + * this is not strictly lossless, but it usually gives the best-looking + * result for odd-size images. Note that when this option is active, + * the expected mathematical equivalences between the transforms may not hold. + * (For example, -rot 270 -trim trims only the bottom edge, but -rot 90 -trim + * followed by -rot 180 -trim trims both edges.) + * + * We also offer a "force to grayscale" option, which simply discards the + * chrominance channels of a YCbCr image. This is lossless in the sense that + * the luminance channel is preserved exactly. It's not the same kind of + * thing as the rotate/flip transformations, but it's convenient to handle it + * as part of this package, mainly because the transformation routines have to + * be aware of the option to know how many components to work on. + */ + +typedef struct { + /* Options: set by caller */ + JXFORM_CODE transform; /* image transform operator */ + boolean trim; /* if TRUE, trim partial MCUs as needed */ + boolean force_grayscale; /* if TRUE, convert color image to grayscale */ + + /* Internal workspace: caller should not touch these */ + int num_components; /* # of components in workspace */ + jvirt_barray_ptr * workspace_coef_arrays; /* workspace for transformations */ +} jpeg_transform_info; + + +#if TRANSFORMS_SUPPORTED + +/* Request any required workspace */ +EXTERN(void) jtransform_request_workspace + JPP((j_decompress_ptr srcinfo, jpeg_transform_info *info)); +/* Adjust output image parameters */ +EXTERN(jvirt_barray_ptr *) jtransform_adjust_parameters + JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + jvirt_barray_ptr *src_coef_arrays, + jpeg_transform_info *info)); +/* Execute the actual transformation, if any */ +EXTERN(void) jtransform_execute_transformation + JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + jvirt_barray_ptr *src_coef_arrays, + jpeg_transform_info *info)); + +#endif /* TRANSFORMS_SUPPORTED */ + + +/* + * Support for copying optional markers from source to destination file. + */ + +typedef enum { + JCOPYOPT_NONE, /* copy no optional markers */ + JCOPYOPT_COMMENTS, /* copy only comment (COM) markers */ + JCOPYOPT_ALL /* copy all optional markers */ +} JCOPY_OPTION; + +#define JCOPYOPT_DEFAULT JCOPYOPT_COMMENTS /* recommended default */ + +/* Setup decompression object to save desired markers in memory */ +EXTERN(void) jcopy_markers_setup + JPP((j_decompress_ptr srcinfo, JCOPY_OPTION option)); +/* Copy markers saved in the given source object to the destination object */ +EXTERN(void) jcopy_markers_execute + JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + JCOPY_OPTION option)); diff --git a/lc-continuity/mk4/modjava/CVS/Entries b/lc-continuity/mk4/modjava/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..9e2612129fb74ab30ea9959fcc0fcd1d3ad4e163 --- /dev/null +++ b/lc-continuity/mk4/modjava/CVS/Entries @@ -0,0 +1,6 @@ +/Makefile.in/1.2/Mon Apr 26 15:04:31 2004//Tmk4_mod6_rc2 +/Prog.java/1.5/Mon Mar 15 22:15:12 2004//Tmk4_mod6_rc2 +/entrance.c/1.6/Thu Mar 18 15:04:15 2004//Tmk4_mod6_rc2 +/modjava.c/1.5/Thu Mar 18 15:04:15 2004//Tmk4_mod6_rc2 +/module.cfg/1.2/Tue Feb 11 23:30:12 2003//Tmk4_mod6_rc2 +D/com//// diff --git a/lc-continuity/mk4/modjava/CVS/Repository b/lc-continuity/mk4/modjava/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..c8c33540a660065c860dec55e2670f351bbe5a25 --- /dev/null +++ b/lc-continuity/mk4/modjava/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/modjava diff --git a/lc-continuity/mk4/modjava/CVS/Root b/lc-continuity/mk4/modjava/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/modjava/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/modjava/CVS/Tag b/lc-continuity/mk4/modjava/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/modjava/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/modjava/Makefile.in b/lc-continuity/mk4/modjava/Makefile.in new file mode 100644 index 0000000000000000000000000000000000000000..12156f1a9ffe6d559a2e5dd91a76581cb6bcc2e8 --- /dev/null +++ b/lc-continuity/mk4/modjava/Makefile.in @@ -0,0 +1,37 @@ +CDIR=../continuity + +include $(CDIR)/lib/env.mk + +JINCLUDE=-I/usr/j2se/include -I/usr/j2se/include/solaris + +CFLAGS=-g $(JINCLUDE) -I$(CDIR)/include + +SRCS=modjava.c +OBJS=modjava.o + +world: com/ashpool/continuity/ContRequest.class modjava.so libentrance.so Prog.class + +com/ashpool/continuity/ContRequest.class: com/ashpool/continuity/ContRequest.java + javac com/ashpool/continuity/ContRequest.java + +modjava.so: $(OBJS) + $(LD_SHARECMD) $(OBJS) -o modjava.so + cp modjava.so ../continuity/lib +#-L/usr/j2se/jre/lib/sparc -ljvm + +libjavaentrance.so: com_ashpool_continuity_ContRequest.h entrance.o + $(LD_SHARECMD) entrance.o -o libjavaentrance.so + cp libjavaentrance.so ../continuity/lib + +com_ashpool_continuity_ContRequest.h: + javah com.ashpool.continuity.ContRequest + +Prog.class: Prog.java + javac Prog.java + +clean: + $(RM) modjava.so $(OBJS) *~ Prog.class libentrance.so entrance.o + $(RM) com_ashpool_continuity_ContRequest.h + +depend: + $(MAKEDEPEND) $(DEPFLAGS) -I ../continuity/include $(JINCLUDE) $(SRCS) diff --git a/lc-continuity/mk4/modjava/Prog.java b/lc-continuity/mk4/modjava/Prog.java new file mode 100644 index 0000000000000000000000000000000000000000..518f101f23ad147ea96bb3521de5e9f936d9ec7f --- /dev/null +++ b/lc-continuity/mk4/modjava/Prog.java @@ -0,0 +1,45 @@ +/* + * $Header: /san01/cvs/ashpool/csrc/modjava/Attic/Prog.java,v 1.5 2004/03/15 22:15:12 aleigh Exp $ + */ + +/* + * Copyright (c) 2003 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Use, disclosure, copying, distribution, or transmission of this code without + * express permission is prohibited. + */ + +import com.ashpool.continuity.*; + + public class Prog { + public static void main(String[] args) { + System.out.println("-java-> Loading entrance.so.."); + + System.setProperty("java.library.path","../lib"); + try { + System.loadLibrary("javaentrance"); + } catch (Exception e) { + System.out.println("loadLibrary: " + e.getMessage()); + } + } + + public static void handle(String[] args) { + System.out.println("Prog->Handler: called"); + + String foo = ContRequest.getResponseTuple("Server"); + String uri = ContRequest.getRequestTuple("uri"); + + ContRequest.setResponseTuple("Content-Type","text/plain"); + System.out.println("->java-> server: " + foo); + System.out.println("->java-> uri: " + uri); + + ContRequest.logMessage(3,"-java-> internal handler run."); + ContRequest.setResponseTuple("Java-Version","v.0.0.0"); + ContRequest.startResponse(200); + ContRequest.write("Hello World"); + } + } diff --git a/lc-continuity/mk4/modjava/com/CVS/Entries b/lc-continuity/mk4/modjava/com/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..28ce2b1de5577fe68c3c55ba1dd18a1d836afda8 --- /dev/null +++ b/lc-continuity/mk4/modjava/com/CVS/Entries @@ -0,0 +1 @@ +D/ashpool//// diff --git a/lc-continuity/mk4/modjava/com/CVS/Repository b/lc-continuity/mk4/modjava/com/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..8326002a21f85c858587aa37c2c59b6c83def183 --- /dev/null +++ b/lc-continuity/mk4/modjava/com/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/modjava/com diff --git a/lc-continuity/mk4/modjava/com/CVS/Root b/lc-continuity/mk4/modjava/com/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/modjava/com/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/modjava/com/CVS/Tag b/lc-continuity/mk4/modjava/com/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..3677f37e4f0eee70c8ee8cab24c43155060ef7d0 --- /dev/null +++ b/lc-continuity/mk4/modjava/com/CVS/Tag @@ -0,0 +1 @@ +Tmk4_mod6_rc2 diff --git a/lc-continuity/mk4/modjava/com/ashpool/CVS/Entries b/lc-continuity/mk4/modjava/com/ashpool/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..b638a6b84661fa059599ae2a2451782b997e04fd --- /dev/null +++ b/lc-continuity/mk4/modjava/com/ashpool/CVS/Entries @@ -0,0 +1 @@ +D/continuity//// diff --git a/lc-continuity/mk4/modjava/com/ashpool/CVS/Repository b/lc-continuity/mk4/modjava/com/ashpool/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..e5e264cb5bee1e0b8279871f5282000871573d9f --- /dev/null +++ b/lc-continuity/mk4/modjava/com/ashpool/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/modjava/com/ashpool diff --git a/lc-continuity/mk4/modjava/com/ashpool/CVS/Root b/lc-continuity/mk4/modjava/com/ashpool/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/modjava/com/ashpool/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/modjava/com/ashpool/CVS/Tag b/lc-continuity/mk4/modjava/com/ashpool/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..3677f37e4f0eee70c8ee8cab24c43155060ef7d0 --- /dev/null +++ b/lc-continuity/mk4/modjava/com/ashpool/CVS/Tag @@ -0,0 +1 @@ +Tmk4_mod6_rc2 diff --git a/lc-continuity/mk4/modjava/com/ashpool/continuity/CVS/Entries b/lc-continuity/mk4/modjava/com/ashpool/continuity/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..fec8378fb73bafdf0d9dd58505c1015ffd7e0e3b --- /dev/null +++ b/lc-continuity/mk4/modjava/com/ashpool/continuity/CVS/Entries @@ -0,0 +1,4 @@ +/CatalinaConnector.java/1.2/Tue Feb 11 23:30:12 2003//Tmk4_mod6_rc2 +/ContHttpRequest.java/1.3/Tue Feb 11 23:30:12 2003//Tmk4_mod6_rc2 +/ContRequest.java/1.3/Mon Mar 15 22:15:12 2004//Tmk4_mod6_rc2 +D diff --git a/lc-continuity/mk4/modjava/com/ashpool/continuity/CVS/Repository b/lc-continuity/mk4/modjava/com/ashpool/continuity/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..69c3f844f817258c912f7b5cfed2b8620e4d10af --- /dev/null +++ b/lc-continuity/mk4/modjava/com/ashpool/continuity/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/modjava/com/ashpool/continuity diff --git a/lc-continuity/mk4/modjava/com/ashpool/continuity/CVS/Root b/lc-continuity/mk4/modjava/com/ashpool/continuity/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/modjava/com/ashpool/continuity/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/modjava/com/ashpool/continuity/CVS/Tag b/lc-continuity/mk4/modjava/com/ashpool/continuity/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/modjava/com/ashpool/continuity/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/modjava/com/ashpool/continuity/CatalinaConnector.java b/lc-continuity/mk4/modjava/com/ashpool/continuity/CatalinaConnector.java new file mode 100644 index 0000000000000000000000000000000000000000..6fe4baa31de900447cb6de92eab17de7be8afca5 --- /dev/null +++ b/lc-continuity/mk4/modjava/com/ashpool/continuity/CatalinaConnector.java @@ -0,0 +1,307 @@ +package com.tessier.continuity; + +import org.apache.catalina.Container; +import org.apache.catalina.HttpRequest; +import org.apache.catalina.HttpResponse; +import org.apache.catalina.Lifecycle; +import org.apache.catalina.LifecycleEvent; +import org.apache.catalina.LifecycleException; +import org.apache.catalina.LifecycleListener; +import org.apache.catalina.Logger; +import org.apache.catalina.Request; +import org.apache.catalina.Response; +import org.apache.catalina.Service; +import org.apache.catalina.net.DefaultServerSocketFactory; +import org.apache.catalina.net.ServerSocketFactory; +import org.apache.catalina.util.LifecycleSupport; +import org.apache.catalina.util.StringManager; +import org.apache.catalina.Connector; + +/** + * Implementation of a Connectinuity interior connector. + * + * @author Alex Leigh + * @version $Revision: 1.2 $ + */ + +public final class CatalinaConnector + implements Lifecycle, Connector, Runnable { + + /** + * The Service we are associated with (if any). + */ + private Service service = null; + + /** + * The secure connection flag that will be set on all requests received + * through this connector. + */ + private boolean secure = false; + + + /** + * The redirect port for non-SSL to SSL redirects. + */ + private int redirectPort = 443; + + + /** + * The request scheme that will be set on all requests received + * through this connector. + */ + private String scheme = "http"; + + /** + * Descriptive information about this Connector implementation. + */ + private static final String info = + "com.tessier.continuity.CatalinaConnector/1.0"; + + /** + * The Container used for processing requests received by this Connector. + */ + protected Container container = null; + + /** + * The lifecycle event support for this component. + */ + protected LifecycleSupport lifecycle = new LifecycleSupport(this); + + + /** + * The "enable DNS lookups" flag for this Connector. + */ + private boolean enableLookups = false; + + + /** + * The server socket factory for this component. + */ + private ServerSocketFactory factory = null; + + + public void run() { + System.out.println("CatalinaConnector: run() called."); + } + + /** + * Add a lifecycle event listener to this component. + * + * @param listener The listener to add + */ + public void addLifecycleListener(LifecycleListener listener) { + lifecycle.addLifecycleListener(listener); + } + + /** + * Get the lifecycle listeners associated with this lifecycle. If this + * Lifecycle has no listeners registered, a zero-length array is returned. + */ + public LifecycleListener[] findLifecycleListeners() { + return lifecycle.findLifecycleListeners(); + } + + /** + * Remove a lifecycle event listener from this component. + * + * @param listener The listener to add + */ + public void removeLifecycleListener(LifecycleListener listener) { + lifecycle.removeLifecycleListener(listener); + } + + /** + * Begin processing requests via this Connector. + * + * @exception LifecycleException if a fatal startup error occurs + */ + public void start() throws LifecycleException { + // This really does nothing since our requests are going to come + // directly from Continuity. + } + + /** + * Terminate processing requests via this Connector. + * + * @exception LifecycleException if a fatal shutdown error occurs + */ + public void stop() throws LifecycleException { + } + + /** + * Return the Container used for processing requests received by this + * Connector. + */ + public Container getContainer() { + return (container); + } + + /** + * Set the Container used for processing requests received by this + * Connector. + * + * @param container The new Container to use + */ + public void setContainer(Container container) { + this.container = container; + } + + /** + * Return the "enable DNS lookups" flag. + */ + public boolean getEnableLookups() { + return (this.enableLookups); + } + + /** + * Set the "enable DNS lookups" flag. + * + * @param enableLookups The new "enable DNS lookups" flag value + */ + public void setEnableLookups(boolean enableLookups) { + this.enableLookups = enableLookups; + } + + /** + * Return the server socket factory used by this Container. + */ + public ServerSocketFactory getFactory() { + if (this.factory == null) { + synchronized (this) { + this.factory = new DefaultServerSocketFactory(); + } + } + return (this.factory); + } + + /** + * Set the server socket factory used by this Container. + * + * @param factory The new server socket factory + */ + public void setFactory(ServerSocketFactory factory) { + this.factory = factory; + } + + /** + * Return descriptive information about this Connector implementation. + */ + public String getInfo() { + return (info); + } + + /** + * Return the port number to which a request should be redirected if + * it comes in on a non-SSL port and is subject to a security constraint + * with a transport guarantee that requires SSL. + */ + public int getRedirectPort() { + + return (this.redirectPort); + + } + + /** + * Set the redirect port number. + * + * @param redirectPort The redirect port number (non-SSL to SSL) + */ + public void setRedirectPort(int redirectPort) { + + this.redirectPort = redirectPort; + + } + + /** + * Return the scheme that will be assigned to requests received + * through this connector. Default value is "http". + */ + public String getScheme() { + + return (this.scheme); + + } + + + /** + * Set the scheme that will be assigned to requests received through + * this connector. + * + * @param scheme The new scheme + */ + public void setScheme(String scheme) { + + this.scheme = scheme; + + } + + + /** + * Return the secure connection flag that will be assigned to requests + * received through this connector. Default value is "false". + */ + public boolean getSecure() { + + return (this.secure); + + } + + + /** + * Set the secure connection flag that will be assigned to requests + * received through this connector. + * + * @param secure The new secure connection flag + */ + public void setSecure(boolean secure) { + + this.secure = secure; + + } + + /** + * Return the Service with which we are associated (if any). + */ + public Service getService() { + + return (this.service); + + } + + + /** + * Set the Service with which we are associated (if any). + * + * @param service The service that owns this Engine + */ + public void setService(Service service) { + + this.service = service; + + } + + /** + * Create (or allocate) and return a Request object suitable for + * specifying the contents of a Request to the responsible Container. + */ + public Request createRequest() { + ContHttpRequest req = new ContHttpRequest(); + + req.setConnector(this); + return req; + } + + /** + * Create (or allocate) and return a Response object suitable for + * receiving the contents of a Response from the responsible Container. + */ + public Response createResponse() { + return null; + } + + public void initialize() + throws LifecycleException { + System.out.println("CatalinaConnector: initialize() called."); + } +} + diff --git a/lc-continuity/mk4/modjava/com/ashpool/continuity/ContHttpRequest.java b/lc-continuity/mk4/modjava/com/ashpool/continuity/ContHttpRequest.java new file mode 100644 index 0000000000000000000000000000000000000000..84b9baf97c41b4d2d30990b8055120eb0ff4b6c6 --- /dev/null +++ b/lc-continuity/mk4/modjava/com/ashpool/continuity/ContHttpRequest.java @@ -0,0 +1,82 @@ + +package com.tessier.continuity; + +import java.util.Locale; +import java.security.Principal; +import java.net.Socket; +import java.io.InputStream; +import java.util.Iterator; + +import javax.servlet.http.Cookie; +import javax.servlet.ServletInputStream; +import javax.servlet.ServletRequest; + +import org.apache.catalina.HttpRequest; +import org.apache.catalina.Context; +import org.apache.catalina.Connector; +import org.apache.catalina.Wrapper; +import org.apache.catalina.Response; + +/** + * Implementation of HttpRequest specific to the + * Continuity catalina connector. + * + * @author Alex Leigh + * @version $Revision: 1.3 $ $Date: 2003/02/11 23:30:12 $ + */ +final public class ContHttpRequest implements HttpRequest { + + public void addCookie(Cookie cookie) {} + public void addHeader (String name, String value) {} + public void addLocale(Locale locale) {} + public void addParameter(String name, String[] values) {} + public void clearCookies() {} + public void clearHeaders() {} + public void clearLocales() {} + public void clearParameters() {} + public String getDecodedRequestURI() {return null;} + public void setAuthType(String type) {} + public void setContextPath(String path) {} + public void setDecodedRequestURI(String uri) {} + public void setMethod(String method) {} + public void setPathInfo(String path) {} + public void setQueryString(String query) {} + public void setRequestedSessionCookie(boolean flag) {} + public void setRequestedSessionId(String id) {} + public void setRequestedSessionURL(boolean flag) {} + public void setRequestURI(String uri) {} + public void setServletPath(String path) {} + public void setUserPrincipal(Principal principal) {} + + public ServletInputStream createInputStream() {return null;} + public void finishRequest() {} + public String getAuthorization(){return null;} + public Connector getConnector(){return null;} + public Context getContext(){return null;} + public String getInfo(){return null;} + public Object getNote(String name){return null;} + public Iterator getNoteNames(){return null;} + public ServletRequest getRequest(){return null;} + public Response getResponse(){return null;} + public Socket getSocket(){return null;} + public InputStream getStream(){return null;} + public Wrapper getWrapper(){return null;} + public void recycle(){} + public void removeNote(String name){} + public void setAuthorization(String authorization){} + public void setConnector(Connector connector){} + public void setContentLength(int length){} + public void setContentType(String type){} + public void setContext(Context context){} + public void setNote(String name, Object value){} + public void setProtocol(String protocol){} + public void setRemoteAddr(String remote){} + public void setResponse(Response response){} + public void setScheme(String scheme){} + public void setSecure(boolean secure){} + public void setServerName(String name){} + public void setServerPort(int port){} + public void setSocket(Socket socket){} + public void setStream(InputStream stream){} + public void setWrapper(Wrapper wrapper){} +} diff --git a/lc-continuity/mk4/modjava/com/ashpool/continuity/ContRequest.java b/lc-continuity/mk4/modjava/com/ashpool/continuity/ContRequest.java new file mode 100644 index 0000000000000000000000000000000000000000..6804e6152f1b1a6a586026e9a6b37247d67e582b --- /dev/null +++ b/lc-continuity/mk4/modjava/com/ashpool/continuity/ContRequest.java @@ -0,0 +1,33 @@ +package com.ashpool.continuity; + +/** + * ContRequest implements a series of static methods which window + * into the Continuity server. The context for each method is the + * currently executing transaction for this thread. + */ + +public class ContRequest { +/** + * Log a message to the Continuity console. + * @param level The log level to use. 0 OK 1 WARN 2 ERR 3 DIAG + * msg The message to log to the console. + */ + public static native void logMessage(int level, String msg); + + public static native String getRequestTuple(String key); + public static native String getResponseTuple(String key); + public static native String getVarTuple(String key); + + public static native void setRequestTuple(String key, String value); + public static native void setResponseTuple(String key, String value); + public static native void setVarTuple(String key, String value); + + public static native void startResponse(int status); + + public static native void write(String str); + public static native void write(byte[] b, int length); + + public static native byte[] read(int length); + + public static native void glueObject(Object obj, String method, String name); +} diff --git a/lc-continuity/mk4/modjava/entrance.c b/lc-continuity/mk4/modjava/entrance.c new file mode 100644 index 0000000000000000000000000000000000000000..4e4fe5201f54a66b34df50d451ecd8cde31d3f28 --- /dev/null +++ b/lc-continuity/mk4/modjava/entrance.c @@ -0,0 +1,277 @@ +/* + * Copyright (c) 2003 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Use, disclosure, copying, distribution, or transmission of this code without + * express permission is prohibited. + */ + +#include "com_ashpool_continuity_ContRequest.h" +#include +#include + +JNIEXPORT void JNICALL + Java_com_ashpool_continuity_ContRequest_setResponseTuple(JNIEnv * env, + jclass class, + jstring key, + jstring value) +{ + httpTtrans *t = httpFthread_gettrans(); + jbyte *kstr; + jbyte *vstr; + + if (t == NULL) { + logFmsg(3, "mod/java: entrance thread had an orphaned context."); + return; + } + kstr = (jbyte *) (*env)->GetStringUTFChars(env, key, NULL); + vstr = (jbyte *) (*env)->GetStringUTFChars(env, value, NULL); + + logFmsg(3, "Setting %s/%s", kstr, vstr); + + lstFset_update(t->res_hdrs, (char *) kstr, (char *) vstr); + + (*env)->ReleaseStringUTFChars(env, key, (const char *) kstr); + (*env)->ReleaseStringUTFChars(env, value, (const char *) vstr); + + return; +} + + +JNIEXPORT jstring JNICALL + Java_com_ashpool_continuity_ContRequest_getResponseTuple(JNIEnv * env, + jclass class, + jstring key) { + httpTtrans *t; + char *v; + const jbyte *kstr; + + logFmsg(3, "getResponseTuple() called."); + + t == httpFthread_gettrans(); + + if (t == NULL) { + logFmsg(3, "mod/java: entrance thread had an orphaned context."); + return; + } + kstr = (jbyte *) (*env)->GetStringUTFChars(env, key, NULL); + + v = lstFset_get(t->res_hdrs, (char *) kstr); + + (*env)->ReleaseStringUTFChars(env, key, (const char *) kstr); + + if (v == NULL) + return NULL; + + return (*env)->NewStringUTF(env, v); +} + +JNIEXPORT void JNICALL + Java_com_ashpool_continuity_ContRequest_setRequestTuple(JNIEnv * env, + jclass class, + jstring key, + jstring value) +{ + httpTtrans *t = httpFthread_gettrans(); + jbyte *kstr; + jbyte *vstr; + + + logFmsg(3, "setRequestTuple() called."); + + if (t == NULL) { + logFmsg(3, "mod/java: entrance thread had an orphaned context."); + return; + } + kstr = (jbyte *) (*env)->GetStringUTFChars(env, key, NULL); + vstr = (jbyte *) (*env)->GetStringUTFChars(env, value, NULL); + + logFmsg(3, "Setting %s/%s", kstr, vstr); + + lstFset_update(t->req_hdrs, (char *) kstr, (char *) vstr); + + (*env)->ReleaseStringUTFChars(env, key, (const char *) kstr); + (*env)->ReleaseStringUTFChars(env, value, (const char *) vstr); + + return; +} + + +JNIEXPORT jstring JNICALL + Java_com_ashpool_continuity_ContRequest_getRequestTuple(JNIEnv * env, + jclass class, + jstring key) { + httpTtrans *t; + char *v; + const jbyte *kstr; + + logFmsg(3, "getRequestTuple() called."); + + t = httpFthread_gettrans(); + + + if (t == NULL) { + logFmsg(3, "mod/java: entrance thread had an orphaned context."); + return; + } + kstr = (jbyte *) (*env)->GetStringUTFChars(env, key, NULL); + + v = lstFset_get(t->req_hdrs, (char *) kstr); + + (*env)->ReleaseStringUTFChars(env, key, (const char *) kstr); + + if (v == NULL) + return NULL; + + return (*env)->NewStringUTF(env, v); +} + +JNIEXPORT void JNICALL Java_com_ashpool_continuity_ContRequest_setVarTuple + (JNIEnv * env, jclass class, jstring key, jstring value) { + httpTtrans *t = httpFthread_gettrans(); + jbyte *kstr; + jbyte *vstr; + + if (t == NULL) { + logFmsg(3, "mod/java: entrance thread had an orphaned context."); + return; + } + kstr = (jbyte *) (*env)->GetStringUTFChars(env, key, NULL); + vstr = (jbyte *) (*env)->GetStringUTFChars(env, value, NULL); + + logFmsg(3, "Setting %s/%s", kstr, vstr); + + lstFset_update(t->vars, (char *) kstr, (char *) vstr); + + (*env)->ReleaseStringUTFChars(env, key, (const char *) kstr); + (*env)->ReleaseStringUTFChars(env, value, (const char *) vstr); + + return; +} + + +JNIEXPORT jstring JNICALL + Java_com_ashpool_continuity_ContRequest_getVarTuple(JNIEnv * env, + jclass class, + jstring key) { + httpTtrans *t = httpFthread_gettrans(); + char *v; + const jbyte *kstr; + + logFmsg(3, "getVarTuple() called."); + + if (t == NULL) { + logFmsg(3, "mod/java: entrance thread had an orphaned context."); + return; + } + kstr = (jbyte *) (*env)->GetStringUTFChars(env, key, NULL); + + v = lstFset_get(t->vars, (char *) kstr); + + (*env)->ReleaseStringUTFChars(env, key, (const char *) kstr); + + if (v == NULL) + return NULL; + + return (*env)->NewStringUTF(env, v); +} + +JNIEXPORT void JNICALL Java_com_ashpool_continuity_ContRequest_write___3BI + (JNIEnv * env, jclass class, jbyteArray bytes, jint length) { + + httpTtrans *t = httpFthread_gettrans(); + + logFmsg(3, "write() called."); + + if (t == NULL) { + logFmsg(3, "mod/java: entrance thread had an orphaned context."); + return; + } + httpFwrite(t, (char *) bytes, length); +} + +JNIEXPORT void JNICALL Java_com_ashpool_continuity_ContRequest_logMessage + (JNIEnv * env, jclass class, jint level, jstring msg) { + char buf[128]; + const jbyte *str; + + logFmsg(3, "logMessage() called."); + + str = (jbyte *) (*env)->GetStringUTFChars(env, msg, NULL); + if (str == NULL) + return; + + logFmsg(level, (char *) str); + + (*env)->ReleaseStringUTFChars(env, msg, (const char *) str); + + return; +} + +JNIEXPORT void JNICALL + Java_com_ashpool_continuity_ContRequest_startResponse(JNIEnv * env, + jclass class, + jint status) { + httpTtrans *t = httpFthread_gettrans(); + + logFmsg(3, "startResponse() called."); + + if (t == NULL) { + logFmsg(3, "mod/java: entrance thread had an orphaned context."); + return; + } + logFmsg(3, "Setting status to %d and starting..", status); + + httpFset_status(t, status, NULL); + httpFstart_response(t); + + return; +} + +JNIEXPORT void JNICALL + Java_com_ashpool_continuity_ContRequest_write__Ljava_lang_String_2 + (JNIEnv * env, jclass class, jstring strv) { + const jbyte *str; + httpTtrans *t = httpFthread_gettrans(); + + if (t == NULL) { + logFmsg(3, "mod/java: entrance thread had an orphaned context."); + return; + } + str = (jbyte *) (*env)->GetStringUTFChars(env, strv, NULL); + if (str == NULL) + return; + + httpFwrite(t, (char *) str, strlen(str)); + + (*env)->ReleaseStringUTFChars(env, strv, (const char *) str); + return; +} + + +/* Let them come - There is still one dwarf in Moria who yet draws breath */ + +/* + * Class: com_ashpool_continuity_ContRequest Method: glueObject + * Signature: (Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;)V + */ + +/* obj method name */ + +JNIEXPORT void JNICALL Java_com_ashpool_continuity_ContRequest_glueObject + (JNIEnv * env, jclass class, jobject obj, jstring method, + jstring name) { + + /* + * right now we don't support any other container systems, so we are going + * to go ahead and just set this object as the catalina connector in + * modjava. + */ + + /* javaFsetCatalinaConnector(env,obj); */ + + return; +} diff --git a/lc-continuity/mk4/modjava/modjava.c b/lc-continuity/mk4/modjava/modjava.c new file mode 100644 index 0000000000000000000000000000000000000000..3eadea2161204010a6a3e1c07038e2876023a1d0 --- /dev/null +++ b/lc-continuity/mk4/modjava/modjava.c @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2003 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Use, disclosure, copying, distribution, or transmission of this code without + * express permission is prohibited. + */ + +#include +#include +#include + +#define PATH_SEPARATOR ';' /* define it to be ':' on Solaris */ +#define USER_CLASSPATH "." /* where Prog.class is */ + +JNIEnv *javaGenv; +JavaVM *javaGjvm; + +JNIEnv *javaFcreate_vm(char *classpath); +int javaFrun_method(JNIEnv * env, const char *class, const char *method); +int javaFinit(void *p, lstTset * opts); + +int javaFinit(void *p, lstTset * opts) +{ + pthread_t tid; + char *classpath = lstFset_get(opts, "classpath"); + char *initclass = lstFset_get(opts, "initclass"); + char *initmethod = lstFset_get(opts, "initmethod"); + + logFmsg(0, "mod/java: Java Runtime Engine v1.0.0"); + logFmsg(0, "mod/java: Copyright (c) 2003, Alex Leigh"); + + if (classpath == NULL || initclass == NULL || initmethod == NULL) { + logFmsg(2, + "mod/java: javaFinit: classpath, initclass, and initmethod must be specified."); + exit(0); + } + javaGenv = javaFcreate_vm(classpath); + javaFrun_method(javaGenv, initclass, initmethod); + + return STATUS_OK; +} + +int javaFrun_method(JNIEnv * env, const char *class, const char *method) +{ + jclass cls; + jmethodID mid; + jstring jstr; + jclass stringClass; + jobjectArray args; + + cls = (*env)->FindClass(env, class); + if (cls == NULL) { + logFmsg(2, "mod/java: init class %s could not be loaded.", class); + exit(0); + } + mid = (*env)->GetStaticMethodID(env, cls, method, + "([Ljava/lang/String;)V"); + if (mid == NULL) { + logFmsg(2, "mod/java: init method %s.%s could not be loaded.", + class, method); + exit(0); + + } + jstr = (*env)->NewStringUTF(env, " from C!"); + if (jstr == NULL) { + + } + stringClass = (*env)->FindClass(env, "java/lang/String"); + args = (*env)->NewObjectArray(env, 1, stringClass, jstr); + if (args == NULL) { + + } + + (*env)->CallStaticVoidMethod(env, cls, mid, args); + + return STATUS_OK; +} + +JNIEnv *javaFcreate_vm(char *classpath) +{ + JNIEnv *env; + jint res; + jclass cls; + jmethodID mid; + jstring jstr; + jclass stringClass; + jobjectArray args; + char argbuf[512]; + +#ifdef JNI_VERSION_1_2 + JavaVMInitArgs vm_args; + JavaVMOption options[3]; + + sprintf(argbuf, "-Djava.class.path=%s", classpath); + + options[0].optionString = &argbuf; + options[1].optionString = "-Djava.security.policy=lib/java.policy"; + options[2].optionString = "-verbose:jni"; + vm_args.version = 0x00010002; + vm_args.options = options; + vm_args.nOptions = 3; + vm_args.ignoreUnrecognized = JNI_TRUE; + /* Create the Java VM */ + res = JNI_CreateJavaVM(&javaGjvm, (void **) &env, &vm_args); +#else + JDK1_1InitArgs vm_args; + char classpath[1024]; + vm_args.version = 0x00010001; + JNI_GetDefaultJavaVMInitArgs(&vm_args); + /* Append USER_CLASSPATH to the default system class path */ + sprintf(classpath, "%s%c%s", + vm_args.classpath, PATH_SEPARATOR, USER_CLASSPATH); + vm_args.classpath = classpath; + /* Create the Java VM */ + res = JNI_CreateJavaVM(&javaGjvm, &env, &vm_args); +#endif /* JNI_VERSION_1_2 */ + + if (res < 0) { + fprintf(stderr, "Can't create Java VM\n"); + exit(1); + } + return env; + + destroy: + if ((*env)->ExceptionOccurred(env)) { + (*env)->ExceptionDescribe(env); + } + (*javaGjvm)->DestroyJavaVM(javaGjvm); + + return NULL; +} + +int javaFservice(httpTtrans * t, lstTset * opts) +{ + jint res; + JNIEnv *env; + const char *class_arg = lstFset_get(opts, "class"); + const char *method_arg = lstFset_get(opts, "method"); + + logFmsg(3, "mod/java: service: Called."); + + if (class_arg == NULL || method_arg == NULL) { + logFmsg(2, + "mod/java: javaFservice: method or class not specified."); + return STATUS_ERROR; + } +#ifdef JNI_VERSION_1_2 + res = (*javaGjvm)->AttachCurrentThread(javaGjvm, (void **) &env, NULL); +#else + res = (*javaGjvm)->AttachCurrentThread(javaGjvm, &env, NULL); +#endif + + if (res < 0) { + logFmsg(2, "mod/java: thread attach to VM failed."); + return STATUS_ERROR; + } + + javaFrun_method(env, class_arg, method_arg); + return STATUS_EXIT; +} diff --git a/lc-continuity/mk4/modjava/module.cfg b/lc-continuity/mk4/modjava/module.cfg new file mode 100644 index 0000000000000000000000000000000000000000..eae9d9cbd70fd3865d0b71ee12909186fe47bc8b --- /dev/null +++ b/lc-continuity/mk4/modjava/module.cfg @@ -0,0 +1,10 @@ +load shlib=./http.so +load shlib=/usr/j2se/jre/lib/sparc/libjvm.so +load shlib=./modjava.so + +init fn=httpFinit +init fn=javaFinit initclass=Prog initmethod=main classpath=/usr/j2se/lib/tools.jar:/datum01/users/aleigh/proj/java/tomcat/bin/bootstrap.jar:. +init fn=ipv4_dispatcher port=8990 handler=httpFhandler + +natr fn=javaFcatalina_service +natr fn=javaFservice method=handler class=Prog diff --git a/lc-continuity/mk4/modm3/.rev b/lc-continuity/mk4/modm3/.rev new file mode 100644 index 0000000000000000000000000000000000000000..fd6d73e4a0554be7673f39086280788941fefc24 --- /dev/null +++ b/lc-continuity/mk4/modm3/.rev @@ -0,0 +1 @@ +0.95 diff --git a/lc-continuity/mk4/modm3/CVS/Entries b/lc-continuity/mk4/modm3/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..a1ed9bd5dfd900455a40620a4f503a1ef4b87ccf --- /dev/null +++ b/lc-continuity/mk4/modm3/CVS/Entries @@ -0,0 +1,4 @@ +/.rev/1.1/Tue Apr 27 06:31:52 2004//Tmk4_mod6_rc2 +/Makefile.in/1.1/Wed May 19 19:48:27 2004//Tmk4_mod6_rc2 +D/include//// +D/src//// diff --git a/lc-continuity/mk4/modm3/CVS/Repository b/lc-continuity/mk4/modm3/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..827ba320e2a911bdca11b7e0bdf5b750322aa1df --- /dev/null +++ b/lc-continuity/mk4/modm3/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/modm3 diff --git a/lc-continuity/mk4/modm3/CVS/Root b/lc-continuity/mk4/modm3/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/modm3/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/modm3/CVS/Tag b/lc-continuity/mk4/modm3/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/modm3/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/modm3/Makefile.in b/lc-continuity/mk4/modm3/Makefile.in new file mode 100644 index 0000000000000000000000000000000000000000..930f24d0d1e63070deb4a18c8a0fea0337aa73d4 --- /dev/null +++ b/lc-continuity/mk4/modm3/Makefile.in @@ -0,0 +1,22 @@ +CONTINUITY = ../continuity + +TARGET = m3 +TARGETTYPE = module + +SOURCES = src/m3.c src/ixtime.c src/support.c \ + src/queue_playlist_engine.c src/order_playlist_engine.c \ + src/randomlist_playlist_engine.c src/m3_tcl.c src/file_entry.c \ + src/music_packet.c src/file_reader.c src/mp3_reader.c src/mp3_frame.c \ + src/shoutcast_metadata_writer.c src/m3_client.c src/m3_server.c \ + src/m3_server_factory.c src/file_catalog.c src/playlist_engine_factory.c \ + src/playlist_manager.c + +INCLUDES += -I../modsite -I../lib/aura/include +LOCAL_CFLAGS += + +STATIC_LIBS += ../lib/aura/libaura.a + +include $(CONTINUITY)/lib/build.mk + +depend: + echo No depend. diff --git a/lc-continuity/mk4/modm3/include/CVS/Entries b/lc-continuity/mk4/modm3/include/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..b9b69de68dbf69ec1db5f17137ff4d43d9d0061c --- /dev/null +++ b/lc-continuity/mk4/modm3/include/CVS/Entries @@ -0,0 +1,24 @@ +/_build.h/1.1/Wed Apr 28 16:51:50 2004//Tmk4_mod6_rc2 +/file_catalog.h/1.1/Thu Apr 29 07:21:17 2004//Tmk4_mod6_rc2 +/file_entry.h/1.1/Tue Apr 27 06:31:52 2004//Tmk4_mod6_rc2 +/file_reader.h/1.1/Tue Apr 27 06:31:52 2004//Tmk4_mod6_rc2 +/idata_reader.h/1.2/Fri May 14 16:51:26 2004//Tmk4_mod6_rc2 +/iplaylist.h/1.3/Fri May 14 06:20:33 2004//Tmk4_mod6_rc2 +/ixtime.h/1.1/Tue Apr 27 06:31:52 2004//Tmk4_mod6_rc2 +/m3.h/1.6/Fri May 14 16:51:26 2004//Tmk4_mod6_rc2 +/m3_client.h/1.2/Fri May 14 16:51:26 2004//Tmk4_mod6_rc2 +/m3_server.h/1.4/Fri May 14 06:20:33 2004//Tmk4_mod6_rc2 +/m3_server_factory.h/1.1/Tue Apr 27 06:31:52 2004//Tmk4_mod6_rc2 +/m3_tcl.h/1.1/Tue Apr 27 06:31:52 2004//Tmk4_mod6_rc2 +/mp3_frame.h/1.1/Tue Apr 27 06:31:52 2004//Tmk4_mod6_rc2 +/mp3_reader.h/1.2/Fri May 14 16:51:26 2004//Tmk4_mod6_rc2 +/music_packet.h/1.1/Tue Apr 27 06:31:52 2004//Tmk4_mod6_rc2 +/order_playlist_engine.h/1.1/Tue Apr 27 06:31:52 2004//Tmk4_mod6_rc2 +/playlist.h/1.1/Tue Apr 27 06:31:52 2004//Tmk4_mod6_rc2 +/playlist_engine_factory.h/1.1/Thu Apr 29 07:21:17 2004//Tmk4_mod6_rc2 +/playlist_manager.h/1.3/Fri May 14 06:20:33 2004//Tmk4_mod6_rc2 +/queue_playlist_engine.h/1.2/Thu Apr 29 07:21:17 2004//Tmk4_mod6_rc2 +/randomlist_playlist_engine.h/1.2/Thu Apr 29 07:21:17 2004//Tmk4_mod6_rc2 +/shoutcast_metadata_writer.h/1.2/Fri May 14 16:51:26 2004//Tmk4_mod6_rc2 +/support.h/1.1/Tue Apr 27 06:31:52 2004//Tmk4_mod6_rc2 +D diff --git a/lc-continuity/mk4/modm3/include/CVS/Repository b/lc-continuity/mk4/modm3/include/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..fa7af44e3de8c96fa1ed2e257aa02b052b120631 --- /dev/null +++ b/lc-continuity/mk4/modm3/include/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/modm3/include diff --git a/lc-continuity/mk4/modm3/include/CVS/Root b/lc-continuity/mk4/modm3/include/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/modm3/include/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/modm3/include/CVS/Tag b/lc-continuity/mk4/modm3/include/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/modm3/include/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/modm3/include/_build.h b/lc-continuity/mk4/modm3/include/_build.h new file mode 100644 index 0000000000000000000000000000000000000000..2f9459ab615832fdaa738d291b7f49b48ad15c28 --- /dev/null +++ b/lc-continuity/mk4/modm3/include/_build.h @@ -0,0 +1 @@ +#define _L_BUILDREV "0.95" diff --git a/lc-continuity/mk4/modm3/include/file_catalog.h b/lc-continuity/mk4/modm3/include/file_catalog.h new file mode 100644 index 0000000000000000000000000000000000000000..df9c2f3fee1c138deff51dc68bdd725f55be36b2 --- /dev/null +++ b/lc-continuity/mk4/modm3/include/file_catalog.h @@ -0,0 +1,15 @@ +#ifndef __FILE_CATALOG_H__ +#define __FILE_CATALOG_H__ + +#include "file_entry.h" + +typedef struct s_FileCatalog FileCatalog; + +FileCatalog * file_catalog_new (void); +void file_catalog_destroy (void *ptr); + +int file_catalog_get_fileid (FileCatalog *instance, const char *filename); + +FileEntry * file_catalog_get_file_entry (FileCatalog *instance, int fileId); + +#endif diff --git a/lc-continuity/mk4/modm3/include/file_entry.h b/lc-continuity/mk4/modm3/include/file_entry.h new file mode 100644 index 0000000000000000000000000000000000000000..a32de257b27b47e88f1c936fa44b9dfc05e569b0 --- /dev/null +++ b/lc-continuity/mk4/modm3/include/file_entry.h @@ -0,0 +1,18 @@ + +#ifndef __FILE_ENTRY_H__ +#define __FILE_ENTRY_H__ + +typedef struct s_FileEntry FileEntry; + +FileEntry * file_entry_new (const char *filename); +void file_entry_destroy (void *ptr); + +const char * file_entry_get_filename (FileEntry *instance); + +FileEntry * file_entry_duplicate (FileEntry *instance); + +const char * file_entry_get_filename (FileEntry *instance); +const char * file_entry_get_display_name (FileEntry *instance); +int file_entry_get_fileno (FileEntry *instance); + +#endif diff --git a/lc-continuity/mk4/modm3/include/file_reader.h b/lc-continuity/mk4/modm3/include/file_reader.h new file mode 100644 index 0000000000000000000000000000000000000000..aee81c9d9c7dfc2cd19d74adcecc0ed36f18048e --- /dev/null +++ b/lc-continuity/mk4/modm3/include/file_reader.h @@ -0,0 +1,10 @@ + +#ifndef __FILE_READER_H__ +#define __FILE_READER_H__ + +typedef struct s_FileReader FileReader; + +FileReader * file_reader_new (void); +void file_reader_destroy (void *ptr); + +#endif diff --git a/lc-continuity/mk4/modm3/include/idata_reader.h b/lc-continuity/mk4/modm3/include/idata_reader.h new file mode 100644 index 0000000000000000000000000000000000000000..9433e3d04b514852709b74d9130e86c605170673 --- /dev/null +++ b/lc-continuity/mk4/modm3/include/idata_reader.h @@ -0,0 +1,21 @@ +#ifndef __IDATA_READER_H__ +#define __IDATA_READER_H__ + +#include + +typedef struct IDataReader_s IDataReader; + +struct IDataReader_s +{ + bool (*open) (IDataReader *instance, const char *uri); + void (*close) (IDataReader *instance); + bool (*read_exact) (IDataReader *instance, char *buf, size_t count); + ssize_t (*read_bytes) (IDataReader *instance, char *buf, size_t count); + bool (*peek_bytes) (IDataReader *instance, char *buf, size_t count); + ssize_t (*seek_to_data) (IDataReader *instance, const char *needle, size_t count); + ssize_t (*seek_to_data_func) (IDataReader *instance, size_t count, int (*) (const char *ptr)); + void (*destroy) (void *instance); +}; + + +#endif diff --git a/lc-continuity/mk4/modm3/include/iplaylist.h b/lc-continuity/mk4/modm3/include/iplaylist.h new file mode 100644 index 0000000000000000000000000000000000000000..9b9f4322ede4d3dd64ab815c7b9f62dd73b2ca06 --- /dev/null +++ b/lc-continuity/mk4/modm3/include/iplaylist.h @@ -0,0 +1,25 @@ +#ifndef __IPLAYLIST_H__ +#define __IPLAYLIST_H__ + +#include "mecha.h" + +#include "iterator.h" + +typedef struct s_IPlaylist IPlaylist; + +struct s_IPlaylist +{ + void (*destroy) (IPlaylist *); + + const char * (*get_name) (IPlaylist *); + const char * (*get_type) (IPlaylist *); + + int (*get_next) (IPlaylist *); + bool (*add_file) (IPlaylist *, int fileid); + bool (*remove_file) (IPlaylist *, int fileid); + + IIterator * (*get_list_iterator) (IPlaylist *); + IIterator * (*get_next_iterator) (IPlaylist *); +}; + +#endif diff --git a/lc-continuity/mk4/modm3/include/ixtime.h b/lc-continuity/mk4/modm3/include/ixtime.h new file mode 100644 index 0000000000000000000000000000000000000000..adf3e10cf5e89db3d09f2e19e524d7b08250d54f --- /dev/null +++ b/lc-continuity/mk4/modm3/include/ixtime.h @@ -0,0 +1,12 @@ +/* $Id: ixtime.h,v 1.1 2004/04/27 06:31:52 eric Exp $ */ + +#ifndef __IXTIME_H__ +#define __IXTIME_H__ + +void timeval_add (struct timeval *res, struct timeval *t1, struct timeval *t2); +void timespec_add (struct timespec *res, struct timespec *t1, struct timespec *t2); +int timeval_subtract (struct timeval *result, struct timeval *x, struct timeval *y); +int timespec_subtract (struct timespec *result, struct timespec *x, struct timespec *y); +long timeval_to_ms (struct timeval *tv); + +#endif diff --git a/lc-continuity/mk4/modm3/include/m3.h b/lc-continuity/mk4/modm3/include/m3.h new file mode 100644 index 0000000000000000000000000000000000000000..c478405d8909a9a46331b5ffa6b5570c0561ed45 --- /dev/null +++ b/lc-continuity/mk4/modm3/include/m3.h @@ -0,0 +1,14 @@ +#ifndef __M3_H__ +#define __M3_H__ + +#include "mecha.h" + +const char * m3_get_songname (httpTtrans *trans); +int m3_get_skip_addr (httpTtrans *trans); +int m3_get_user_count (httpTtrans *trans); +void m3_skip_track (httpTtrans *trans); +bool m3_reload_playlist (httpTtrans *trans); + +bool m3_add_file (httpTtrans *trans, const char *playlist, const char *fileName); + +#endif diff --git a/lc-continuity/mk4/modm3/include/m3_client.h b/lc-continuity/mk4/modm3/include/m3_client.h new file mode 100644 index 0000000000000000000000000000000000000000..f776ca29da4716e6661a3533102a0f6aca5ddb2e --- /dev/null +++ b/lc-continuity/mk4/modm3/include/m3_client.h @@ -0,0 +1,23 @@ + +#ifndef __M3_CLIENT_H__ +#define __M3_CLIENT_H__ + +#include "mecha.h" +#include "http.h" +#include "music_packet.h" + +typedef struct s_M3Client M3Client; + +M3Client * m3_client_new (httpTtrans *trans, bool wantMetadata, int metadataInterval); +void m3_client_destroy (void *ptr); + +const char * m3_client_ip_address_get (M3Client *instance); + +void m3_client_packet_add (M3Client *instance, MusicPacket *packet); + +void m3_client_process_request (M3Client *instance); + +void m3_client_metadata_set (M3Client *instance, const char *title, const char *url); + + +#endif diff --git a/lc-continuity/mk4/modm3/include/m3_server.h b/lc-continuity/mk4/modm3/include/m3_server.h new file mode 100644 index 0000000000000000000000000000000000000000..82750c77e3f86af9eb8334b118263c4db7d91421 --- /dev/null +++ b/lc-continuity/mk4/modm3/include/m3_server.h @@ -0,0 +1,32 @@ + +#ifndef __M3_SERVER_H__ +#define __M3_SERVER_H__ + +#include "mecha.h" +#include "m3_client.h" + +typedef struct s_M3Server M3Server; + +M3Server * m3_server_new (void); +void m3_server_destroy (void *ptr); + +bool m3_server_parse (M3Server *instance, const char *siteid, const xmlTtag *m3Tag); + +const char * m3_server_metadata_title_get (M3Server *instance); +const char * m3_server_metadata_url_get (M3Server *instance); +const char * m3_server_browser_url_get (M3Server *instance); +const char * m3_server_file_displayname_get (M3Server *instance); +const char * m3_server_mountpoint_get (M3Server *instance); +int m3_server_connected_clients (M3Server *instance); +int m3_server_skipped_ip_address (M3Server *instance); + +void m3_server_skip_track (M3Server *instance, httpTtrans *trans); + +bool m3_server_reload_playlist (M3Server *instance); + +void m3_server_client_add (M3Server *instance, M3Client *client); +void m3_server_client_remove (M3Server *instance, M3Client *client); + +bool m3_server_add_file (M3Server *instance, const char *playlist, const char *fileName); + +#endif diff --git a/lc-continuity/mk4/modm3/include/m3_server_factory.h b/lc-continuity/mk4/modm3/include/m3_server_factory.h new file mode 100644 index 0000000000000000000000000000000000000000..0c53c1e55d413cf50149cce27ea50c5a235b8ab2 --- /dev/null +++ b/lc-continuity/mk4/modm3/include/m3_server_factory.h @@ -0,0 +1,14 @@ + +#ifndef __M3_SERVER_FACTORY_H__ +#define __M3_SERVER_FACTORY_H__ + +#include "m3_server.h" + +typedef struct s_M3ServerFactory M3ServerFactory; + +M3ServerFactory * m3_server_factory_new (const char *siteid); +void m3_server_factory_destroy (void *ptr); + +M3Server * m3_server_factory_find_mountpoint (M3ServerFactory *instance, const char *mountpoint); + +#endif diff --git a/lc-continuity/mk4/modm3/include/m3_tcl.h b/lc-continuity/mk4/modm3/include/m3_tcl.h new file mode 100644 index 0000000000000000000000000000000000000000..5ac8bf0d655b4cd9545881eab2f4efe3a0a21efb --- /dev/null +++ b/lc-continuity/mk4/modm3/include/m3_tcl.h @@ -0,0 +1,6 @@ +#ifndef __M3_TCL_H__ +#define __M3_TCL_H__ + +void m3_tcl_init (void); + +#endif diff --git a/lc-continuity/mk4/modm3/include/mp3_frame.h b/lc-continuity/mk4/modm3/include/mp3_frame.h new file mode 100644 index 0000000000000000000000000000000000000000..5dc0480562fc16905eb06ea0efc33007360eb0d6 --- /dev/null +++ b/lc-continuity/mk4/modm3/include/mp3_frame.h @@ -0,0 +1,28 @@ +#ifndef __MP3_FRAME_H__ +#define __MP3_FRAME_H__ + +struct mp3frame +{ + int version; + int layer; + int protection; + int bitrate; + int frequency; + int padding; + int private; + int channel_mode; + int channel_extension; + int copyright; + int original; + int emphasis; + int frame_byte_length; + long frame_usec_length; +}; + +/* thanks to http://www.dv.co.yu/mpgscript/mpeghdr.htm for the help */ + +extern int bitrate_index[4][4][16]; + +extern int samplerate_index[4][5]; + +#endif diff --git a/lc-continuity/mk4/modm3/include/mp3_reader.h b/lc-continuity/mk4/modm3/include/mp3_reader.h new file mode 100644 index 0000000000000000000000000000000000000000..f9d1b13d48ebced4a2043e9fd6035daa83c6cf6e --- /dev/null +++ b/lc-continuity/mk4/modm3/include/mp3_reader.h @@ -0,0 +1,17 @@ + +#ifndef __MP3_READER_H__ +#define __MP3_READER_H__ + +#include "mecha.h" +#include "music_packet.h" + +typedef struct s_Mp3Reader Mp3Reader; + +Mp3Reader * mp3_reader_new (void); +void mp3_reader_destroy (void *ptr); + +bool mp3_reader_open (Mp3Reader *instance, const char *uri); + +MusicPacket * mp3_reader_get_packet (Mp3Reader *instance, int requestedUsecs); + +#endif diff --git a/lc-continuity/mk4/modm3/include/music_packet.h b/lc-continuity/mk4/modm3/include/music_packet.h new file mode 100644 index 0000000000000000000000000000000000000000..9d73ab61f2e36d81816c272d8e8155ee85a0987e --- /dev/null +++ b/lc-continuity/mk4/modm3/include/music_packet.h @@ -0,0 +1,25 @@ + +#ifndef __MUSIC_PACKET_H__ +#define __MUSIC_PACKET_H__ + +#include + +#include "mecha.h" + +typedef struct s_MusicPacket MusicPacket; + +MusicPacket * music_packet_new (void); +void music_packet_destroy (void *ptr); + +MusicPacket * music_packet_duplicate (MusicPacket *instance); + +dynTstring * music_packet_data_get (MusicPacket *instance); +struct timeval music_packet_time_length_get (MusicPacket *instance); + +void music_packet_time_length_add_usec (MusicPacket *instance, long usec); + +int music_packet_timestamp_get (MusicPacket *instance); + +int music_packet_time_length_usecs_get (MusicPacket *instance); + +#endif diff --git a/lc-continuity/mk4/modm3/include/order_playlist_engine.h b/lc-continuity/mk4/modm3/include/order_playlist_engine.h new file mode 100644 index 0000000000000000000000000000000000000000..bec94dd4de2d234a53077d394313d0eb28528030 --- /dev/null +++ b/lc-continuity/mk4/modm3/include/order_playlist_engine.h @@ -0,0 +1,6 @@ +#ifndef __ORDER_PLAYLIST_ENGINE_H__ +#define __ORDER_PLAYLIST_ENGINE_H__ + +playlist_engine * order_playlist_engine_init (void); + +#endif diff --git a/lc-continuity/mk4/modm3/include/playlist.h b/lc-continuity/mk4/modm3/include/playlist.h new file mode 100644 index 0000000000000000000000000000000000000000..a11552752098ef3d20aca20f22af95b23f54455a --- /dev/null +++ b/lc-continuity/mk4/modm3/include/playlist.h @@ -0,0 +1,61 @@ +#ifndef __PLAYLIST_H__ +#define __PLAYLIST_H__ + +#include "mecha.h" + +#include "file_entry.h" + +#define PLAYLIST_TYPE_ORDER 0x001 /* playlist is played in order (from filelist) */ +#define PLAYLIST_TYPE_RANDOM 0x002 /* playlist is played completely randomly (with possible duplicates) */ +#define PLAYLIST_TYPE_RANDOMLIST 0x004 /* playlist is played randomly without duplicates */ +#define PLAYLIST_TYPE_RANDOMWEIGHTED 0x008 /* playlist is played randomly with weighting (with possible duplicates) */ +#define PLAYLIST_TYPE_QUEUE 0x010 /* playlist is played once - files removed after playing */ + +#define PLAYLIST_OPTION_FILEBASED 0x020 /* playlist is attached to a file */ +#define PLAYLIST_OPTION_MEMORYBASED 0x040 /* playlist is attached to a file */ + +typedef struct +{ + char *name; + + int type; + int options; + + int offset; + int len; + FileEntry **list; + + lstTlist *filelist; +} playlist; + +typedef struct +{ + char *name; + + int type; + + FileEntry * (*get_next) (playlist *); + int (*add_file) (playlist *, FileEntry *file); + int (*remove_file) (playlist *, const char *filename); + int (*set_to_filelist) (playlist *, const char *file); + int (*peek) (int num_entries, int *out_num_entries, lstTlist **out_entries); + +} playlist_engine; + +void playlist_init (void); +void playlist_destroy (void *ptr); + +void playlist_engine_destroy (void *ptr); + +FileEntry * playlist_get_next (void); + +int playlist_create (const char *name, const char *type); +int playlist_delete (const char *name); + +int playlist_add_file (const char *playlistname, const char *file); +int playlist_add_fileglob (const char *playlistname, const char *file); +int playlist_add_filelist (const char *playlistname, const char *file); + +int playlist_reload_filelist (const char *playlistname, const char *file); + +#endif diff --git a/lc-continuity/mk4/modm3/include/playlist_engine_factory.h b/lc-continuity/mk4/modm3/include/playlist_engine_factory.h new file mode 100644 index 0000000000000000000000000000000000000000..b27471bc5e1368af709d9c9c8af3dbe6832cd15a --- /dev/null +++ b/lc-continuity/mk4/modm3/include/playlist_engine_factory.h @@ -0,0 +1,14 @@ + +#ifndef __PLAYLIST_ENGINE_FACTORY_H__ +#define __PLAYLIST_ENGINE_FACTORY_H__ + +#include "iplaylist.h" + +typedef struct s_PlaylistEngineFactory PlaylistEngineFactory; + +PlaylistEngineFactory * playlist_engine_factory_new (void); +void playlist_engine_factory_destroy (void *ptr); + +IPlaylist * playlist_engine_factory_get_playlist (PlaylistEngineFactory *instance, const char *playlistType, const char *playlistName); + +#endif diff --git a/lc-continuity/mk4/modm3/include/playlist_manager.h b/lc-continuity/mk4/modm3/include/playlist_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..f797532eeb75b224e654479e7bea84754ad3f17e --- /dev/null +++ b/lc-continuity/mk4/modm3/include/playlist_manager.h @@ -0,0 +1,19 @@ + +#ifndef __PLAYLIST_MANAGER_H__ +#define __PLAYLIST_MANAGER_H__ + +#include "mecha.h" + +#include "file_entry.h" + +typedef struct s_PlaylistManager PlaylistManager; + +PlaylistManager * playlist_manager_new (void); +void playlist_manager_destroy (void *ptr); + +bool playlist_manager_add_playlist (PlaylistManager *instance, const char *playlistType, const char *playlistName); +bool playlist_manager_add_file (PlaylistManager *instance, const char *playlistName, const char *fileName); +bool playlist_manager_add_filelist (PlaylistManager *instance, const char *playlistName, const char *fileName); +FileEntry * playlist_manager_get_next_file_entry (PlaylistManager *instance); + +#endif diff --git a/lc-continuity/mk4/modm3/include/queue_playlist_engine.h b/lc-continuity/mk4/modm3/include/queue_playlist_engine.h new file mode 100644 index 0000000000000000000000000000000000000000..e86d027e405fc350e9ad6ec4f21716bbf1161e19 --- /dev/null +++ b/lc-continuity/mk4/modm3/include/queue_playlist_engine.h @@ -0,0 +1,8 @@ +#ifndef __QUEUE_PLAYLIST_ENGINE_H__ +#define __QUEUE_PLAYLIST_ENGINE_H__ + +typedef struct s_QueuePlaylistEngine QueuePlaylistEngine; + +QueuePlaylistEngine * queue_playlist_engine_init (const char *playlistName); + +#endif diff --git a/lc-continuity/mk4/modm3/include/randomlist_playlist_engine.h b/lc-continuity/mk4/modm3/include/randomlist_playlist_engine.h new file mode 100644 index 0000000000000000000000000000000000000000..7ea638d874d5ccca9ca9b434564a2afbaf35a14c --- /dev/null +++ b/lc-continuity/mk4/modm3/include/randomlist_playlist_engine.h @@ -0,0 +1,8 @@ +#ifndef __RANDOMLIST_PLAYLIST_ENGINE_H__ +#define __RANDOMLIST_PLAYLIST_ENGINE_H__ + +typedef struct s_RandomlistPlaylistEngine RandomlistPlaylistEngine; + +RandomlistPlaylistEngine * randomlist_playlist_engine_init (const char *playlistName); + +#endif diff --git a/lc-continuity/mk4/modm3/include/shoutcast_metadata_writer.h b/lc-continuity/mk4/modm3/include/shoutcast_metadata_writer.h new file mode 100644 index 0000000000000000000000000000000000000000..1fa6fdbdf9d1a96740302f6695c19336e0e9d9c0 --- /dev/null +++ b/lc-continuity/mk4/modm3/include/shoutcast_metadata_writer.h @@ -0,0 +1,13 @@ + +#ifndef __SHOUTCAST_METADATA_WRITER_H__ +#define __SHOUTCAST_METADATA_WRITER_H__ + +typedef struct s_ShoutcastMetadataWriter ShoutcastMetadataWriter; + +ShoutcastMetadataWriter * shoutcast_metadata_writer_new (httpTtrans *trans, bool writeMetadata, int metadataInterval); +void shoutcast_metadata_writer_destroy (void *ptr); + +bool shoutcast_metadata_writer_write (ShoutcastMetadataWriter *instance, dynTstring *data); +void shoutcast_metadata_writer_set_metadata (ShoutcastMetadataWriter *instance, const char *title, const char *url); + +#endif diff --git a/lc-continuity/mk4/modm3/include/support.h b/lc-continuity/mk4/modm3/include/support.h new file mode 100644 index 0000000000000000000000000000000000000000..f80547a3448d843929100e3f21eadc926e2a500b --- /dev/null +++ b/lc-continuity/mk4/modm3/include/support.h @@ -0,0 +1,12 @@ +/* $Id: support.h,v 1.1 2004/04/27 06:31:52 eric Exp $ */ + +#ifndef __VSUPPORT_H__ +#define __VSUPPORT_H__ + +#include +#include + +int ixmmap_open (const char *filename, char **buf, int *len); +int ixmmap_close (char *buf, int len); + +#endif diff --git a/lc-continuity/mk4/modm3/src/.cvsignore b/lc-continuity/mk4/modm3/src/.cvsignore new file mode 100644 index 0000000000000000000000000000000000000000..39a06683b730815e864ffb8e1993c54683d30c54 --- /dev/null +++ b/lc-continuity/mk4/modm3/src/.cvsignore @@ -0,0 +1 @@ +.deps diff --git a/lc-continuity/mk4/modm3/src/CVS/Entries b/lc-continuity/mk4/modm3/src/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..3c16eae68343084a144f5c28bd1958eb989e2720 --- /dev/null +++ b/lc-continuity/mk4/modm3/src/CVS/Entries @@ -0,0 +1,22 @@ +/.cvsignore/1.1/Thu Apr 29 07:21:17 2004//Tmk4_mod6_rc2 +/file_catalog.c/1.1/Thu Apr 29 07:21:17 2004//Tmk4_mod6_rc2 +/file_entry.c/1.1/Tue Apr 27 06:31:52 2004//Tmk4_mod6_rc2 +/file_reader.c/1.2/Fri May 14 16:51:26 2004//Tmk4_mod6_rc2 +/ixtime.c/1.1/Tue Apr 27 06:31:52 2004//Tmk4_mod6_rc2 +/m3.c/1.4/Fri May 14 16:51:26 2004//Tmk4_mod6_rc2 +/m3_client.c/1.2/Fri May 14 16:51:26 2004//Tmk4_mod6_rc2 +/m3_server.c/1.2/Thu Apr 29 07:21:17 2004//Tmk4_mod6_rc2 +/m3_server_factory.c/1.2/Fri May 14 16:51:26 2004//Tmk4_mod6_rc2 +/m3_tcl.c/1.3/Fri May 14 16:51:26 2004//Tmk4_mod6_rc2 +/mp3_frame.c/1.1/Tue Apr 27 06:31:52 2004//Tmk4_mod6_rc2 +/mp3_reader.c/1.2/Fri May 14 16:51:26 2004//Tmk4_mod6_rc2 +/music_packet.c/1.1/Tue Apr 27 06:31:52 2004//Tmk4_mod6_rc2 +/order_playlist_engine.c/1.1/Tue Apr 27 06:31:52 2004//Tmk4_mod6_rc2 +/playlist.c/1.2/Thu Apr 29 07:21:17 2004//Tmk4_mod6_rc2 +/playlist_engine_factory.c/1.1/Thu Apr 29 07:21:17 2004//Tmk4_mod6_rc2 +/playlist_manager.c/1.2/Fri Apr 30 19:06:23 2004//Tmk4_mod6_rc2 +/queue_playlist_engine.c/1.2/Thu Apr 29 07:21:17 2004//Tmk4_mod6_rc2 +/randomlist_playlist_engine.c/1.3/Thu May 13 07:48:44 2004//Tmk4_mod6_rc2 +/shoutcast_metadata_writer.c/1.2/Fri May 14 16:51:26 2004//Tmk4_mod6_rc2 +/support.c/1.1/Tue Apr 27 06:31:52 2004//Tmk4_mod6_rc2 +D diff --git a/lc-continuity/mk4/modm3/src/CVS/Repository b/lc-continuity/mk4/modm3/src/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..18c0311750401d83a8a2cdbbf67cd81b22efda47 --- /dev/null +++ b/lc-continuity/mk4/modm3/src/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/modm3/src diff --git a/lc-continuity/mk4/modm3/src/CVS/Root b/lc-continuity/mk4/modm3/src/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/modm3/src/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/modm3/src/CVS/Tag b/lc-continuity/mk4/modm3/src/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/modm3/src/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/modm3/src/file_catalog.c b/lc-continuity/mk4/modm3/src/file_catalog.c new file mode 100644 index 0000000000000000000000000000000000000000..3e59395535e2575e655a427d980f4020fa814d6c --- /dev/null +++ b/lc-continuity/mk4/modm3/src/file_catalog.c @@ -0,0 +1,63 @@ + +#include + +#include "mecha.h" + +#include "file_entry.h" +#include "file_catalog.h" + +struct s_FileCatalog +{ + hshTvoid_list *file_by_id; + hshTvoid_list *file_by_filename; +}; + +FileCatalog * +file_catalog_new (void) +{ + FileCatalog *instance = (FileCatalog *) malloc (sizeof (FileCatalog)); + + instance->file_by_id = hshFvoid_int_init (file_entry_destroy); + instance->file_by_filename = hshFvoid_init (NULL); + + return (instance); +} + +void +file_catalog_destroy (void *ptr) +{ + FileCatalog *instance = (FileCatalog *) ptr; + + hshFvoid_destroy (instance->file_by_id); + hshFvoid_destroy (instance->file_by_filename); + + free (instance); +} + +int +file_catalog_get_fileid (FileCatalog *instance, const char *filename) +{ + FileEntry *entry; + + entry = (FileEntry *) hshFvoid_find (instance->file_by_filename, filename); + + if (entry == NULL) + { + entry = file_entry_new (filename); + + hshFvoid_add (instance->file_by_filename, filename, entry); + hshFvoid_int_add (instance->file_by_id, file_entry_get_fileno (entry), entry); + } + + return (file_entry_get_fileno (entry)); +} + +FileEntry * +file_catalog_get_file_entry (FileCatalog *instance, int fileId) +{ + FileEntry *entry; + + entry = (FileEntry *) hshFvoid_int_find (instance->file_by_id, fileId); + + return (entry); +} diff --git a/lc-continuity/mk4/modm3/src/file_entry.c b/lc-continuity/mk4/modm3/src/file_entry.c new file mode 100644 index 0000000000000000000000000000000000000000..f019d7c05c222625157382d5dbc971fbce1747cc --- /dev/null +++ b/lc-continuity/mk4/modm3/src/file_entry.c @@ -0,0 +1,111 @@ + +#include + +#include "file_entry.h" + +#include "mecha.h" + +static char * file_entry_create_display_name (FileEntry *instance); + +static int g_file_sequence_counter = 0; + +struct s_FileEntry +{ + int fileno; + char * filename; + char * displayName; +}; + +FileEntry * +file_entry_new (const char *filename) +{ + FileEntry *instance = (FileEntry *) malloc (sizeof (FileEntry)); + + instance->fileno = g_file_sequence_counter++; + + instance->filename = strFcopy (filename); + + instance->displayName = file_entry_create_display_name ( + instance); + + return (instance); +} + +void +file_entry_destroy (void *ptr) +{ + FileEntry *instance = (FileEntry *) ptr; + + free (instance->filename); + + free (instance->displayName); + + free (instance); +} + +FileEntry * +file_entry_duplicate (FileEntry *instance) +{ + FileEntry *dest = (FileEntry *) malloc (sizeof (FileEntry)); + + dest->fileno = instance->fileno; + dest->filename = strFcopy (instance->filename); + dest->displayName = strFcopy (instance->displayName); + + return (dest); +} + +const char * +file_entry_get_filename (FileEntry *instance) +{ + return (instance->filename); +} + +const char * +file_entry_get_display_name (FileEntry *instance) +{ + return (instance->displayName); +} + +int +file_entry_get_fileno (FileEntry *instance) +{ + return (instance->fileno); +} + +static char * +file_entry_create_display_name (FileEntry *instance) +{ + const char *p, *q; + char *ret; + int len; + + p = strrchr (instance->filename, '/'); + + if (p != NULL) + { + p++; + } + else + { + p = instance->filename; + } + + q = strrchr (p, '.'); + + if (q) + { + len = q - p; + } + else + { + len = strlen (p); + } + + ret = (char *) malloc (len + 1); + memcpy (ret, p, len); + ret[len] = 0; + + return (ret); +} + diff --git a/lc-continuity/mk4/modm3/src/file_reader.c b/lc-continuity/mk4/modm3/src/file_reader.c new file mode 100644 index 0000000000000000000000000000000000000000..b885d2d16e09495052b98760b830404d1d0c3e9f --- /dev/null +++ b/lc-continuity/mk4/modm3/src/file_reader.c @@ -0,0 +1,395 @@ + +#include + +#include "mecha.h" + +#include "file_reader.h" + +#include "idata_reader.h" + +struct s_FileReader +{ + IDataReader reader; + + int fd; + + size_t start_offset; + size_t end_offset; + char *buffer; + size_t buffer_len; +}; + +static bool file_reader_read_exact (IDataReader *inst, char *buf, size_t count); +ssize_t file_reader_read_bytes (IDataReader *inst, char *buf, size_t count); +static bool file_reader_peek_bytes (IDataReader *inst, char *buf, size_t count); +ssize_t file_reader_seek_to_data (IDataReader *instance, const char *needle, size_t count); +static ssize_t file_reader_seek_to_data_func (IDataReader *inst, size_t count, int (*) (const char *ptr)); + +static bool file_reader_open (IDataReader *inst, const char *file); +static void file_reader_close (IDataReader *inst); + +FileReader * +file_reader_new (void) +{ + FileReader *instance = (FileReader *) malloc (sizeof (FileReader)); + + instance->reader.open = file_reader_open; + instance->reader.close = file_reader_close; + + instance->reader.read_exact = file_reader_read_exact; + instance->reader.read_bytes = file_reader_read_bytes; + instance->reader.peek_bytes = file_reader_peek_bytes; + instance->reader.seek_to_data = file_reader_seek_to_data; + instance->reader.seek_to_data_func = file_reader_seek_to_data_func; + + instance->reader.destroy = file_reader_destroy; + + instance->fd = -1; + + instance->start_offset = 0; + instance->end_offset = 0; + + instance->buffer_len = 1024; + instance->buffer = malloc (sizeof (char) * instance->buffer_len); + + return (instance); +} + +void +file_reader_destroy (void *ptr) +{ + FileReader *instance = (FileReader *) ptr; + + file_reader_close ((IDataReader *) instance); + + free (instance->buffer); + + free (instance); +} + +static bool +file_reader_open (IDataReader *inst, const char *file) +{ + FileReader *instance = (FileReader *) inst; + + instance->fd = open (file, O_RDONLY); + + if (instance->fd == -1) + { + return (false); + } + else + { + instance->start_offset = 0; + instance->end_offset = 0; + + return (true); + } +} + +static void +file_reader_close (IDataReader *inst) +{ + FileReader *instance = (FileReader *) inst; + + if (instance->fd != -1) + { + close (instance->fd); + } +} + +static size_t +file_reader_buffer_len_get (FileReader *instance) +{ + return (instance->end_offset - instance->start_offset); +} + +static int +file_reader_buffer_avail_len (FileReader *instance) +{ + return (instance->buffer_len - instance->end_offset); +} + +static char * +file_reader_buffer_get (FileReader *instance) +{ + return (instance->buffer + instance->start_offset); +} + +static bool +file_reader_buffer_populate (FileReader *instance, size_t minLen) +{ + if (minLen <= file_reader_buffer_len_get (instance)) + { + return (true); + } + else + { + int ret; + + if (file_reader_buffer_avail_len (instance) + file_reader_buffer_len_get (instance) < minLen) + { + size_t growAmount = 1024; + + if (minLen > growAmount) + { + growAmount = minLen; + } + + /* + * if we have more room at the start of the buffer that is unused + * than we're looking to grow by, we'll just move the buffer to + * the start. + */ + if (growAmount < instance->start_offset) + { + memmove (instance->buffer, instance->buffer + instance->start_offset, + instance->end_offset - instance->start_offset); + + instance->end_offset = instance->end_offset - instance->start_offset; + instance->start_offset = 0; + } + else + { + instance->buffer = realloc (instance->buffer, instance->buffer_len + growAmount); + instance->buffer_len += growAmount; + } + } + + while (file_reader_buffer_len_get (instance) < minLen) + { + ret = read (instance->fd, instance->buffer + instance->end_offset, + file_reader_buffer_avail_len (instance)); + + if (ret < 1) + { + return (false); + } + + instance->end_offset += ret; + } + + return (true); + } +} + +static bool +file_reader_buffer_copy (FileReader *instance, char *buf, size_t len) +{ + if (len > file_reader_buffer_len_get (instance)) + { + return (false); + } + else + { + memcpy (buf, file_reader_buffer_get (instance), len); + + instance->start_offset += len; + + if (instance->start_offset == instance->end_offset) + { + instance->start_offset = 0; + instance->end_offset = 0; + } + + return (true); + } +} + +static bool +file_reader_read_exact (IDataReader *inst, char *buf, size_t count) +{ + FileReader *instance = (FileReader *) inst; + + /* + * couldn't read the length we needed to, we have to fail -- we want to + * either read the length we were asked or fail. + */ + if (file_reader_buffer_populate (instance, count) == false) + { + return (false); + } + + if (file_reader_buffer_copy (instance, buf, count) == true) + { + return (true); + } + else + { + /* + * this can't fail -- we already checked that there was enough room to + * do this copy + */ + + abort(); + } +} + +ssize_t +file_reader_read_bytes (IDataReader *inst, char *buf, size_t count) +{ + FileReader *instance = (FileReader *) inst; + size_t buffer_len = 0; + + /* couldn't read even one byte -- we obviously are at the end */ + if (file_reader_buffer_populate (instance, 1) == false) + { + return (-1); + } + + /* figure out how much we want to read */ + buffer_len = file_reader_buffer_len_get (instance); + + if (count < buffer_len) + { + buffer_len = count; + } + + if (file_reader_buffer_copy (instance, buf, buffer_len) == true) + { + return (buffer_len); + } + else + { + /* + * this can't fail -- we already checked that there was enough room to + * do this copy + */ + + abort(); + } +} + +static bool +file_reader_peek_bytes (IDataReader *inst, char *buf, size_t count) +{ + FileReader *instance = (FileReader *) inst; + + /* make sure the buffer has at least the number of bytes we need */ + if (file_reader_buffer_populate (instance, count) == false) + { + return (false); + } + + memcpy (buf, file_reader_buffer_get (instance), count); + + return (true); +} + +static ssize_t +file_reader_seek_to_data_func (IDataReader *inst, size_t count, int (*compare_func) (const char *)) +{ + FileReader *instance = (FileReader *) inst; + int skippedBytes = 0; + + assert (count > 0); + + if (count < 1) + { + return (-1); + } + + while (true) + { + /* make sure we have at least the number of bytes we're looking for */ + if (file_reader_buffer_populate (instance, count) == false) + { + return (-1); + } + + if (compare_func (file_reader_buffer_get (instance)) == 0) + { + /* + * if we found it, start_offset is correct, and everything is + * happy + */ + + return (skippedBytes); + } + else + { + instance->start_offset++; + skippedBytes++; + } + } +} + +ssize_t +file_reader_seek_to_data (IDataReader *inst, const char *needle, size_t count) +{ + FileReader *instance = (FileReader *) inst; + int skippedBytes = 0; + + assert (count > 0); + + if (count < 1) + { + return (-1); + } + + while (true) + { + char *ptr; + + /* make sure we have at least the number of bytes we're looking for */ + if (file_reader_buffer_populate (instance, count) == false) + { + return (-1); + } + + ptr = memchr (file_reader_buffer_get (instance), needle[0], file_reader_buffer_len_get (instance)); + + if (ptr != NULL) + { + int new_start_offset = ptr - instance->buffer; + + skippedBytes += new_start_offset - instance->start_offset; + + instance->start_offset = new_start_offset; + + /* + * if we don't have enough bytes in the buffer, we'll just do this + * again (which will force enough bytes on the buffer) + */ + if (file_reader_buffer_len_get (instance) < count) + { + continue; + } + + if (memcmp (ptr, needle, count) == 0) + { + /* + * if we found it, start_offset is correct, and everything is + * happy + */ + + return (skippedBytes); + } + else + { + /* + * if we didn't find it, so we'll skip one more byte so that + * the next time around, we'll be searching the rest of the + * data. + */ + + skippedBytes++; + instance->start_offset++; + + continue; + } + } + else + { + /* + * if we didn't find the first byte anywhere.. we'll have to ditch + * this buffer and try for another one + */ + skippedBytes += instance->end_offset - instance->start_offset; + + instance->start_offset = 0; + instance->end_offset = 0; + } + } +} + diff --git a/lc-continuity/mk4/modm3/src/ixtime.c b/lc-continuity/mk4/modm3/src/ixtime.c new file mode 100644 index 0000000000000000000000000000000000000000..d99949520de2e50b42ce8b0cbff6868e8c241727 --- /dev/null +++ b/lc-continuity/mk4/modm3/src/ixtime.c @@ -0,0 +1,91 @@ + +#include +#include +#include + +#include "ixtime.h" + +void +timeval_add (struct timeval *res, struct timeval *t1, struct timeval *t2) +{ + res->tv_sec = t1->tv_sec + t2->tv_sec; + res->tv_usec = t1->tv_usec + t2->tv_usec; + + res->tv_sec += res->tv_usec / 1000000L; + + res->tv_usec %= 1000000L; +} + +void +timespec_add (struct timespec *res, struct timespec *t1, struct timespec *t2) +{ + res->tv_sec = t1->tv_sec + t2->tv_sec; + res->tv_nsec = t1->tv_nsec + t2->tv_nsec; + + res->tv_sec += res->tv_nsec / 1000000000L; + + res->tv_nsec %= 1000000000L; +} + +/* Subtract the `struct timeval' values X and Y, + * storing the result in RESULT. + * Return 1 if the difference is negative, otherwise 0. */ + +/* ripped from some GNU webpage + * http://www.gnu.org/manual/glibc-2.2.3/html_node/libc_418.html + */ + +int +timeval_subtract (result, x, y) + struct timeval *result, *x, *y; +{ + /* Perform the carry for the later subtraction by updating y. */ + if (x->tv_usec < y->tv_usec) { + int nsec = (y->tv_usec - x->tv_usec) / 1000000L + 1; + y->tv_usec -= 1000000L * nsec; + y->tv_sec += nsec; + } + if (x->tv_usec - y->tv_usec > 1000000L) { + int nsec = (x->tv_usec - y->tv_usec) / 1000000L; + y->tv_usec += 1000000L * nsec; + y->tv_sec -= nsec; + } + + /* Compute the time remaining to wait. + * tv_usec is certainly positive. */ + result->tv_sec = x->tv_sec - y->tv_sec; + result->tv_usec = x->tv_usec - y->tv_usec; + + /* Return 1 if result is negative. */ + return x->tv_sec < y->tv_sec; +} + +int +timespec_subtract (struct timespec *result, struct timespec *x, struct timespec *y) +{ + /* Perform the carry for the later subtraction by updating y. */ + if (x->tv_nsec < y->tv_nsec) { + int nsec = (y->tv_nsec - x->tv_nsec) / 1000000000L + 1; + y->tv_nsec -= 1000000000L * nsec; + y->tv_sec += nsec; + } + if (x->tv_nsec - y->tv_nsec > 1000000000L) { + int nsec = (x->tv_nsec - y->tv_nsec) / 1000000000L; + y->tv_nsec += 1000000 * nsec; + y->tv_sec -= nsec; + } + + /* Compute the time remaining to wait. + * tv_nsec is certainly positive. */ + result->tv_sec = x->tv_sec - y->tv_sec; + result->tv_nsec = x->tv_nsec - y->tv_nsec; + + /* Return 1 if result is negative. */ + return x->tv_sec < y->tv_sec; +} + +long +timeval_to_ms (struct timeval *tv) +{ + return (tv->tv_sec * 1000 + tv->tv_usec / 1000); +} diff --git a/lc-continuity/mk4/modm3/src/m3.c b/lc-continuity/mk4/modm3/src/m3.c new file mode 100644 index 0000000000000000000000000000000000000000..867239fd432ec2e3842a3b857d4b456d6edad38f --- /dev/null +++ b/lc-continuity/mk4/modm3/src/m3.c @@ -0,0 +1,275 @@ + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mecha.h" +#include "site.h" +#include "continuity.h" +#include "modtcl.h" + +#include "ixtime.h" +#include "support.h" + +#include "_build.h" + +#include "m3_tcl.h" + +#include "m3.h" +#include "mp3_reader.h" + +#include "m3_server.h" +#include "m3_client.h" + +#include "m3_server.h" +#include "m3_server_factory.h" + +static M3Server * m3_get_server (httpTtrans *trans, const char *uri); + + + +int m3_client (httpTtrans *t, lstTset *opts); + +#define METADISTANCE (10 * 1024) + +static M3Server * +m3_get_this_server (httpTtrans *trans) +{ + const char *uri = lstFset_get (trans->vars, "uri"); + + assert (trans != NULL); + + if (uri == NULL) + { + return (NULL); + } + + return (m3_get_server (trans, uri)); +} + +static M3Server * +m3_get_server (httpTtrans *trans, const char *uri) +{ + const char *siteid = lstFset_get (trans->vars, "siteid"); + M3ServerFactory *serverFactory; + + assert (trans != NULL); + assert (uri != NULL); + assert (siteid != NULL); + + if (siteid == NULL) + { + return (NULL); + } + + serverFactory = (M3ServerFactory *) siteFsite_data_get (siteid, "m3"); + + if (serverFactory == NULL) + { + serverFactory = m3_server_factory_new (siteid); + + siteFsite_data_set (siteid, "m3", serverFactory); + } + + return (m3_server_factory_find_mountpoint (serverFactory, uri)); +} + +static bool +m3_is_browser_connection (httpTtrans *trans) +{ + const char *user_agent = lstFset_iget (trans->req_hdrs, "user-agent"); + + if (user_agent == NULL) + { + return (false); + } + + + if (strFcasestr (user_agent, "mozilla") || strFcasestr (user_agent, "lynx")) + { + return (true); + } + else + { + return (false); + } +} + + +int +m3_client (httpTtrans *t, MECHA_UNUSED_ARGUMENT lstTset *opts) +{ + const char *metac; + bool wantmeta = false; + M3Client *client; + M3Server *server; + + server = m3_get_this_server (t); + + if (server == NULL) + { + return (STATUS_PROCEED); + } + + if (m3_is_browser_connection (t) == true) + { + if (m3_server_browser_url_get (server) != NULL) + { + return (httpFredirect (t, m3_server_browser_url_get (server))); + } + } + + httpFset_nph (t); + + if ((metac = lstFset_iget (t->req_hdrs, "Icy-MetaData"))) + { + wantmeta = atoi (metac); + } + + httpFwritef (t, "HTTP/1.0 200 HAPPY HAPPY\r\n"); + httpFwritef (t, "icy-notice1:continuity/m3 v%s - http://5stops.com/m3/\r\n", _L_BUILDREV); + httpFwritef (t, "icy-name:%s\r\n", m3_server_metadata_title_get (server)); + httpFwritef (t, "icy-pub:0\r\n"); + httpFwritef (t, "icy-genre:mixed\r\n"); + httpFwritef (t, "icy-url:%s\r\n", m3_server_metadata_url_get (server)); + + if (wantmeta) + { + httpFwritef (t, "icy-metaint:%d\r\n", METADISTANCE); + } + + httpFwrite (t, "\r\n", 2); + + client = m3_client_new (t, wantmeta, METADISTANCE); + + m3_server_client_add (server, client); + + logFmsg (CONT_LOG_OK, "%s: starting stream // connected clients: %d", + m3_client_ip_address_get (client), m3_server_connected_clients (server)); + + m3_client_process_request (client); + + m3_server_client_remove (server, client); + + logFmsg (CONT_LOG_OK, "%s: closing stream // connected clients: %d", + m3_client_ip_address_get (client), m3_server_connected_clients (server)); + + m3_client_destroy (client); + + return (STATUS_EXIT); +} + +static bool +ensure_httpFwrite (httpTtrans * t, const char *buf, size_t len) +{ + ssize_t ret; + + ret = ensure_httpFwrite (t, buf, len); + + if (ret != (ssize_t) len) + { + return (false); + } + else + { + return (true); + } +} + +/* + * ---------------------------------------------------------- + * TCL HELPERS + * ---------------------------------------------------------- + */ + +const char * +m3_get_songname (httpTtrans *trans) +{ + M3Server *server = m3_get_server (trans, "/"); + + if (server == NULL) + { + return ("(none)"); + } + else + { + return (m3_server_file_displayname_get (server)); + } +} + +int +m3_get_skip_addr (httpTtrans *trans) +{ + M3Server *server = m3_get_server (trans, "/"); + + if (server == NULL) + { + return (0); + } + else + { + return (m3_server_skipped_ip_address (server)); + } +} + +int +m3_get_user_count (httpTtrans *trans) +{ + M3Server *server = m3_get_server (trans, "/"); + + if (server == NULL) + { + return (0); + } + else + { + return (m3_server_connected_clients (server)); + } +} + +bool +m3_add_file (httpTtrans *trans, const char *playlist, const char *fileName) +{ + M3Server *server = m3_get_server (trans, "/"); + + if (server == NULL) + { + return (false); + } + else + { + return (m3_server_add_file (server, playlist, fileName)); + } +} + +void +m3_skip_track (httpTtrans *trans) +{ + M3Server *server = m3_get_server (trans, "/"); + + if (server != NULL) + { + m3_server_skip_track (server, trans); + } +} + +bool +m3_reload_playlist (httpTtrans *trans) +{ + M3Server *server = m3_get_server (trans, "/"); + + if (server == NULL) + { + return (0); + } + else + { + return (m3_server_reload_playlist (server)); + } +} diff --git a/lc-continuity/mk4/modm3/src/m3_client.c b/lc-continuity/mk4/modm3/src/m3_client.c new file mode 100644 index 0000000000000000000000000000000000000000..c5abea4d73bdd990ac0ce7863c0975fbfb1bc71e --- /dev/null +++ b/lc-continuity/mk4/modm3/src/m3_client.c @@ -0,0 +1,134 @@ + +#include + +#include "m3_client.h" +#include "music_packet.h" +#include "shoutcast_metadata_writer.h" + +/* the maximum ip addr size including the null */ +#define MAX_IP_ADDR_SIZE 16 + +struct s_M3Client +{ + httpTtrans *trans; + + char ipAddress[MAX_IP_ADDR_SIZE]; + + lstTlist *messages; + + pthread_mutex_t messagesMutex; + pthread_cond_t messagesCond; + + ShoutcastMetadataWriter *metadataWriter; +}; + +M3Client * +m3_client_new (httpTtrans *trans, bool wantMetadata, int metadataInterval) +{ + M3Client *instance = (M3Client *) malloc (sizeof (M3Client)); + + instance->trans = trans; + + utlFip_to_str (trans->cli_ipv4_addr, instance->ipAddress, MAX_IP_ADDR_SIZE); + + instance->messages = lstFlist_create (music_packet_destroy); + + pthread_mutex_init (&instance->messagesMutex, 0); + pthread_cond_init (&instance->messagesCond, 0); + + instance->metadataWriter = shoutcast_metadata_writer_new (trans, wantMetadata, metadataInterval); + + return (instance); +} + +void +m3_client_destroy (void *ptr) +{ + M3Client *instance = (M3Client *) ptr; + + pthread_cond_destroy (&instance->messagesCond); + pthread_mutex_destroy (&instance->messagesMutex); + + lstFlist_free (instance->messages); + + shoutcast_metadata_writer_destroy (instance->metadataWriter); + + free (instance); +} + +const char * +m3_client_ip_address_get (M3Client *instance) +{ + return (instance->ipAddress); +} + +static void +m3_client_trim_old_messages (M3Client *instance) +{ + if (lstFlist_size (instance->messages) > 0) + { + MusicPacket *oldestPacket = (MusicPacket *) lstFlist_data (lstFlist_tail (instance->messages)); + + if (time(0) > music_packet_timestamp_get (oldestPacket) + 6) + { + logFmsg (CONT_LOG_WARN, "%s: too far behind -- clearing queue of %d packets.", + instance->ipAddress, lstFlist_size (instance->messages)); + + while (lstFlist_size (instance->messages) > 0) + { + lstFlist_remove (instance->messages, lstFlist_tail (instance->messages), (void **) &oldestPacket); + + music_packet_destroy (oldestPacket); + } + } + } +} + +void +m3_client_packet_add (M3Client *instance, MusicPacket *packet) +{ + pthread_mutex_lock (&instance->messagesMutex); + + m3_client_trim_old_messages (instance); + + lstFlist_add_prev (instance->messages, lstFlist_head (instance->messages), packet); + + pthread_cond_signal (&instance->messagesCond); + pthread_mutex_unlock (&instance->messagesMutex); +} + +void +m3_client_metadata_set (M3Client *instance, const char *title, const char *url) +{ + shoutcast_metadata_writer_set_metadata (instance->metadataWriter, title, url); +} + +void +m3_client_process_request (M3Client *instance) +{ + while (true) + { + MusicPacket *packet; + + pthread_mutex_lock (&instance->messagesMutex); + + if (lstFlist_size (instance->messages) == 0) + { + pthread_cond_wait (&instance->messagesCond, &instance->messagesMutex); + } + + lstFlist_remove (instance->messages, lstFlist_tail (instance->messages), (void **) &packet); + + pthread_mutex_unlock (&instance->messagesMutex); + + if (shoutcast_metadata_writer_write (instance->metadataWriter, + music_packet_data_get (packet)) == false) + { + music_packet_destroy (packet); + + break; + } + + music_packet_destroy (packet); + } +} diff --git a/lc-continuity/mk4/modm3/src/m3_server.c b/lc-continuity/mk4/modm3/src/m3_server.c new file mode 100644 index 0000000000000000000000000000000000000000..3a8ad44d5722d5897a053e6c9955fa71457a152e --- /dev/null +++ b/lc-continuity/mk4/modm3/src/m3_server.c @@ -0,0 +1,481 @@ + +#include +#include + +#include +#include "ixtime.h" + +#include "mp3_reader.h" + +#include "m3_server.h" +#include "file_entry.h" + +#include "m3_client.h" + +#include "playlist_manager.h" + +#if 0 +#include "playlist.h" +#endif + +#include "m3_tcl.h" + +struct s_M3Server +{ + const char *siteid; + + const char *mountpoint; + const char *browserUrl; + const char *metadataTitle; + const char *metadataUrl; + + PlaylistManager *playlistManager; + + FileEntry *currentFile; + pthread_rwlock_t currentFileLock; + + bool skipToNext; + + long ipAddressHitNext; + + const char *playlistFile; + + lstTlist *clientlist; + pthread_mutex_t clientlistMutex; + pthread_cond_t clientlistCond; +}; + + +static void * m3_server_process (void *ptr); +static bool m3_server_init (M3Server *instance); + +static void m3_server_broadcast_metadata (M3Server *instance, const char *title, const char *url); +static void m3_server_broadcast_packet (M3Server *instance, MusicPacket *packet); + +M3Server * +m3_server_new (void) +{ + M3Server *instance = (M3Server *) malloc (sizeof (M3Server)); + + instance->mountpoint = NULL; + instance->browserUrl = NULL; + instance->metadataTitle = NULL; + instance->metadataUrl = NULL; + + instance->playlistManager = playlist_manager_new(); + + instance->currentFile = NULL; + pthread_rwlock_init (&instance->currentFileLock, 0); + + instance->skipToNext = false; + + instance->ipAddressHitNext = 0; + + instance->playlistFile = NULL; + + instance->clientlist = lstFlist_create (m3_client_destroy); + + pthread_mutex_init (&instance->clientlistMutex, 0); + pthread_cond_init (&instance->clientlistCond, 0); + + return (instance); +} + +void +m3_server_destroy (void *ptr) +{ + M3Server *instance = (M3Server *) ptr; + + playlist_manager_destroy (instance->playlistManager); + + lstFlist_free (instance->clientlist); + + pthread_mutex_destroy (&instance->clientlistMutex); + pthread_cond_destroy (&instance->clientlistCond); + + free (instance); +} + +/* + * Example XML chunk: + * + * + * /home/eric/src/music.m3u + * /m3/ + * + * 5stops/radio + * http://stream.5stops.com/m3/currently_playing.html + * + * + */ + +bool +m3_server_parse (M3Server *instance, const char *siteid, const xmlTtag *m3Tag) +{ + instance->siteid = siteid; + + instance->mountpoint = xmlFtag_get_attrib_value (m3Tag, "mountpoint"); + + if (instance->mountpoint == NULL) + { + logFmsg (CONT_LOG_ERROR, "mod/m3: A mountpoint must be specified."); + + return (false); + } + + instance->playlistFile = xmlFfirst_child_value_str (m3Tag, "playlist"); + + if (instance->playlistFile == NULL) + { + logFmsg (CONT_LOG_ERROR, "mod/m3: %s:%s: A playlist must be specified.", + instance->siteid, instance->mountpoint); + + return (false); + } + + instance->browserUrl = xmlFfirst_child_value_str (m3Tag, "browserUrl"); + + { + const xmlTtag *metadataTag = xmlFfind_first_child (m3Tag, "shoutcastMetadata"); + + if (metadataTag != NULL) + { + instance->metadataTitle = xmlFfirst_child_value_str (metadataTag, "title"); + instance->metadataUrl = xmlFfirst_child_value_str (metadataTag, "url"); + } + } + + return (m3_server_init (instance)); +} + +static bool +m3_server_init (M3Server *instance) +{ + pthread_t thread; + + /* BUGBUG: This should be pulled from the config file */ + playlist_manager_add_playlist (instance->playlistManager, "queue", "preempt"); + playlist_manager_add_playlist (instance->playlistManager, "randomlist", "general"); + + if (playlist_manager_add_filelist (instance->playlistManager, "general", instance->playlistFile)) + { + logFmsg (CONT_LOG_OK, "mod/m3: %s:%s: Added filelist: %s", + instance->siteid, instance->mountpoint, instance->playlistFile); + } + else + { + logFmsg (CONT_LOG_ERROR, "mod/m3: %s:%s: Could not add filelist: %s", + instance->siteid, instance->mountpoint, instance->playlistFile); + + return (false); + } + + m3_tcl_init(); + + if (pthread_create (&thread, 0, m3_server_process, instance) != 0) + { + logFmsg (CONT_LOG_ERROR, "mod/m3: %s:%s: pthread_create: %s", + instance->siteid, instance->mountpoint, strerror (errno)); + + return (false); + } + + return (true); +} + +const char * +m3_server_metadata_title_get (M3Server *instance) +{ + return (instance->metadataTitle); +} + +const char * +m3_server_metadata_url_get (M3Server *instance) +{ + return (instance->metadataUrl); +} + +const char * +m3_server_browser_url_get (M3Server *instance) +{ + return (instance->browserUrl); +} + +const char * +m3_server_mountpoint_get (M3Server *instance) +{ + return (instance->mountpoint); +} + +int +m3_server_skipped_ip_address (M3Server *instance) +{ + return (instance->ipAddressHitNext); +} + +void +m3_server_skip_track (M3Server *instance, httpTtrans *trans) +{ + instance->skipToNext = true; + instance->ipAddressHitNext = trans->cli_ipv4_addr; +} + +int +m3_server_connected_clients (M3Server *instance) +{ + int count; + + pthread_mutex_lock (&instance->clientlistMutex); + + count = lstFlist_size (instance->clientlist); + + pthread_mutex_unlock (&instance->clientlistMutex); + + return (count); +} + +bool +m3_server_reload_playlist (MECHA_UNUSED_ARGUMENT M3Server *instance) +{ +#if 0 + if (playlist_reload_filelist ("general", instance->playlistFile) == 0) + { + return (true); + } + else + { + return (false); + } +#endif + + logFmsg (CONT_LOG_ERROR, "mod/m3: m3_server_reload_playlist needs to be implemented."); + + return (false); +} + +bool +m3_server_add_file (M3Server *instance, const char *playlist, const char *fileName) +{ + return (playlist_manager_add_file (instance->playlistManager, playlist, fileName)); +} + +void +m3_server_client_add (M3Server *instance, M3Client *client) +{ + pthread_mutex_lock (&instance->clientlistMutex); + + lstFlist_add_next (instance->clientlist, lstFlist_head (instance->clientlist), client); + + pthread_cond_signal (&instance->clientlistCond); + + tasFstat_set ((char *) "m3", 0, (char *) "users", lstFlist_size (instance->clientlist)); + + pthread_mutex_unlock (&instance->clientlistMutex); + + /* + * This will send an update notification to all clients, allowing the + * mini-browser to update, showing the current number of connected users + */ + m3_server_broadcast_metadata (instance, m3_server_file_displayname_get (instance), instance->metadataUrl); +} + +void +m3_server_client_remove (M3Server *instance, M3Client *client) +{ + lstTlist_elem *eptr; + + pthread_mutex_lock (&instance->clientlistMutex); + + for (eptr = lstFlist_head (instance->clientlist); eptr; eptr = lstFlist_next (eptr)) + { + if (client == lstFlist_data (eptr)) + { + lstFlist_remove (instance->clientlist, eptr, (void **) 0); + + tasFstat_set ((char *) "m3", 0, (char *) "users", lstFlist_size (instance->clientlist)); + + break; + } + } + + pthread_mutex_unlock (&instance->clientlistMutex); + + /* + * This will send an update notification to all clients, allowing the + * mini-browser to update, showing the current number of connected users + */ + m3_server_broadcast_metadata (instance, m3_server_file_displayname_get (instance), instance->metadataUrl); +} + +static void +m3_server_wait_for_clients (M3Server *instance) +{ + pthread_mutex_lock (&instance->clientlistMutex); + + if (lstFlist_size (instance->clientlist) == 0) + { + pthread_cond_wait (&instance->clientlistCond, &instance->clientlistMutex); + } + + pthread_mutex_unlock (&instance->clientlistMutex); +} + +static void +m3_server_get_next_file (M3Server *instance) +{ + pthread_rwlock_wrlock (&instance->currentFileLock); + + while ((instance->currentFile = playlist_manager_get_next_file_entry (instance->playlistManager)) == NULL) + { + thrFsleep (1000); + } + + pthread_rwlock_unlock (&instance->currentFileLock); +} + +const char * +m3_server_file_displayname_get (M3Server *instance) +{ + const char *name; + + pthread_rwlock_rdlock (&instance->currentFileLock); + + if (instance->currentFile != NULL) + { + name = file_entry_get_display_name (instance->currentFile); + } + else + { + name = ""; + } + + pthread_rwlock_unlock (&instance->currentFileLock); + + return (name); +} + +static void * +m3_server_process (void *ptr) +{ + M3Server *instance = (M3Server *) ptr; + struct timeval curtv; + bool playing = false; + Mp3Reader *mp3Reader = NULL; + + logFmsg (CONT_LOG_OK, "mod/m3: %s:%s: spinning up", + instance->siteid, instance->mountpoint); + + gettimeofday (&curtv, 0); + + while (true) + { + MusicPacket *packet; + + if (playing == false) + { + m3_server_get_next_file (instance); + + mp3Reader = mp3_reader_new(); + + if (mp3_reader_open (mp3Reader, file_entry_get_filename (instance->currentFile)) == false) + { + logFmsg (CONT_LOG_ERROR, "mod/m3: Could not open file: %s", + file_entry_get_filename (instance->currentFile)); + + mp3_reader_destroy (mp3Reader); + + continue; + } + + m3_server_wait_for_clients (instance); + + logFmsg (CONT_LOG_OK, "playing %s", file_entry_get_filename (instance->currentFile)); + + m3_server_broadcast_metadata (instance, m3_server_file_displayname_get (instance), + instance->metadataUrl); + + playing = true; + gettimeofday (&curtv, 0); + } + + if (instance->skipToNext == false) + { + packet = mp3_reader_get_packet (mp3Reader, 200000L); + } + else + { + packet = NULL; + } + + if (packet == NULL) + { + mp3_reader_destroy (mp3Reader); + + if (instance->skipToNext == false) + { + instance->ipAddressHitNext = 0; + } + + playing = false; + instance->skipToNext = false; + + continue; + } + + m3_server_broadcast_packet (instance, packet); + + { + struct timeval t1, t2, tsl, tdiff, twait, temptv; + + struct timeval packet_length = music_packet_time_length_get (packet); + + gettimeofday (&t1, 0); + timeval_add (&temptv, &curtv, &packet_length); /* add how long we want to sleep to the last run time */ + timeval_subtract (&twait, &temptv, &t1); /* subtract where we want to end up from where we are */ + + thrFsleep (timeval_to_ms (&twait)); + + gettimeofday (&t2, 0); + timeval_subtract (&tsl, &t2, &t1); /* get how long it took */ + timeval_subtract (&tdiff, &tsl, &twait); /* get the difference between how long it should and how long it did */ + timeval_subtract (&curtv, &t2, &tdiff); /* sent curtime to the last gettimeofday minus how long it shouldn't have taken */ + } + + music_packet_destroy (packet); + } +} + +static void +m3_server_broadcast_metadata (M3Server *instance, const char *title, const char *url) +{ + lstTlist_elem *ep; + + pthread_mutex_lock (&instance->clientlistMutex); + + for (ep = lstFlist_head (instance->clientlist); ep; ep = lstFlist_next (ep)) + { + M3Client *client = (M3Client *) lstFlist_data (ep); + + m3_client_metadata_set (client, title, url); + } + + pthread_mutex_unlock (&instance->clientlistMutex); +} + +static void +m3_server_broadcast_packet (M3Server *instance, MusicPacket *packet) +{ + lstTlist_elem *ep; + + pthread_mutex_lock (&instance->clientlistMutex); + + for (ep = lstFlist_head (instance->clientlist); ep; ep = lstFlist_next (ep)) + { + MusicPacket *newPacket = music_packet_duplicate (packet); + M3Client *client = (M3Client *) lstFlist_data (ep); + + m3_client_packet_add (client, newPacket); + } + + pthread_mutex_unlock (&instance->clientlistMutex); +} diff --git a/lc-continuity/mk4/modm3/src/m3_server_factory.c b/lc-continuity/mk4/modm3/src/m3_server_factory.c new file mode 100644 index 0000000000000000000000000000000000000000..b518a423574190384f33b07c9c3f6f9ca7192846 --- /dev/null +++ b/lc-continuity/mk4/modm3/src/m3_server_factory.c @@ -0,0 +1,109 @@ + +#include + +#include "site.h" + +#include "m3_server_factory.h" +#include "m3_server.h" + +struct s_M3ServerFactory +{ + lstTlist *serverlist; +}; + +static void m3_server_factory_parse (M3ServerFactory *instance, const char *siteid); + +M3ServerFactory * +m3_server_factory_new (const char *siteid) +{ + M3ServerFactory *instance = (M3ServerFactory *) malloc (sizeof (M3ServerFactory)); + + instance->serverlist = lstFlist_create (m3_server_destroy); + + m3_server_factory_parse (instance, siteid); + + return (instance); +} + +void +m3_server_factory_destroy (void *ptr) +{ + M3ServerFactory *instance = (M3ServerFactory *) ptr; + + lstFlist_free (instance->serverlist); + + free (instance); +} + +M3Server * +m3_server_factory_find_mountpoint (M3ServerFactory *instance, const char *mountpoint) +{ + lstTlist_elem *ep; + + for (ep = lstFlist_head (instance->serverlist); ep; ep = lstFlist_next (ep)) + { + M3Server *server = (M3Server *) lstFlist_data (ep); + + if (strcmp (m3_server_mountpoint_get (server), mountpoint) == 0) + { + return (server); + } + } + + return (NULL); +} + +static void +m3_server_factory_add (M3ServerFactory *instance, M3Server *server) +{ + lstFlist_add_next (instance->serverlist, lstFlist_tail (instance->serverlist), server); +} + +static void +m3_server_factory_parse (M3ServerFactory *instance, const char *siteid) +{ + const xmlTtag *config = siteFconfig_get_by_siteid (siteid); + xmlTiterator *iter; + const xmlTtag *tag; + + if (config == NULL) + { + return; + } + + iter = xmlFiterator_init (config); + + if (iter == NULL) + { + return; + } + + while ((tag = xmlFiterator_next_name (iter, "m3")) != NULL) + { + M3Server *server = m3_server_new(); + + if (m3_server_parse (server, siteid, tag) == true) + { + if (m3_server_factory_find_mountpoint (instance, m3_server_mountpoint_get (server)) == NULL) + { + m3_server_factory_add (instance, server); + } + else + { + logFmsg (CONT_LOG_ERROR, "mod/m3: Found a duplicate mountpoint for site %s: %s", + siteid, m3_server_mountpoint_get (server)); + + m3_server_destroy (server); + } + } + else + { + logFmsg (CONT_LOG_ERROR, "mod/m3: Could not parse m3 entry for site %s", + siteid); + + m3_server_destroy (server); + } + } + + xmlFiterator_free (iter); +} diff --git a/lc-continuity/mk4/modm3/src/m3_tcl.c b/lc-continuity/mk4/modm3/src/m3_tcl.c new file mode 100644 index 0000000000000000000000000000000000000000..25d0bbbd991467d1ff2d3c5c17bd65d421f9ecc7 --- /dev/null +++ b/lc-continuity/mk4/modm3/src/m3_tcl.c @@ -0,0 +1,131 @@ + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mecha.h" +#include "continuity.h" +#include "modtcl.h" + +#include "m3.h" + +#include "m3_tcl.h" + +static int m3_tcl_get_loser (ClientData ignored, Tcl_Interp *interp, int argc, char **argv); +static int m3_tcl_get_displayname (ClientData ignored, Tcl_Interp *interp, int argc, char **argv); +static int m3_tcl_skip_track (ClientData ignored, Tcl_Interp *interp, int argc, char **argv); +static int m3_tcl_get_users (ClientData ignored, Tcl_Interp *interp, int argc, char **argv); +static int m3_tcl_add_track (ClientData ignored, Tcl_Interp *interp, int argc, char **argv); +static int m3_tcl_reload_playlist (ClientData ignored, Tcl_Interp *interp, int argc, char **argv); + +void +m3_tcl_init() +{ + tclFbind_dyn_command ((char *) "m3_get_displayname", &m3_tcl_get_displayname); + tclFbind_dyn_command ((char *) "m3_skip_track", &m3_tcl_skip_track); + tclFbind_dyn_command ((char *) "m3_get_users", &m3_tcl_get_users); + tclFbind_dyn_command ((char *) "m3_get_loser", &m3_tcl_get_loser); + tclFbind_dyn_command ((char *) "m3_add_track", &m3_tcl_add_track); + tclFbind_dyn_command ((char *) "m3_reload_playlist", &m3_tcl_reload_playlist); +} + +static int +m3_tcl_get_loser (MECHA_UNUSED_ARGUMENT ClientData ignored, Tcl_Interp *interp, + MECHA_UNUSED_ARGUMENT int argc, MECHA_UNUSED_ARGUMENT char **argv) +{ + httpTtrans *trans = httpFthread_gettrans(); + + if (m3_get_skip_addr (trans)) + { + char *ip = Tcl_Alloc (17); + + utlFip_to_str (m3_get_skip_addr (trans), ip, 16); + Tcl_SetResult (interp, ip, TCL_DYNAMIC); + } + + return (TCL_OK); +} + +static int +m3_tcl_get_displayname (MECHA_UNUSED_ARGUMENT ClientData ignored, + Tcl_Interp *interp, MECHA_UNUSED_ARGUMENT int argc, + MECHA_UNUSED_ARGUMENT char **argv) +{ + Tcl_AppendResult (interp, m3_get_songname (httpFthread_gettrans()), (char *) NULL); + + return (TCL_OK); +} + +static int +m3_tcl_get_users (MECHA_UNUSED_ARGUMENT ClientData ignored, Tcl_Interp *interp, + MECHA_UNUSED_ARGUMENT int argc, MECHA_UNUSED_ARGUMENT char **argv) +{ + char *users = Tcl_Alloc (33); + + snprintf (users, 32, "%d", m3_get_user_count (httpFthread_gettrans())); + Tcl_SetResult (interp, users, TCL_DYNAMIC); + + return (TCL_OK); +} + +static int +m3_tcl_skip_track (MECHA_UNUSED_ARGUMENT ClientData ignored, + MECHA_UNUSED_ARGUMENT Tcl_Interp *interp, + MECHA_UNUSED_ARGUMENT int argc, MECHA_UNUSED_ARGUMENT char **argv) +{ + httpTtrans *trans = httpFthread_gettrans (); + char ipaddr[18]; + + utlFip_to_str (trans->cli_ipv4_addr, ipaddr, 17); + logFmsg (CONT_LOG_OK, "%s: skipped %s", ipaddr, m3_get_songname (trans)); + + m3_skip_track (trans); + + return (TCL_OK); +} + +static int +m3_tcl_add_track (MECHA_UNUSED_ARGUMENT ClientData ignored, + Tcl_Interp *interp, int argc, char **argv) +{ + if (argc != 3) + { + Tcl_SetResult (interp, (char *) "ERROR: requires two arguments: plalistname, filename", TCL_STATIC); + + return (TCL_ERROR); + } + + if (m3_add_file (httpFthread_gettrans(), argv[1], argv[2])) + { + Tcl_AppendResult (interp, "file ", argv[2], " added", (char *) NULL); + return (TCL_OK); + } + else + { + Tcl_AppendResult (interp, "ERROR: Could not add file '", argv[2], "' to playlist '", argv[1], "'", (char *) NULL); + return (TCL_ERROR); + } +} + +static int +m3_tcl_reload_playlist (MECHA_UNUSED_ARGUMENT ClientData ignored, + MECHA_UNUSED_ARGUMENT Tcl_Interp *interp, + MECHA_UNUSED_ARGUMENT int argc, MECHA_UNUSED_ARGUMENT char **argv) +{ + if (m3_reload_playlist (httpFthread_gettrans()) == true) + { + Tcl_AppendResult (interp, "Playlist reloaded.", NULL); + return (TCL_OK); + } + else + { + Tcl_AppendResult (interp, "Unable to reload playlist.", NULL); + return (TCL_ERROR); + } +} diff --git a/lc-continuity/mk4/modm3/src/mp3_frame.c b/lc-continuity/mk4/modm3/src/mp3_frame.c new file mode 100644 index 0000000000000000000000000000000000000000..14c6e33c1fb0a7046157186825647aed4a9d3f8b --- /dev/null +++ b/lc-continuity/mk4/modm3/src/mp3_frame.c @@ -0,0 +1,54 @@ + +/* thanks to http://www.dv.co.yu/mpgscript/mpeghdr.htm for the help */ + +int bitrate_index[4][4][16] = { + { /* version 0 */ + { 0 } + }, + { /* version 1 */ + { /* layer 0 */ + 0 + }, + /* layer 1 */ + { -1, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, -2 }, + /* layer 2 */ + { -1, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, -2 }, + /* layer 3 */ + { -1, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, -2 } + }, + { /* version 2 */ + { /* layer 0 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2 + }, + /* layer 1 */ + { -1, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, -2 }, + /* layer 2 */ + { -1, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, -2 }, + /* layer 3 */ + { -1, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, -2 } + }, + { /* version 2.5 */ + { /* layer 0 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2 + }, + /* layer 1 */ + { -1, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, -2 }, + /* layer 2 */ + { -1, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, -2 }, + /* layer 3 */ + { -1, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, -2 } + } +}; + +int samplerate_index[4][5] = +{ + /* (mpeg0) */ + { 0 }, + /* mpeg1 */ + { 44100, 48000, 32000, -1 }, + /* mpeg2 */ + { 22050, 24000, 16000, -1 }, + /* mpeg2.5 - not used */ + { 11025, 12000, 8000, -1 } +}; + diff --git a/lc-continuity/mk4/modm3/src/mp3_reader.c b/lc-continuity/mk4/modm3/src/mp3_reader.c new file mode 100644 index 0000000000000000000000000000000000000000..ec9ae44e924fa79e7e5ae4131bbf7cb2a80d5849 --- /dev/null +++ b/lc-continuity/mk4/modm3/src/mp3_reader.c @@ -0,0 +1,313 @@ + +#include + +#include "mp3_reader.h" + +#include "music_packet.h" +#include "idata_reader.h" +#include "file_reader.h" + +#include "mp3_frame.h" + +struct s_Mp3Reader +{ + IDataReader *reader; +}; + +Mp3Reader * +mp3_reader_new (void) +{ + Mp3Reader *instance = (Mp3Reader *) malloc (sizeof (Mp3Reader)); + + instance->reader = NULL; + + return (instance); +} + +void +mp3_reader_destroy (void *ptr) +{ + Mp3Reader *instance = (Mp3Reader *) ptr; + + if (instance->reader != NULL) + { + instance->reader->destroy (instance->reader); + } + + free (instance); +} + +bool +mp3_reader_open (Mp3Reader *instance, const char *uri) +{ + /* this should be using DataReaderFactory -- if such a thing existed */ + instance->reader = (IDataReader *) file_reader_new(); + + if (instance->reader->open (instance->reader, uri) == false) + { + return (false); + } + else + { + return (true); + } +} + +static bool +mp3_reader_parse_frame_header (MECHA_UNUSED_ARGUMENT Mp3Reader *instance, char *frameHeader, struct mp3frame *frameToFill) +{ + frameToFill->version = ((frameHeader[1] & 0x18) >> 3); + + if (frameToFill->version == 1) + { + logFmsg (CONT_LOG_ERROR, "found reserved version set"); + + return (false); + } + + if (frameToFill->version < 0 || frameToFill->version > 3) + { + logFmsg (CONT_LOG_ERROR, "unknown version %x", frameToFill->version); + + return (false); + } + + if (frameToFill->version == 3) + { + frameToFill->version = 1; + } + else if (frameToFill->version == 0) + { + frameToFill->version = 3; + } + + frameToFill->layer = ((frameHeader[1] & 0x06) >> 1); + + if (frameToFill->layer == 0) + { + logFmsg (CONT_LOG_ERROR, "found reserved layer set"); + + return (false); + } + if (frameToFill->layer < 1 || frameToFill->layer > 3) + { + logFmsg (CONT_LOG_ERROR, "unknown layer %x", frameToFill->layer); + + return (false); + } + + if (frameToFill->layer == 1) + { + frameToFill->layer = 3; + } + else if (frameToFill->layer == 3) + { + frameToFill->layer = 1; + } + + frameToFill->protection = frameHeader[1] & 0x01; + + frameToFill->bitrate = bitrate_index[frameToFill->version][frameToFill->layer][(frameHeader[2] & 0xf0) >> 4]; + + if (frameToFill->bitrate == -1) + { + logFmsg (CONT_LOG_ERROR, "don't know how to handle free format frames"); + + return (false); + } + else if (frameToFill->bitrate == -2) + { + logFmsg (CONT_LOG_ERROR, "found a frame with bad bitrate"); + + return (false); + } + else + { + frameToFill->bitrate *= 1000; + } + + frameToFill->frequency = samplerate_index[frameToFill->version][(frameHeader[2] & 0x0f) >> 2]; + + if (frameToFill->frequency == -1) + { + logFmsg (CONT_LOG_ERROR, "frequency was set to a reserved value"); + + return (false); + } + + frameToFill->padding = (frameHeader[2] & 0x02) >> 1; + + if (frameToFill->version == 1) + { + switch (frameToFill->layer) + { + case 1: + frameToFill->frame_byte_length = (384 * frameToFill->bitrate / 8 / frameToFill->frequency + frameToFill->padding) * 4; + frameToFill->frame_usec_length = 1000000L * 384 / frameToFill->frequency; + break; + case 2: + case 3: + frameToFill->frame_byte_length = 1152 * frameToFill->bitrate / 8 / frameToFill->frequency + frameToFill->padding; + frameToFill->frame_usec_length = 1000000L * 1152 / frameToFill->frequency; + break; + } + } + else + { + /* if we're not mpeg version 1 -- we don't know what to do */ + } + + frameToFill->private = frameHeader[2] & 0x01; + frameToFill->channel_mode = frameHeader[3] & 0xc0 >> 6; + frameToFill->channel_extension = frameHeader[3] & 0x30 >> 4; + frameToFill->copyright = frameHeader[3] & 0x08 >> 3; + frameToFill->original = frameHeader[3] & 0x04 >> 2; + frameToFill->emphasis = frameHeader[3] & 0x03; + + return (true); +} + +static int +mp3_reader_validate_sync_frame (const char *ptr) +{ + if ((ptr[0] & 0xff) == 0xff && (ptr[1] & 0xe0) == 0xe0) + { + return (0); + } + else + { + return (1); + } +} + +static bool +mp3_reader_get_next_frame (Mp3Reader *instance, struct mp3frame *frameToFill) +{ + ssize_t skippedBytes = 0; + char frameHeader[4]; + + while (true) + { + int thisSkippedBytes = instance->reader->seek_to_data_func (instance->reader, 2, mp3_reader_validate_sync_frame); + + if (thisSkippedBytes == -1) + { + /* we found the end of the file before we found the next sync frame */ + + return (false); + } + + skippedBytes += thisSkippedBytes; + + if (instance->reader->peek_bytes (instance->reader, frameHeader, sizeof (frameHeader)) == false) + { + /* + * we couldn't get all three bytes we needed.. we obviously got the + * end of the file early. + */ + + logFmsg (CONT_LOG_DEBUG, "mp3_reader: Reached the end of the file after finding the sync frame."); + + return (false); + } + + if (mp3_reader_parse_frame_header (instance, frameHeader, frameToFill) == false) + { + /* eat two bytes to progress on the stream */ + instance->reader->read_exact (instance->reader, frameHeader, 2); + + continue; + } + + if (frameToFill->version == 3) + { + /* logFmsg (CONT_LOG_ERROR, "not sure if we like version 2.5"); */ + + logFmsg (CONT_LOG_ERROR, "we don't support version 2.5"); + + /* eat two bytes to progress on the stream */ + instance->reader->read_exact (instance->reader, frameHeader, 2); + + continue; + } + + if (frameToFill->version != 1) + { + logFmsg (CONT_LOG_ERROR, "mp3_reader: Unknown mpeg version: %d", frameToFill->version); + + return (false); + } + + /* + * NOTE: we may not like: + * (frameToFill->version == 1 && frameToFill->layer == 1) + * either! + */ + + if (skippedBytes > 0) + { + logFmsg (CONT_LOG_DEBUG, "skipped %d bytes", skippedBytes); + } + + return (true); /* return offset */ + } +} + + +static bool +mp3_reader_add_next_frame (Mp3Reader *instance, MusicPacket *packet) +{ + struct mp3frame frame; + char frameBuffer[4096]; + + if (mp3_reader_get_next_frame (instance, &frame) == false) + { + return (false); + } + + assert (frame.frame_byte_length < 4096); + + if (instance->reader->read_exact (instance->reader, frameBuffer, frame.frame_byte_length) == true) + { + dynFappend (music_packet_data_get (packet), frameBuffer, frame.frame_byte_length); + + music_packet_time_length_add_usec (packet, frame.frame_usec_length); + + return (true); + } + else + { + return (false); + } +} + +MusicPacket * +mp3_reader_get_packet (Mp3Reader *instance, int requestedUsecs) +{ + MusicPacket *packet; + bool addedFrame = false; + + packet = music_packet_new(); + + while (music_packet_time_length_usecs_get (packet) < requestedUsecs) + { + if (mp3_reader_add_next_frame (instance, packet) == false) + { + break; + } + + addedFrame = true; + } + + if (addedFrame == false) + { + music_packet_destroy (packet); + + return (NULL); + } + else + { + return (packet); + } +} + diff --git a/lc-continuity/mk4/modm3/src/music_packet.c b/lc-continuity/mk4/modm3/src/music_packet.c new file mode 100644 index 0000000000000000000000000000000000000000..42d0397a4bd35c4fbcc168d430d9d0c2724b5aec --- /dev/null +++ b/lc-continuity/mk4/modm3/src/music_packet.c @@ -0,0 +1,83 @@ + +#include +#include + +#include "music_packet.h" + +struct s_MusicPacket +{ + dynTstring *data; + struct timeval timeLength; + int timestamp; +}; + +MusicPacket * +music_packet_new (void) +{ + MusicPacket *instance = (MusicPacket *) malloc (sizeof (MusicPacket)); + + instance->data = dynFinit(); + + instance->timeLength.tv_sec = 0; + instance->timeLength.tv_usec = 0; + + instance->timestamp = time (0); + + return (instance); +} + +void +music_packet_destroy (void *ptr) +{ + MusicPacket *instance = (MusicPacket *) ptr; + + dynFfree (instance->data); + + free (instance); +} + +MusicPacket * +music_packet_duplicate (MusicPacket *instance) +{ + MusicPacket *newInstance = (MusicPacket *) malloc (sizeof (MusicPacket)); + + newInstance->data = dynFinit(); + dynFappend_string (newInstance->data, instance->data); + + newInstance->timeLength = instance->timeLength; + + newInstance->timestamp = instance->timestamp; + + return (newInstance); +} + +dynTstring * +music_packet_data_get (MusicPacket *instance) +{ + return (instance->data); +} + +int +music_packet_timestamp_get (MusicPacket *instance) +{ + return (instance->timestamp); +} + +struct timeval +music_packet_time_length_get (MusicPacket *instance) +{ + return (instance->timeLength); +} + +int +music_packet_time_length_usecs_get (MusicPacket *instance) +{ + return ((instance->timeLength.tv_sec * 1000000L) + instance->timeLength.tv_usec); +} + +void +music_packet_time_length_add_usec (MusicPacket *instance, long usec) +{ + instance->timeLength.tv_sec += usec / 1000000L; + instance->timeLength.tv_usec += usec % 1000000L; +} diff --git a/lc-continuity/mk4/modm3/src/order_playlist_engine.c b/lc-continuity/mk4/modm3/src/order_playlist_engine.c new file mode 100644 index 0000000000000000000000000000000000000000..54ee32649be29264585df5fa2fef88ac51f1aec4 --- /dev/null +++ b/lc-continuity/mk4/modm3/src/order_playlist_engine.c @@ -0,0 +1,81 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mecha.h" + +#include "playlist.h" +#include "file_entry.h" + +#include "order_playlist_engine.h" + +static FileEntry * order_playlist_engine_get_next (playlist *p); +static int order_playlist_engine_add_file (playlist *p, FileEntry *file); + +playlist_engine * +order_playlist_engine_init (void) +{ + playlist_engine *p; + + p = (playlist_engine *) malloc (sizeof (playlist_engine)); + + p->name = strFcopy ("order"); + p->type = PLAYLIST_TYPE_ORDER; + p->get_next = order_playlist_engine_get_next; + p->add_file = order_playlist_engine_add_file; + + return (p); +} + +static FileEntry * +order_playlist_engine_get_next (playlist *p) +{ + if (p->type != PLAYLIST_TYPE_ORDER) + return (0); + + if (lstFlist_size (p->filelist) == 0) + return (0); + + if (p->len == 0) + { + lstTlist_elem *ep; + int i; + + p->len = lstFlist_size (p->filelist); + + p->list = (FileEntry **) malloc (sizeof (FileEntry *) * p->len); + + for (ep = lstFlist_head (p->filelist), i = 0; ep; ep = lstFlist_next (ep)) + p->list[i++] = lstFlist_data (ep); + + p->offset = 0; + } + + if (p->offset >= p->len) + p->offset = 0; + + return (file_entry_duplicate (p->list[p->offset++])); +} + + +static int +order_playlist_engine_add_file (playlist *p, FileEntry *entry) +{ + if (p->len > 0) + { + p->list = realloc (p->list, sizeof (FileEntry *) * (p->len + 1)); + p->list[p->len] = entry; + p->len++; + } + + lstFlist_add_next (p->filelist, lstFlist_tail (p->filelist), entry); + + return (0); +} diff --git a/lc-continuity/mk4/modm3/src/playlist.c b/lc-continuity/mk4/modm3/src/playlist.c new file mode 100644 index 0000000000000000000000000000000000000000..0aae564ee6045e7c350c7e514597ea5b4f56e387 --- /dev/null +++ b/lc-continuity/mk4/modm3/src/playlist.c @@ -0,0 +1,311 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mecha.h" + +#include "playlist.h" +#include "queue_playlist_engine.h" +#include "order_playlist_engine.h" +#include "randomlist_playlist_engine.h" + +static lstTlist *g_playlists; +static lstTlist *g_engines; + +static playlist * get_playlist (const char *name); + +void +playlist_init() +{ + g_playlists = lstFlist_create (playlist_destroy); + g_engines = lstFlist_create (playlist_engine_destroy); + +#if 0 + lstFlist_add_next (g_engines, lstFlist_tail (g_engines), + randomlist_playlist_engine_init()); + + lstFlist_add_next (g_engines, lstFlist_tail (g_engines), + queue_playlist_engine_init()); + + lstFlist_add_next (g_engines, lstFlist_tail (g_engines), + order_playlist_engine_init()); +#endif +} + +void +playlist_destroy (void *ptr) +{ + playlist *p = ptr; + + free (p->name); + if (p->len) + free (p->list); + + lstFlist_free (p->filelist); + + free (p); +} + +void +playlist_engine_destroy (void *ptr) +{ + playlist_engine *p = ptr; + + free (p->name); + + free (p); +} + +static playlist_engine * +get_playlist_engine_by_name (const char *name) +{ + lstTlist_elem *el; + + for (el = lstFlist_head (g_engines); el; el = lstFlist_next (el)) + { + playlist_engine *e = (playlist_engine *) lstFlist_data (el); + + if (!strcmp (name, e->name)) + return (e); + } + + return (0); +} + +static playlist_engine * +get_playlist_engine_by_type (int type) +{ + lstTlist_elem *el; + + for (el = lstFlist_head (g_engines); el; el = lstFlist_next (el)) + { + playlist_engine *e = (playlist_engine *) lstFlist_data (el); + + if (e->type == type) + return (e); + } + + return (0); +} + +int +playlist_create (const char *name, const char *type) +{ + playlist *p; + playlist_engine *e; + + if (get_playlist (name)) + return (1); + + if (!(e = get_playlist_engine_by_name (type))) + return (2); + + p = (playlist *) malloc (sizeof (playlist)); + + p->name = strFcopy (name); + + p->len = 0; + + p->type = e->type; + p->filelist = lstFlist_create (file_entry_destroy); + + lstFlist_add_next (g_playlists, lstFlist_tail (g_playlists), p); + + return (0); +} + +int +playlist_delete (const char *name) +{ + lstTlist_elem *el; + + for (el = lstFlist_head (g_playlists); el; el = lstFlist_next (el)) + { + playlist *p = lstFlist_data (el); + if (strcmp (name, p->name) == 0) + { + lstFlist_remove (g_playlists, el, NULL); + playlist_destroy (p); + return (0); + } + } + + return (1); +} + +playlist * +get_playlist (const char *name) +{ + lstTlist_elem *el; + + for (el = lstFlist_head (g_playlists); el; el = lstFlist_next (el)) + { + playlist *p = lstFlist_data (el); + if (strcmp (name, p->name) == 0) + return (p); + } + + return (0); +} + +int +playlist_add_file (const char *playlistname, const char *file) +{ + playlist *p; + playlist_engine *pe; + struct stat sbuf; + + if (!(p = get_playlist (playlistname))) + return (1); + + if (!(pe = get_playlist_engine_by_type (p->type))) + return (2); + + if (!pe->add_file) + return (3); + + if (stat (file, &sbuf) != 0) + { + return (-errno); + } + + return (pe->add_file (p, file_entry_new (file))); +} + +int +playlist_add_fileglob (const char *playlistname, const char *fileglob) +{ + playlist *p; + playlist_engine *pe; + glob_t globbuf; + int e; + unsigned int i; + + if (!(p = get_playlist (playlistname))) + return (1); + + if (!(pe = get_playlist_engine_by_type (p->type))) + return (2); + + if (!pe->add_file) + return (3); + + if (glob (fileglob, 0, NULL, &globbuf) != 0) + { + e = errno; + globfree (&globbuf); + return (-e); + } + + for (i = 0; i < globbuf.gl_pathc; i++) + pe->add_file (p, file_entry_new (globbuf.gl_pathv[i])); + + globfree (&globbuf); + + return (0); +} + +int +playlist_add_filelist (const char *playlistname, const char *file) +{ + playlist_engine *pe; + playlist *p; + + if (!(p = get_playlist (playlistname))) + return (1); + + if (!(pe = get_playlist_engine_by_type (p->type))) + return (2); + + if (!pe->add_file) + return (3); + + { + struct stat sbuf; + FILE *fp; + char strbuf[NAME_MAX+1]; + + if (stat (file, &sbuf) != 0) + return (-errno); + + if (!(fp = fopen (file, "r"))) + { + logFmsg (CONT_LOG_ERROR, "couldn't open file %s", file); + fclose (fp); + return (1); + } + + while (fgets (strbuf, sizeof (strbuf), fp) != NULL) + { + char *nl; + + if (strlen (strbuf) > 0 && (nl = strpbrk (strbuf, "\n\r"))) + { + *nl = 0; + + if (strbuf[0] == '#') + continue; + + if (stat (strbuf, &sbuf) != 0) + { + logFmsg (CONT_LOG_ERROR, "%s: no such file or directory", strbuf); + continue; + } + + pe->add_file (p, file_entry_new (strbuf)); + } + } + + fclose (fp); + } + + return (0); +} + +int +playlist_reload_filelist (const char *playlistname, const char *file) +{ + playlist_engine *pe; + playlist *p; + + if (!(p = get_playlist (playlistname))) + return (1); + + if (!(pe = get_playlist_engine_by_type (p->type))) + return (2); + + if (!pe->set_to_filelist) + return (3); + + return (pe->set_to_filelist (p, file)); +} + +FileEntry * +playlist_get_next () +{ + FileEntry *fileEntry; + playlist *p; + playlist_engine *pe; + + if ((p = get_playlist ("preempt"))) + if ((pe = get_playlist_engine_by_type (p->type))) + if (pe->get_next) + if ((fileEntry = pe->get_next (p))) + return (fileEntry); + + if ((p = get_playlist ("general"))) + if ((pe = get_playlist_engine_by_type (p->type))) + if (pe->get_next) + if ((fileEntry = pe->get_next (p))) + return (fileEntry); + + return (0); +} + diff --git a/lc-continuity/mk4/modm3/src/playlist_engine_factory.c b/lc-continuity/mk4/modm3/src/playlist_engine_factory.c new file mode 100644 index 0000000000000000000000000000000000000000..87377e9273097e6814ca155edc3aa1a7ea1b0218 --- /dev/null +++ b/lc-continuity/mk4/modm3/src/playlist_engine_factory.c @@ -0,0 +1,69 @@ + +#include + +#include "mecha.h" + +#include "queue_playlist_engine.h" +#include "randomlist_playlist_engine.h" + +#include "playlist_engine_factory.h" + +struct s_PlaylistEngineFactory +{ + hshTvoid_list *playlistEngines; +}; + +typedef IPlaylist * (*IPlaylistConstructorDelegate) (const char *playlistName); + +static void playlist_engine_factory_add_playlist (PlaylistEngineFactory *instance, + const char *playlistType, IPlaylistConstructorDelegate delegate); + +PlaylistEngineFactory * +playlist_engine_factory_new (void) +{ + PlaylistEngineFactory *instance = (PlaylistEngineFactory *) malloc (sizeof (PlaylistEngineFactory)); + + instance->playlistEngines = hshFvoid_init (NULL); + + playlist_engine_factory_add_playlist (instance, "queue", + (IPlaylistConstructorDelegate) queue_playlist_engine_init); + + playlist_engine_factory_add_playlist (instance, "randomlist", + (IPlaylistConstructorDelegate) randomlist_playlist_engine_init); + + return (instance); +} + +void +playlist_engine_factory_destroy (void *ptr) +{ + PlaylistEngineFactory *instance = (PlaylistEngineFactory *) ptr; + + hshFvoid_destroy (instance->playlistEngines); + + free (instance); +} + +static void +playlist_engine_factory_add_playlist (PlaylistEngineFactory *instance, const char *playlistType, + IPlaylistConstructorDelegate delegate) +{ + hshFvoid_replace (instance->playlistEngines, playlistType, (void *) delegate); +} + +IPlaylist * +playlist_engine_factory_get_playlist (PlaylistEngineFactory *instance, const char *playlistType, const char *playlistName) +{ + IPlaylistConstructorDelegate constructor; + + constructor = (IPlaylistConstructorDelegate) hshFvoid_find (instance->playlistEngines, playlistType); + + if (constructor == NULL) + { + return (NULL); + } + else + { + return (constructor (playlistName)); + } +} diff --git a/lc-continuity/mk4/modm3/src/playlist_manager.c b/lc-continuity/mk4/modm3/src/playlist_manager.c new file mode 100644 index 0000000000000000000000000000000000000000..edb2b03bc6ae57de88bc582b2382daae28341fc3 --- /dev/null +++ b/lc-continuity/mk4/modm3/src/playlist_manager.c @@ -0,0 +1,204 @@ + +#include + +#include "mecha.h" + +#include "playlist_engine_factory.h" +#include "file_catalog.h" + +#include "playlist_manager.h" + +/* NAME_MAX, quizzically, isn't everywhere. -aleigh */ +#ifndef NAME_MAX +#define NAME_MAX 255 +#endif + +struct s_PlaylistManager +{ + lstTlist *playlists; + + FileCatalog *fileCatalog; + + PlaylistEngineFactory *playlistFactory; +}; + +static void playlist_manager_destroy_engine (void *ptr); + + +PlaylistManager * +playlist_manager_new (void) +{ + PlaylistManager *instance = (PlaylistManager *) malloc (sizeof (PlaylistManager)); + + instance->playlists = lstFlist_create (playlist_manager_destroy_engine); + + instance->fileCatalog = file_catalog_new(); + + instance->playlistFactory = playlist_engine_factory_new(); + + return (instance); +} + +void +playlist_manager_destroy (void *ptr) +{ + PlaylistManager *instance = (PlaylistManager *) ptr; + + lstFlist_free (instance->playlists); + + playlist_engine_factory_destroy (instance->playlistFactory); + + file_catalog_destroy (instance->fileCatalog); + + free (instance); +} + +static void +playlist_manager_destroy_engine (void *ptr) +{ + IPlaylist *playlist = (IPlaylist *) ptr; + + playlist->destroy (playlist); +} + +static IPlaylist * +playlist_manager_get_engine (PlaylistManager *instance, const char *playlistName) +{ + lstTlist_elem *elem = lstFlist_head (instance->playlists); + + for (; elem; elem = lstFlist_next (elem)) + { + IPlaylist *playlist = (IPlaylist *) lstFlist_data (elem); + + if (strcmp (playlistName, playlist->get_name (playlist)) == 0) + { + return (playlist); + } + } + + return (NULL); +} + +bool +playlist_manager_add_playlist (PlaylistManager *instance, const char *playlistType, const char *playlistName) +{ + if (playlist_manager_get_engine (instance, playlistName) != NULL) + { + return (false); + } + + IPlaylist *playlist = playlist_engine_factory_get_playlist (instance->playlistFactory, + playlistType, playlistName); + + if (playlist == NULL) + { + return (false); + } + + lstFlist_add_next (instance->playlists, lstFlist_tail (instance->playlists), playlist); + + return (true); +} + +bool +playlist_manager_add_file (PlaylistManager *instance, const char *playlistName, const char *fileName) +{ + IPlaylist *playlist; + + playlist = playlist_manager_get_engine (instance, playlistName); + + if (playlist == NULL) + { + return (false); + } + + int fileId = file_catalog_get_fileid (instance->fileCatalog, fileName); + + return (playlist->add_file (playlist, fileId)); +} + +bool +playlist_manager_add_filelist (PlaylistManager *instance, const char *playlistName, const char *fileName) +{ + IPlaylist *playlist; + + playlist = playlist_manager_get_engine (instance, playlistName); + + if (playlist == NULL) + { + return (false); + } + + struct stat sbuf; + + if (stat (fileName, &sbuf) != 0) + { + logFmsg (CONT_LOG_ERROR, "mod/m3: Couldn't open file: %s", fileName); + + return (false); + } + + FILE *fp = fopen (fileName, "r"); + + if (fp == NULL) + { + logFmsg (CONT_LOG_ERROR, "mod/m3: Couldn't open file: %s", fileName); + + return (false); + } + + char strbuf[NAME_MAX+1]; + + while (fgets (strbuf, sizeof (strbuf), fp) != NULL) + { + char *nl; + + if (strlen (strbuf) > 0 && (nl = strpbrk (strbuf, "\n\r"))) + { + *nl = 0; + + if (strbuf[0] == '#') + continue; + + /* + * BUGBUG: We shouldn't be doing this check once we allow for + * transports other than local disk for reading mp3's. + */ + if (stat (strbuf, &sbuf) != 0) + { + logFmsg (CONT_LOG_ERROR, "mod/m3: No such file or directory: %s", strbuf); + continue; + } + + int fileId = file_catalog_get_fileid (instance->fileCatalog, strbuf); + + playlist->add_file (playlist, fileId); + } + } + + fclose (fp); + + return (true); +} + +FileEntry * +playlist_manager_get_next_file_entry (PlaylistManager *instance) +{ + lstTlist_elem *elem = lstFlist_head (instance->playlists); + + for (; elem; elem = lstFlist_next (elem)) + { + IPlaylist *playlist = (IPlaylist *) lstFlist_data (elem); + + int fileId = playlist->get_next (playlist); + + if (fileId != -1) + { + return (file_catalog_get_file_entry (instance->fileCatalog, fileId)); + } + } + + return (NULL); +} + + diff --git a/lc-continuity/mk4/modm3/src/queue_playlist_engine.c b/lc-continuity/mk4/modm3/src/queue_playlist_engine.c new file mode 100644 index 0000000000000000000000000000000000000000..da16d6b7f6d422c4aaf529bbe35218cb7b254b4d --- /dev/null +++ b/lc-continuity/mk4/modm3/src/queue_playlist_engine.c @@ -0,0 +1,148 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mecha.h" + +#include "iplaylist.h" +#include "playlist.h" + +#include "list_iterator.h" + +#include "queue_playlist_engine.h" + + +static void queue_playlist_engine_destroy (IPlaylist *inst); +static const char * queue_playlist_engine_get_name (IPlaylist *inst); +static const char * queue_playlist_engine_get_type (MECHA_UNUSED_ARGUMENT IPlaylist *inst); +static int queue_playlist_engine_get_next (IPlaylist *inst); +static bool queue_playlist_engine_add_file (IPlaylist *inst, int fileId); +static bool queue_playlist_engine_remove_file (IPlaylist *inst, int fileId); +static IIterator * queue_playlist_engine_get_list_iterator (IPlaylist *inst); + + +struct s_QueuePlaylistEngine +{ + IPlaylist interface; + + char *playlist_name; + + lstTlist *filelist; +}; + +QueuePlaylistEngine * +queue_playlist_engine_init (const char *playlistName) +{ + QueuePlaylistEngine *instance = (QueuePlaylistEngine *) malloc (sizeof (QueuePlaylistEngine)); + + instance->interface.destroy = queue_playlist_engine_destroy; + + instance->interface.get_name = queue_playlist_engine_get_name; + instance->interface.get_type = queue_playlist_engine_get_type; + + instance->interface.get_next = queue_playlist_engine_get_next; + instance->interface.add_file = queue_playlist_engine_add_file; + instance->interface.remove_file = queue_playlist_engine_remove_file; + + instance->interface.get_list_iterator = queue_playlist_engine_get_list_iterator; + instance->interface.get_next_iterator = queue_playlist_engine_get_list_iterator; + + instance->playlist_name = strFcopy (playlistName); + instance->filelist = lstFlist_create (NULL); + + return (instance); +} + +static void +queue_playlist_engine_destroy (IPlaylist *inst) +{ + QueuePlaylistEngine *instance = (QueuePlaylistEngine *) inst; + + free (instance->playlist_name); + + lstFlist_free (instance->filelist); + + free (instance); +} + +static const char * +queue_playlist_engine_get_name (IPlaylist *inst) +{ + QueuePlaylistEngine *instance = (QueuePlaylistEngine *) inst; + + return (instance->playlist_name); +} + +static const char * +queue_playlist_engine_get_type (MECHA_UNUSED_ARGUMENT IPlaylist *inst) +{ + return ("queue"); +} + +static int +queue_playlist_engine_get_next (IPlaylist *inst) +{ + QueuePlaylistEngine *instance = (QueuePlaylistEngine *) inst; + int retFileId; + + if (lstFlist_size (instance->filelist) == 0) + { + return (-1); + } + + lstFlist_remove (instance->filelist, lstFlist_head (instance->filelist), + (void **) &retFileId); + + return (retFileId); +} + +static bool +queue_playlist_engine_add_file (IPlaylist *inst, int fileId) +{ + QueuePlaylistEngine *instance = (QueuePlaylistEngine *) inst; + + lstFlist_add_next (instance->filelist, lstFlist_tail (instance->filelist), (void *) fileId); + + return (true); +} + +static bool +queue_playlist_engine_remove_file (IPlaylist *inst, int fileId) +{ + QueuePlaylistEngine *instance = (QueuePlaylistEngine *) inst; + + bool retRemoved = false; + + lstTlist_elem *elem = lstFlist_head (instance->filelist); + + while (elem) + { + lstTlist_elem *next = lstFlist_next (elem); + + if ((int) lstFlist_data (elem) == fileId) + { + lstFlist_remove (instance->filelist, elem, NULL); + + retRemoved = true; + } + + elem = next; + } + + return (retRemoved); +} + +static IIterator * +queue_playlist_engine_get_list_iterator (IPlaylist *inst) +{ + QueuePlaylistEngine *instance = (QueuePlaylistEngine *) inst; + + return ((IIterator *) list_iterator_new (instance->filelist)); +} diff --git a/lc-continuity/mk4/modm3/src/randomlist_playlist_engine.c b/lc-continuity/mk4/modm3/src/randomlist_playlist_engine.c new file mode 100644 index 0000000000000000000000000000000000000000..c286964ac3ac0d531834310958ac82975b524908 --- /dev/null +++ b/lc-continuity/mk4/modm3/src/randomlist_playlist_engine.c @@ -0,0 +1,377 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mecha.h" + +#include "iplaylist.h" + +#include "file_entry.h" + +#include "randomlist_playlist_engine.h" + +struct s_RandomlistPlaylistEngine +{ + IPlaylist interface; + + char *playlistName; + + lstTlist *fileIdList; + + int randomizedListOffset; + int randomizedListLen; + + int *randomizedList; +}; + + +#define GET_RANDOM(__low,__high) (__low + (double) random() * (__high - __low + 1) / RAND_MAX) + +static void randomlist_playlist_engine_destroy (IPlaylist *inst); +static const char * randomlist_playlist_engine_get_name (IPlaylist *inst); +static const char * randomlist_playlist_engine_get_type (MECHA_UNUSED_ARGUMENT IPlaylist *inst); +static int randomlist_playlist_engine_get_next (IPlaylist *inst); +static bool randomlist_playlist_engine_add_file (IPlaylist *inst, int fileId); +static bool randomlist_playlist_engine_remove_file (IPlaylist *inst, int fileId); +#if 0 +static IIterator * randomlist_playlist_engine_get_list_iterator (IPlaylist *inst); +static IIterator * randomlist_playlist_engine_get_next_iterator (IPlaylist *inst); +#endif + +RandomlistPlaylistEngine * +randomlist_playlist_engine_init (const char *playlistName) +{ + RandomlistPlaylistEngine *instance = (RandomlistPlaylistEngine *) malloc (sizeof (RandomlistPlaylistEngine)); + + instance->interface.destroy = randomlist_playlist_engine_destroy; + + instance->interface.get_name = randomlist_playlist_engine_get_name; + instance->interface.get_type = randomlist_playlist_engine_get_type; + + instance->interface.get_next = randomlist_playlist_engine_get_next; + instance->interface.add_file = randomlist_playlist_engine_add_file; + instance->interface.remove_file = randomlist_playlist_engine_remove_file; + +#if 0 + instance->interface.get_list_iterator = randomlist_playlist_engine_get_list_iterator; + instance->interface.get_next_iterator = randomlist_playlist_engine_get_next_iterator; +#endif + + instance->interface.get_list_iterator = NULL; + instance->interface.get_next_iterator = NULL; + + instance->playlistName = strFcopy (playlistName); + + instance->fileIdList = lstFlist_create (NULL); + + instance->randomizedListOffset = 0; + instance->randomizedListLen = 0; + + instance->randomizedList = NULL; + + return (instance); +} + +static void +randomlist_playlist_engine_destroy (IPlaylist *inst) +{ + RandomlistPlaylistEngine *instance = (RandomlistPlaylistEngine *) inst; + + free (instance->playlistName); + + lstFlist_free (instance->fileIdList); + + if (instance->randomizedListLen > 0) + { + free (instance->randomizedList); + } + + free (instance); +} + +static const char * +randomlist_playlist_engine_get_name (IPlaylist *inst) +{ + RandomlistPlaylistEngine *instance = (RandomlistPlaylistEngine *) inst; + + return (instance->playlistName); +} + +static const char * +randomlist_playlist_engine_get_type (MECHA_UNUSED_ARGUMENT IPlaylist *inst) +{ + return ("randomlist"); +} + +static int +randomlist_playlist_engine_get_next (IPlaylist *inst) +{ + RandomlistPlaylistEngine *instance = (RandomlistPlaylistEngine *) inst; + + if (lstFlist_size (instance->fileIdList) == 0) + { + return (-1); + } + + if (instance->randomizedListLen > 0 && instance->randomizedListOffset >= instance->randomizedListLen) + { + logFmsg (CONT_LOG_OK, "mod/m3: Resetting randomized list."); + + instance->randomizedListLen = 0; + instance->randomizedListOffset = 0; + + free (instance->randomizedList); + + instance->randomizedList = NULL; + } + + if (instance->randomizedListLen == 0) + { + int numAssigned = 0; + + instance->randomizedListLen = lstFlist_size (instance->fileIdList); + + instance->randomizedList = (int *) malloc (sizeof (int) * instance->randomizedListLen); + + /* Copy all of the elements from the list to the array */ + int i = 0; + for (lstTlist_elem *ep = lstFlist_head (instance->fileIdList); ep; ep = lstFlist_next (ep)) + { + instance->randomizedList[i++] = (int) lstFlist_data (ep); + } + + /* iterate through all elements and randomize them */ + int newPos; + int savedData; + + for (i = 0; i < instance->randomizedListLen; i++) + { + newPos = GET_RANDOM (0, instance->randomizedListLen - 1); + savedData = instance->randomizedList[newPos]; + instance->randomizedList[newPos] = instance->randomizedList[i]; + instance->randomizedList[i] = savedData; + } + + instance->randomizedListOffset = 0; + } + + return (instance->randomizedList[instance->randomizedListOffset++]); +} + +static bool +randomlist_playlist_engine_add_file (IPlaylist *inst, int fileId) +{ + RandomlistPlaylistEngine *instance = (RandomlistPlaylistEngine *) inst; + + if (instance->randomizedListLen > 0) + { + instance->randomizedList = realloc (instance->randomizedList, sizeof (int) * (instance->randomizedListLen + 1)); + + int ranum = GET_RANDOM (instance->randomizedListOffset, instance->randomizedListLen); + + instance->randomizedList[instance->randomizedListLen] = instance->randomizedList[ranum]; + instance->randomizedList[ranum] = fileId; + + instance->randomizedListLen++; + } + + lstFlist_add_next (instance->fileIdList, lstFlist_tail (instance->fileIdList), (void *) fileId); + + return (true); +} + +static bool +randomlist_playlist_engine_remove_file (IPlaylist *inst, int fileId) +{ + RandomlistPlaylistEngine *instance = (RandomlistPlaylistEngine *) inst; + lstTlist_elem *elem; + + for (elem = lstFlist_head (instance->fileIdList); elem; elem = lstFlist_next (elem)) + { + int curFileId = (int) lstFlist_data (elem); + + if (curFileId == fileId) + { + lstFlist_remove (instance->fileIdList, elem, NULL); + + break; + } + } + + if (elem == NULL) + { + return (false); + } + + /* + * remove from the list of files to play. if it already played, we don't + * need to remove it + */ + for (int i = instance->randomizedListOffset; i < instance->randomizedListLen; i++) + { + if (instance->randomizedList[i] == fileId) + { + instance->randomizedList[i] = instance->randomizedList[instance->randomizedListLen - 1]; + + instance->randomizedListLen--; + + instance->randomizedList = realloc (instance->randomizedList, sizeof (int) * (instance->randomizedListLen)); + + break; + } + } + + return (true); +} + +#if 0 +static int +randomlist_playlist_engine_contains_file (playlist *p, const char *filename) +{ + lstTlist_elem *ep; + + for (ep = lstFlist_head (instance->fileIdList); ep; ep = lstFlist_next (ep)) + { + FileEntry *fe = (FileEntry *) lstFlist_data (ep); + + if (strcmp (filename, file_entry_get_filename (fe)) == 0) + { + return (1); + } + } + + return (0); +} + +static int +randomlist_playlist_engine_contains_string (lstTlist *lst, const char *value) +{ + lstTlist_elem *ep; + + for (ep = lstFlist_head (lst); ep; ep = lstFlist_next (ep)) + { + const char *entry = (const char *) lstFlist_data (ep); + + if (strcmp (value, entry) == 0) + { + return (1); + } + } + + return (0); +} + +static int +randomlist_playlist_engine_reload_filelist (playlist *p, const char *filelist) +{ + struct stat sbuf; + FILE *fp; + char strbuf[NAME_MAX+1]; + lstTlist *removedFiles; + lstTlist *addedFiles; + lstTlist *newList; + + if (stat (filelist, &sbuf) != 0) + return (-errno); + + if (!(fp = fopen (filelist, "r"))) + { + logFmsg (CONT_LOG_ERROR, "couldn't open file %s", filelist); + fclose (fp); + return (1); + } + + removedFiles = lstFlist_create (NULL); + newList = lstFlist_create (free); + addedFiles = lstFlist_create (NULL); + + while (fgets (strbuf, sizeof (strbuf), fp) != NULL) + { + char *nl; + + if (strlen (strbuf) > 0 && (nl = strpbrk (strbuf, "\n\r"))) + { + *nl = 0; + + if (strbuf[0] == '#') + continue; + + if (stat (strbuf, &sbuf) != 0) + { + logFmsg (CONT_LOG_ERROR, "%s: no such file or directory", strbuf); + continue; + } + + { + char *fileEntryName = strFcopy (strbuf); + + lstFlist_add_next (newList, lstFlist_tail (newList), + fileEntryName); + + if (randomlist_playlist_engine_contains_file (p, strbuf) == 0) + { + lstFlist_add_next (addedFiles, lstFlist_tail (addedFiles), + fileEntryName); + } + } + } + } + + fclose (fp); + + { + lstTlist_elem *ep; + + for (ep = lstFlist_head (instance->fileIdList); ep; ep = lstFlist_next (ep)) + { + FileEntry *fe = (FileEntry *) lstFlist_data (ep); + + if (randomlist_playlist_engine_contains_string (newList, + file_entry_get_filename (fe)) == 0) + { + lstFlist_add_next (removedFiles, lstFlist_tail (removedFiles), + (void *) file_entry_get_filename (fe)); + } + } + } + + { + lstTlist_elem *ep; + + for (ep = lstFlist_head (addedFiles); ep; ep = lstFlist_next (ep)) + { + const char *entry = (const char *) lstFlist_data (ep); + + logFmsg (CONT_LOG_DEBUG, "m3/randomlist: %s added to playlist.", entry); + + randomlist_playlist_engine_add_file (p, file_entry_new (entry)); + } + } + + { + lstTlist_elem *ep; + + for (ep = lstFlist_head (removedFiles); ep; ep = lstFlist_next (ep)) + { + const char *entry = (const char *) lstFlist_data (ep); + + logFmsg (CONT_LOG_DEBUG, "m3/randomlist: %s removed from playlist.", entry); + + randomlist_playlist_engine_remove_file (p, entry); + } + } + + lstFlist_free (removedFiles); + lstFlist_free (newList); + lstFlist_free (addedFiles); + + return (0); +} +#endif diff --git a/lc-continuity/mk4/modm3/src/shoutcast_metadata_writer.c b/lc-continuity/mk4/modm3/src/shoutcast_metadata_writer.c new file mode 100644 index 0000000000000000000000000000000000000000..3eed9c3efd631c50469bdd76d15c1d3c109699a0 --- /dev/null +++ b/lc-continuity/mk4/modm3/src/shoutcast_metadata_writer.c @@ -0,0 +1,191 @@ + +#include + +#include "mecha.h" +#include "http.h" + +#include "shoutcast_metadata_writer.h" + +struct s_ShoutcastMetadataWriter +{ + httpTtrans *trans; + + bool writeMetadata; + + int bytesUntilNext; + + int metadataInterval; + + bool haveData; + + dynTstring *metadataTitle; + dynTstring *metadataUrl; +}; + + +static bool shoutcast_metadata_writer_write_http (ShoutcastMetadataWriter *instance, const char *buf, size_t len); +static bool shoutcast_metadata_writer_write_metadata (ShoutcastMetadataWriter *instance); + +ShoutcastMetadataWriter * +shoutcast_metadata_writer_new (httpTtrans *trans, bool writeMetadata, int metadataInterval) +{ + ShoutcastMetadataWriter *instance = (ShoutcastMetadataWriter *) malloc (sizeof (ShoutcastMetadataWriter)); + + instance->trans = trans; + + instance->writeMetadata = writeMetadata; + + instance->bytesUntilNext = metadataInterval; + instance->metadataInterval = metadataInterval; + + instance->haveData = false; + + instance->metadataTitle = dynFinit(); + instance->metadataUrl = dynFinit(); + + return (instance); +} + +void +shoutcast_metadata_writer_destroy (void *ptr) +{ + ShoutcastMetadataWriter *instance = (ShoutcastMetadataWriter *) ptr; + + dynFfree (instance->metadataTitle); + dynFfree (instance->metadataUrl); + + free (instance); +} + +void +shoutcast_metadata_writer_set_metadata (ShoutcastMetadataWriter *instance, const char *title, const char *url) +{ + dynFreset (instance->metadataTitle); + dynFreset (instance->metadataUrl); + + if (title != NULL) + { + dynFsappend (instance->metadataTitle, title); + } + + if (url != NULL) + { + dynFsappend (instance->metadataUrl, url); + } + + instance->haveData = true; +} + +bool +shoutcast_metadata_writer_write (ShoutcastMetadataWriter *instance, dynTstring *data) +{ + /* if we don't need to do anything special.. */ + if (instance->writeMetadata == false) + { + bool ret = shoutcast_metadata_writer_write_http (instance, dynFgetstr (data), + dynFgetlen (data)); + + return (ret); + } + else + { + bool ret; + const char *dataPtr = dynFgetstr (data); + int lenRemaining = dynFgetlen (data); + + while (lenRemaining > 0) + { + int writeLen; + + if (lenRemaining < instance->bytesUntilNext) + { + writeLen = lenRemaining; + } + else + { + writeLen = instance->bytesUntilNext; + } + + ret = shoutcast_metadata_writer_write_http (instance, dataPtr, writeLen); + + if (ret == false) + { + return (false); + } + + lenRemaining -= writeLen; + dataPtr += writeLen; + instance->bytesUntilNext -= writeLen; + + if (instance->bytesUntilNext == 0) + { + ret = shoutcast_metadata_writer_write_metadata (instance); + + if (ret == false) + { + return (false); + } + + instance->bytesUntilNext = instance->metadataInterval; + } + } + + return (true); + } +} + +static bool +shoutcast_metadata_writer_write_http (ShoutcastMetadataWriter *instance, const char *buf, size_t len) +{ + ssize_t ret = httpFwrite (instance->trans, buf, len); + + if (ret != (ssize_t) len) + { + return (false); + } + else + { + return (true); + } +} + +static bool +shoutcast_metadata_writer_write_metadata (ShoutcastMetadataWriter *instance) +{ + if (instance->haveData == true) + { + char *metabuf; + int padding, len; + int bufsize = dynFgetlen (instance->metadataTitle) + dynFgetlen (instance->metadataUrl) + 32; + bool ret; + + metabuf = (char *) malloc (bufsize); + + memset (metabuf, 0, bufsize); + + len = snprintf (metabuf + 1, bufsize - 1, "StreamTitle='%s';StreamUrl='%s';", + dynFgetstr (instance->metadataTitle), dynFgetstr (instance->metadataUrl)); + + padding = 16 - (len % 16); + + len += padding; + + metabuf[0] = len / 16; + + len += 1; + + ret = shoutcast_metadata_writer_write_http (instance, metabuf, len); + + free (metabuf); + + instance->haveData = false; + + return (ret); + } + else + { + char emptyByte = 0; + + return (shoutcast_metadata_writer_write_http (instance, &emptyByte, 1)); + } +} diff --git a/lc-continuity/mk4/modm3/src/support.c b/lc-continuity/mk4/modm3/src/support.c new file mode 100644 index 0000000000000000000000000000000000000000..a3b73639b0455ce7b2985c3e3900a6916b8d2786 --- /dev/null +++ b/lc-continuity/mk4/modm3/src/support.c @@ -0,0 +1,57 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "support.h" + +int +ixmmap_open (const char *filename, char **buf, int *len) +{ + int fd, e; + void *map; + struct stat sbuf; + + if ((fd = open (filename, O_RDONLY)) == -1) + return (-errno); + + if (fstat (fd, &sbuf) == -1) + { + e = errno; + close (fd); + return (-e); + } + + if ((map = mmap (0, sbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED) + { + e = errno; + close (fd); + return (-e); + } + + close (fd); + + *buf = map; + *len = sbuf.st_size; + + return (0); +} + +int +ixmmap_close (char *buf, int len) +{ + if (munmap (buf, len) == -1) + return (-errno); + + return (0); +} + diff --git a/lc-continuity/mk4/modmobility/CVS/Entries b/lc-continuity/mk4/modmobility/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..26943075a7109939b924f33cd91afafa0b5c5997 --- /dev/null +++ b/lc-continuity/mk4/modmobility/CVS/Entries @@ -0,0 +1,3 @@ +/Makefile/1.1/Fri May 14 17:53:17 2004//Tmk4_mod6_rc2 +D/include//// +D/src//// diff --git a/lc-continuity/mk4/modmobility/CVS/Repository b/lc-continuity/mk4/modmobility/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..a430bc01ccdc009a8f87a9bf9ec2e248d9b60eb7 --- /dev/null +++ b/lc-continuity/mk4/modmobility/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/modmobility diff --git a/lc-continuity/mk4/modmobility/CVS/Root b/lc-continuity/mk4/modmobility/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/modmobility/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/modmobility/CVS/Tag b/lc-continuity/mk4/modmobility/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/modmobility/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/modmobility/Makefile b/lc-continuity/mk4/modmobility/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..4c05afc355a46446d0da5d9bdcc23cb77af8c099 --- /dev/null +++ b/lc-continuity/mk4/modmobility/Makefile @@ -0,0 +1,13 @@ +CONTINUITY = ../continuity + +TARGET = mobility +TARGETTYPE = module + +SOURCES = src/mobility.c src/handler.c src/mobilitytable.c src/http_request.c \ + src/http_request_list.c src/http_message_handler.c + +INCLUDES += -Iinclude -I../lib/aura/include -I../lib/causality/include +STATIC_LIBS += $(CONTINUITY)/lib/libaura.a $(CONTINUITY)/lib/libcausality.a +#LOCAL_CFLAGS += + +include $(CONTINUITY)/lib/build.mk diff --git a/lc-continuity/mk4/modmobility/include/CVS/Entries b/lc-continuity/mk4/modmobility/include/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..b7f4e02025ba25acd577affac6b2febcf93ea0e0 --- /dev/null +++ b/lc-continuity/mk4/modmobility/include/CVS/Entries @@ -0,0 +1,6 @@ +/http_message_handler.h/1.1/Thu May 13 21:15:33 2004//Tmk4_mod6_rc2 +/http_request.h/1.2/Fri May 14 16:51:26 2004//Tmk4_mod6_rc2 +/http_request_list.h/1.1/Thu May 13 21:15:33 2004//Tmk4_mod6_rc2 +/mobility.h/1.1/Thu May 13 21:15:33 2004//Tmk4_mod6_rc2 +/mobilitytable.h/1.1/Thu May 13 21:15:33 2004//Tmk4_mod6_rc2 +D diff --git a/lc-continuity/mk4/modmobility/include/CVS/Repository b/lc-continuity/mk4/modmobility/include/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..a1ae984cfd3148e0151d0a73db937a9bb07fbea4 --- /dev/null +++ b/lc-continuity/mk4/modmobility/include/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/modmobility/include diff --git a/lc-continuity/mk4/modmobility/include/CVS/Root b/lc-continuity/mk4/modmobility/include/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/modmobility/include/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/modmobility/include/CVS/Tag b/lc-continuity/mk4/modmobility/include/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/modmobility/include/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/modmobility/include/http_message_handler.h b/lc-continuity/mk4/modmobility/include/http_message_handler.h new file mode 100644 index 0000000000000000000000000000000000000000..6900a55ee5d17af779dcc8fc09ddc2dfa4dddae8 --- /dev/null +++ b/lc-continuity/mk4/modmobility/include/http_message_handler.h @@ -0,0 +1,13 @@ +#ifndef __HTTP_MESSAGE_HANDLER_H__ +#define __HTTP_MESSAGE_HANDLER_H__ + +Message * http_message_handler_processWriteMessage (void *context, Message *requestMessage); +Message * http_message_handler_processFinishMessage (void *context, Message *requestMessage); +Message * http_message_handler_processReadEntityBody (void *context, Message *requestMessage); +Message * http_message_handler_handlePing (void *context, Message *requestMessage); + +extern CommandHandler command_HttpWrite; +extern CommandHandler command_HttpFinish; +extern CommandHandler command_HttpReadEntityBody; + +#endif diff --git a/lc-continuity/mk4/modmobility/include/http_request.h b/lc-continuity/mk4/modmobility/include/http_request.h new file mode 100644 index 0000000000000000000000000000000000000000..3b0d67934fe77b1158a4e453ba0f7adc58288e9e --- /dev/null +++ b/lc-continuity/mk4/modmobility/include/http_request.h @@ -0,0 +1,27 @@ +#ifndef __HTTP_REQUEST_H__ +#define __HTTP_REQUEST_H__ + +#include "http.h" +#include "processor.h" +#include "stringdictionary.h" + +typedef struct s_HttpRequest HttpRequest; + +HttpRequest * http_request_new (httpTtrans *trans, Processor *proc); +void http_request_destroy (void *ptr); + +const char * http_request_getToken (HttpRequest *resp); +int http_request_getResponse (HttpRequest *resp); +void http_request_setResponse (HttpRequest *resp, int response); + +bool http_request_sendRequestStart (HttpRequest *resp); + +bool http_request_write (HttpRequest *request, dynTstring *string); + +httpTtrans * http_request_getHttpTrans (HttpRequest *resp); + +void http_request_setResponseHeaders (HttpRequest *request, StringDictionary *responseHeaders); + +void http_request_setStatus (HttpRequest *request, int status, const char *reason); + +#endif diff --git a/lc-continuity/mk4/modmobility/include/http_request_list.h b/lc-continuity/mk4/modmobility/include/http_request_list.h new file mode 100644 index 0000000000000000000000000000000000000000..1c465b6499faf40b844d1dc8eb22d88c5952c9ae --- /dev/null +++ b/lc-continuity/mk4/modmobility/include/http_request_list.h @@ -0,0 +1,20 @@ +#ifndef __HTTP_REQUEST_LIST_H__ +#define __HTTP_REQUEST_LIST_H__ + +#include "http_request.h" + +#include "http.h" + +typedef struct s_HttpRequestList HttpRequestList; + +HttpRequestList * http_request_list_new (void); +void http_request_list_destroy (void *ptr); + +void http_request_list_addRequest (HttpRequestList *request_list, HttpRequest *resp); +void http_request_list_removeRequest (HttpRequestList *request_list, const char *token); + +HttpRequest * http_request_list_getRequest (HttpRequestList *request_list, const char *token); + +dynTstring * http_request_list_getDiag (HttpRequestList *request_list); + +#endif diff --git a/lc-continuity/mk4/modmobility/include/mobility.h b/lc-continuity/mk4/modmobility/include/mobility.h new file mode 100644 index 0000000000000000000000000000000000000000..c6cf04ccb97c57fb01fdc3baa2e2769338039ac0 --- /dev/null +++ b/lc-continuity/mk4/modmobility/include/mobility.h @@ -0,0 +1,20 @@ +#ifndef __MOBILITY_H_ +#define __MOBILITY_H_ + +#include "http.h" +#include "http_request.h" + +typedef struct s_Mobility Mobility; + +Mobility * mobility_new (const char *executable); +void mobility_destroy (void *ptr); + +int mobility_sendRequest (Mobility *mob, httpTtrans *trans); + +HttpRequest * mobility_getRequest (Mobility *mobility, const char *token); + +dynTstring *mobility_getRequestDiag (Mobility *mobility); + +int mobility_getPid (Mobility *mob); + +#endif diff --git a/lc-continuity/mk4/modmobility/include/mobilitytable.h b/lc-continuity/mk4/modmobility/include/mobilitytable.h new file mode 100644 index 0000000000000000000000000000000000000000..12c30a9f00a54b918dd1ee2357c41274870140bf --- /dev/null +++ b/lc-continuity/mk4/modmobility/include/mobilitytable.h @@ -0,0 +1,17 @@ +#ifndef __MOBILITYTABLE_H_ +#define __MOBILITYTABLE_H_ + +#include "mobility.h" + +typedef struct s_MobilityTable MobilityTable; + +MobilityTable * mobilitytable_new (void); +void mobilitytable_destroy (void *ptr); + +Mobility * mobilitytable_getMobilityEntry (MobilityTable *mtable, const char *executable); + +Mobility * mobilitytable_getMobilityEntryByPid (MobilityTable *mtable, int pid); + +MobilityTable * mobilitytable_getTable(void); + +#endif diff --git a/lc-continuity/mk4/modmobility/src/CVS/Entries b/lc-continuity/mk4/modmobility/src/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..ce21334d454e124b79f573644c9aab86a50b89b2 --- /dev/null +++ b/lc-continuity/mk4/modmobility/src/CVS/Entries @@ -0,0 +1,7 @@ +/handler.c/1.1/Thu May 13 21:15:33 2004//Tmk4_mod6_rc2 +/http_message_handler.c/1.2/Fri May 14 16:51:27 2004//Tmk4_mod6_rc2 +/http_request.c/1.3/Sun May 16 20:31:59 2004//Tmk4_mod6_rc2 +/http_request_list.c/1.1/Thu May 13 21:15:33 2004//Tmk4_mod6_rc2 +/mobility.c/1.5/Wed May 19 18:19:53 2004//Tmk4_mod6_rc2 +/mobilitytable.c/1.1/Thu May 13 21:15:33 2004//Tmk4_mod6_rc2 +D diff --git a/lc-continuity/mk4/modmobility/src/CVS/Repository b/lc-continuity/mk4/modmobility/src/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..909c29e29b61c0352f351cee4f263c70c8dc9400 --- /dev/null +++ b/lc-continuity/mk4/modmobility/src/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/modmobility/src diff --git a/lc-continuity/mk4/modmobility/src/CVS/Root b/lc-continuity/mk4/modmobility/src/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/modmobility/src/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/modmobility/src/CVS/Tag b/lc-continuity/mk4/modmobility/src/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/modmobility/src/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/modmobility/src/handler.c b/lc-continuity/mk4/modmobility/src/handler.c new file mode 100644 index 0000000000000000000000000000000000000000..6d5175df7ac2d03a158d0c3e60674e53f58b72ba --- /dev/null +++ b/lc-continuity/mk4/modmobility/src/handler.c @@ -0,0 +1,54 @@ + +#include +#include + +#include "http.h" + +#include "mobilitytable.h" +#include "mobility.h" + + +int mobility_init (void); +int mobility_handler (httpTtrans *t, lstTset *opts); + +int +mobility_init() +{ + return (STATUS_PROCEED); +} + +int +mobility_handler (httpTtrans *t, lstTset *opts) +{ + const char *handler; + const char *mimetype; + Mobility *mob; + + mimetype = lstFset_get (opts, "mimetype"); + + if (mimetype != NULL) + { + const char *this_mimetype = lstFset_get (t->res_hdrs, "Content-Type"); + + if (this_mimetype == NULL || strcmp (mimetype, this_mimetype) != 0) + { + return (STATUS_PROCEED); + } + } + + handler = lstFset_get (opts, "handler"); + + mob = mobilitytable_getMobilityEntry (mobilitytable_getTable(), handler); + + if (mob == NULL) + { + logFmsg (CONT_LOG_ERROR, "mobility: Couldn't get a mobility entry."); + + /* we couldn't function.. we'll just keep on going */ + return (STATUS_PROCEED); + } + else + { + return (mobility_sendRequest (mob, t)); + } +} diff --git a/lc-continuity/mk4/modmobility/src/http_message_handler.c b/lc-continuity/mk4/modmobility/src/http_message_handler.c new file mode 100644 index 0000000000000000000000000000000000000000..9895326d6a2fef38015e6b34aa0583bccab5dc36 --- /dev/null +++ b/lc-continuity/mk4/modmobility/src/http_message_handler.c @@ -0,0 +1,253 @@ + +#include "message.h" +#include "http_request.h" +#include "mobility.h" + +#include "command.h" + +#include "serialization.h" + +Message * http_message_handler_processWriteMessage (void *context, Message *requestMessage); +Message * http_message_handler_processFinishMessage (void *context, Message *requestMessage); +Message * http_message_handler_processReadEntityBody (void *context, Message *requestMessage); +Message * http_message_handler_handlePing (void *context, Message *requestMessage); + + +static const char *command_HttpWrite_RequiredParameters[] = { "token", "data", NULL }; +static const char *command_HttpWrite_OptionalParameters[] = { "responseHeaders", "status", NULL }; +CommandHandler command_HttpWrite = { "HttpWrite", http_message_handler_processWriteMessage, + command_HttpWrite_RequiredParameters, command_HttpWrite_OptionalParameters }; + +static const char *command_HttpFinish_RequiredParameters[] = { "token", "returnStatus", NULL }; +static const char *command_HttpFinish_OptionalParameters[] = { NULL }; +CommandHandler command_HttpFinish = { "HttpFinish", http_message_handler_processFinishMessage, + command_HttpFinish_RequiredParameters, command_HttpFinish_OptionalParameters }; + +static const char *command_HttpReadEntityBody_RequiredParameters[] = { "token", NULL }; +static const char *command_HttpReadEntityBody_OptionalParameters[] = { NULL }; +CommandHandler command_HttpReadEntityBody = { "HttpReadEntityBody", http_message_handler_processReadEntityBody, + command_HttpReadEntityBody_RequiredParameters, command_HttpReadEntityBody_OptionalParameters }; + +static const char *command_HttpPing_RequiredParameters[] = { "token", NULL }; +static const char *command_HttpPing_OptionalParameters[] = { NULL }; +CommandHandler command_HttpPing = { "HttpPing", http_message_handler_processReadEntityBody, + command_HttpPing_RequiredParameters, command_HttpPing_OptionalParameters }; + + +static Message * +http_message_handler_createErrorMessage (Message *requestMessage, const char *message, const char *token) +{ + Message *response = message_makeErrorResponse (requestMessage); + + message_setParameter (response, "message", message); + + if (token != NULL) + { + message_setParameter (response, "token", token); + } + + return (response); +} + +Message * +http_message_handler_processWriteMessage (void *context, Message *requestMessage) +{ + Mobility *mobility = (Mobility *) context; + HttpRequest *request; + const char *token = message_getParameter (requestMessage, "token"); + + request = mobility_getRequest (mobility, token); + + if (request == NULL) + { + dynTstring *diag; + + Message *responseMessage = + http_message_handler_createErrorMessage (requestMessage, + "Could not find specified request.", token); + + diag = mobility_getRequestDiag (mobility); + + message_setParameterString (responseMessage, "hash_diag", diag); + + dynFfree (diag); + + return (responseMessage); + } + + { + dynTstring *serializedResponseHeaders; + + serializedResponseHeaders = message_getParameterString ( + requestMessage, "responseHeaders"); + + if (serializedResponseHeaders != NULL) + { + StringDictionary *responseHeaders; + + serialization_deserializeType ("StringDictionary", + &responseHeaders, serializedResponseHeaders); + + http_request_setResponseHeaders (request, responseHeaders); + + stringdictionary_destroy (responseHeaders); + } + } + + { + dynTstring *status = message_getParameterString ( + requestMessage, "status"); + + if (status != NULL) + { + int status_int = atoi (dynFgetstr (status)); + + /* currently not using the string */ + http_request_setStatus (request, status_int, NULL); + } + } + + { + Message *response; + dynTstring *data = message_getParameterString (requestMessage, "data"); + + if (http_request_write (request, data) == true) + { + response = message_makeResponse (requestMessage); + + message_setParameter (response, "message", "Data written."); + } + else + { + response = message_makeErrorResponse (requestMessage); + + message_setParameter (response, "message", "Did not send data."); + } + + return (response); + } +} + +Message * +http_message_handler_processFinishMessage (void *context, Message *requestMessage) +{ + Mobility *mobility = (Mobility *) context; + HttpRequest *request; + const char *token = message_getParameter (requestMessage, "token"); + + request = mobility_getRequest (mobility, token); + + if (request == NULL) + { + dynTstring *diag; + + Message *responseMessage = + http_message_handler_createErrorMessage (requestMessage, + "Could not find specified request.", token); + + diag = mobility_getRequestDiag (mobility); + + message_setParameterString (responseMessage, "hash_diag", diag); + + dynFfree (diag); + + return (responseMessage); + } + + { + Message *response; + const char *status = message_getParameter (requestMessage, "returnStatus"); + + http_request_setResponse (request, atoi (status)); + + response = message_makeResponse (requestMessage); + + message_setParameter (response, "message", "Data written."); + + return (response); + } +} + +Message * +http_message_handler_processReadEntityBody (void *context, Message *requestMessage) +{ + Mobility *mobility = (Mobility *) context; + HttpRequest *request; + const char *token = message_getParameter (requestMessage, "token"); + + if (token == NULL) + { + return (http_message_handler_createErrorMessage (requestMessage, + "Could not find required 'token' parameter.", NULL)); + } + + request = mobility_getRequest (mobility, token); + + if (request == NULL) + { + dynTstring *diag; + + Message *responseMessage = + http_message_handler_createErrorMessage (requestMessage, + "Could not find specified request.", token); + + diag = mobility_getRequestDiag (mobility); + + message_setParameterString (responseMessage, "hash_diag", diag); + + dynFfree (diag); + + return (responseMessage); + } + + { + Message *response; + httpTtrans *t = http_request_getHttpTrans (request);; + + if (httpFread_post (t) != -1) + { + response = message_makeResponse (requestMessage); + message_setParameter (response, "data", lstFset_get (t->vars, "post_query")); + } + else + { + response = http_message_handler_createErrorMessage (requestMessage, + "There was no data to retrieve.", token); + } + + return (response); + } +} + +Message * +http_message_handler_handlePing (void *context, Message *requestMessage) +{ + Mobility *mobility = (Mobility *) context; + const char *token = message_getParameter (requestMessage, "token"); + + if (mobility_getRequest (mobility, token) == NULL) + { + dynTstring *diag; + + Message *responseMessage = + http_message_handler_createErrorMessage (requestMessage, + "Could not find specified request.", token); + + diag = mobility_getRequestDiag (mobility); + + message_setParameterString (responseMessage, "hash_diag", diag); + + dynFfree (diag); + + return (responseMessage); + } + else + { + Message *responseMessage = message_makeResponse (requestMessage); + + message_setParameter (responseMessage, "message", "Request found."); + + return (responseMessage); + } +} + diff --git a/lc-continuity/mk4/modmobility/src/http_request.c b/lc-continuity/mk4/modmobility/src/http_request.c new file mode 100644 index 0000000000000000000000000000000000000000..45a9662d2d3c8315cbec3bbe369bf3a686a2f827 --- /dev/null +++ b/lc-continuity/mk4/modmobility/src/http_request.c @@ -0,0 +1,361 @@ + +#include +#include +#include +#include + +#include "mecha.h" + +#include "stringdictionary.h" +#include "http_request.h" +#include "message.h" +#include "processor.h" + +#include "http.h" + +#include "serialization.h" + +int g_pid = -1; +int g_sequence = 1; +pthread_mutex_t g_sequence_mutex = PTHREAD_MUTEX_INITIALIZER; + +static int http_request_getPid (void); +static int http_request_getNextSequence (void); + +struct s_HttpRequest +{ + dynTstring *token; + + httpTtrans *trans; + + pthread_cond_t cond; + pthread_mutex_t mutex; + + bool hasStarted; + + bool hasResponse; + + int response; + + Processor *processor; +}; + +static int +http_request_getPid() +{ + if (g_pid == -1) + { + g_pid = getpid(); + } + + return (g_pid); +} + +static int +http_request_getNextSequence() +{ + int ret; + + pthread_mutex_lock (&g_sequence_mutex); + + ret = ++g_sequence; + + pthread_mutex_unlock (&g_sequence_mutex); + + return (ret); +} + +HttpRequest * +http_request_new (httpTtrans *trans, Processor *proc) +{ + HttpRequest *resp = malloc (sizeof (HttpRequest)); + + resp->token = dynFinit(); + + dynFappend_print (resp->token, "0x%x-0x%x", http_request_getPid(), http_request_getNextSequence()); + + resp->trans = trans; + + pthread_cond_init (&resp->cond, NULL); + pthread_mutex_init (&resp->mutex, NULL); + + resp->hasResponse = false; + resp->hasStarted = false; + + resp->response = 0; + resp->processor = proc; + + httpFset_status (resp->trans, 200, "OK OK"); + + return (resp); +} + +void +http_request_destroy (void *ptr) +{ + HttpRequest *resp = (HttpRequest *) ptr; + + dynFfree (resp->token); + + pthread_cond_destroy (&resp->cond); + pthread_mutex_destroy (&resp->mutex); + + free (resp); +} + +const char * +http_request_getToken (HttpRequest *resp) +{ + return (dynFgetstr (resp->token)); +} + +httpTtrans * +http_request_getHttpTrans (HttpRequest *resp) +{ + return (resp->trans); +} + +static bool +http_request_pingRemote (HttpRequest *request) +{ + bool ret; + Message *responseMessage; + Message *startMessage = message_newRequest ("HttpRequestPing"); + + message_setParameter (startMessage, "token", + dynFgetstr (request->token)); + + ret = processor_sendMessage (request->processor, startMessage, &responseMessage); + + if (ret == false) + { + logFmsg (CONT_LOG_ERROR, "Could not send message."); + } + else + { + if (message_getType (responseMessage) == MessageTypeErrorResponse) + { + logFmsg (CONT_LOG_ERROR, "Could not find token %s - %s", dynFgetstr (request->token), + message_getParameter (responseMessage, "message")); + + ret = false; + } + else + { + ret = true; + } + + message_destroy (responseMessage); + } + + message_destroy (startMessage); + + return (ret); +} + +void +http_request_setResponseHeaders (HttpRequest *request, + StringDictionary *responseHeaders) +{ + hshTiterator *iter = stringdictionary_getIterator (responseHeaders); + + while (hshFiterator_next (iter) == 1) + { + const char *key = (const char *) hshFiterator_current_key (iter); + const dynTstring *value = (const dynTstring *) hshFiterator_current_value (iter); + + lstFset_update (request->trans->res_hdrs, key, dynFgetstr (value)); + } + + hshFiterator_free (iter); +} + +void +http_request_setStatus (HttpRequest *request, int status, const char *reason) +{ + httpFset_status (request->trans, status, reason); +} + +bool +http_request_write (HttpRequest *request, dynTstring *string) +{ + if (request->hasStarted == false) + { + httpFstart_response (request->trans); + + request->hasStarted = true; + } + + /* If we didn't have any data to send but want to send our headers */ + if (dynFgetlen (string) == 0) + { + return (true); + } + + if (httpFwrite (request->trans, dynFgetstr (string), dynFgetlen (string)) == -1) + { + http_request_setResponse (request, STATUS_ERROR); + + return (false); + } + else + { + return (true); + } +} + +int +http_request_getResponse (HttpRequest *resp) +{ + int response; + + pthread_mutex_lock (&resp->mutex); + + while (resp->hasResponse == false) + { + struct timespec waitTime = { 0, 0 }; + + waitTime.tv_sec = time(0) + 15; + + if (pthread_cond_timedwait (&resp->cond, &resp->mutex, &waitTime) == ETIMEDOUT) + { + if (http_request_pingRemote (resp) == false) + { + resp->response = STATUS_ERROR; + resp->hasResponse = true; + + logFmsg (CONT_LOG_DEBUG, "request no longer active: %s", dynFgetstr (resp->token)); + } + else + { + logFmsg (CONT_LOG_DEBUG, "request still active: %s", dynFgetstr (resp->token)); + } + } + } + + response = resp->response; + + pthread_mutex_unlock (&resp->mutex); + + return (response); +} + +void +http_request_setResponse (HttpRequest *resp, int response) +{ + pthread_mutex_lock (&resp->mutex); + + resp->hasResponse = true; + resp->response = response; + + pthread_mutex_unlock (&resp->mutex); + + pthread_cond_signal (&resp->cond); +} + +static void +http_request_serializeListSet (Message *message, const char *entryName, lstTset *list) +{ + int i; + StringDictionary *returnList = stringdictionary_new(); + + for (i = 0; i < lstFset_size (list); i++) + { + dynTstring *value_str; + const char *key; + const char *value; + int value_len; + + key = lstFset_get_key_index (list, i); + value = lstFset_get_index (list, i); + + if (value != NULL) + { + value_len = strlen (value); + + value_str = dynFinit(); + dynFappend (value_str, value, value_len); + + /* + dynFappend (value_str, lstFset_get_index (list, i), + lstFset_get_index (list, i)); + */ + + stringdictionary_setValue (returnList, key, value_str); + } + } + + { + dynTstring *ser = serialization_serializeType ("StringDictionary", &returnList); + + message_setParameterBinary (message, entryName, dynFgetstr (ser), dynFgetlen (ser)); + + dynFfree (ser); + } + + stringdictionary_destroy (returnList); +} + +static Message * +http_request_createRequestStartMessage (HttpRequest *resp) +{ + char ipBuf[20]; + + Message *startMessage = message_newRequest ("HttpRequestStart"); + + message_setParameter (startMessage, "token", + dynFgetstr (resp->token)); + + utlFip_to_str (resp->trans->cli_ipv4_addr, ipBuf, sizeof (ipBuf)); + + message_setParameter (startMessage, "remoteIP", ipBuf); + + /* serialize all transaction variables */ + http_request_serializeListSet (startMessage, "variables", + resp->trans->vars); + + /* serialize all request headers */ + http_request_serializeListSet (startMessage, "headers", + resp->trans->req_hdrs); + + return (startMessage); +} + +bool +http_request_sendRequestStart (HttpRequest *resp) +{ + Message *message; + Message *responseMessage; + bool ret; + + message = http_request_createRequestStartMessage (resp); + + ret = processor_sendMessage (resp->processor, message, &responseMessage); + + if (ret == false) + { + logFmsg (CONT_LOG_ERROR, "Could not send message."); + } + else + { + if (message_getType (responseMessage) == MessageTypeErrorResponse) + { + logFmsg (CONT_LOG_ERROR, "Error was returned."); + + message_print (responseMessage); + + ret = false; + } + else + { + ret = true; + } + + message_destroy (responseMessage); + } + + message_destroy (message); + + return (ret); +} + diff --git a/lc-continuity/mk4/modmobility/src/http_request_list.c b/lc-continuity/mk4/modmobility/src/http_request_list.c new file mode 100644 index 0000000000000000000000000000000000000000..2de17bd86f796bd9bb0a9abe768a173926ab3f52 --- /dev/null +++ b/lc-continuity/mk4/modmobility/src/http_request_list.c @@ -0,0 +1,94 @@ + +#include +#include + +#include "http_request_list.h" + +#include "http.h" + +struct s_HttpRequestList +{ + hshTvoid_list *list; + + pthread_rwlock_t list_lock; +}; + +HttpRequestList * +http_request_list_new() +{ + HttpRequestList *request_list = malloc (sizeof (HttpRequestList)); + + request_list->list = hshFvoid_init (http_request_destroy); + + pthread_rwlock_init (&request_list->list_lock, NULL); + + return (request_list); +} + +void +http_request_list_destroy (void *ptr) +{ + HttpRequestList *request_list = (HttpRequestList *) ptr; + + pthread_rwlock_destroy (&request_list->list_lock); + + hshFvoid_destroy (request_list->list); + + free (request_list); +} + +void +http_request_list_addRequest (HttpRequestList *request_list, HttpRequest *resp) +{ + pthread_rwlock_wrlock (&request_list->list_lock); + + hshFvoid_add (request_list->list, http_request_getToken (resp), resp); + +#ifdef TRACE_REQUEST_LIST + printf (" -- added request %s\n", http_request_getToken (resp)); +#endif + + pthread_rwlock_unlock (&request_list->list_lock); +} + +void +http_request_list_removeRequest (HttpRequestList *request_list, const char *token) +{ + pthread_rwlock_wrlock (&request_list->list_lock); + +#ifdef TRACE_REQUEST_LIST + printf (" -- removed request %s\n", token); +#endif + + hshFvoid_del (request_list->list, token); + + pthread_rwlock_unlock (&request_list->list_lock); +} + +HttpRequest * +http_request_list_getRequest (HttpRequestList *request_list, const char *token) +{ + HttpRequest *request; + + pthread_rwlock_rdlock (&request_list->list_lock); + + request = (HttpRequest *) hshFvoid_find (request_list->list, token); + + pthread_rwlock_unlock (&request_list->list_lock); + + return (request); +} + +dynTstring * +http_request_list_getDiag (HttpRequestList *request_list) +{ + dynTstring *string; + + pthread_rwlock_rdlock (&request_list->list_lock); + + string = hshFdiag_output (request_list->list); + + pthread_rwlock_unlock (&request_list->list_lock); + + return (string); +} diff --git a/lc-continuity/mk4/modmobility/src/mobility.c b/lc-continuity/mk4/modmobility/src/mobility.c new file mode 100644 index 0000000000000000000000000000000000000000..6ca0bff63faa78011b2de962697b757d81513c1a --- /dev/null +++ b/lc-continuity/mk4/modmobility/src/mobility.c @@ -0,0 +1,266 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "processor.h" +#include "mobility.h" +#include "mobilitytable.h" + +#include "http_request.h" +#include "http_request_list.h" + +/* #include "capi.h" */ +#include "http.h" + +#include "http_message_handler.h" + +struct s_Mobility +{ + char *executable; + key_t ipcKey; + Processor *processor; + + HttpRequestList *requestList; + int pid; + + pthread_rwlock_t pid_lock; +}; + +static pthread_once_t g_setupChildWatcher_once_control = PTHREAD_ONCE_INIT; + +static void mobility_startChildProcess (Mobility *mob); + +Mobility * +mobility_new (const char *executable) +{ + Mobility *mob; + + mob = malloc (sizeof (Mobility)); + + mob->requestList = http_request_list_new(); + mob->executable = strdup (executable); + mob->pid = -1; + mob->ipcKey = rand(); + pthread_rwlock_init (&mob->pid_lock, NULL); + + /* start up the processor as a server */ + mob->processor = processor_new (mob->ipcKey, false); + + processor_addRequestHandler (mob->processor, &command_HttpWrite, mob); + processor_addRequestHandler (mob->processor, &command_HttpFinish, mob); + processor_addRequestHandler (mob->processor, &command_HttpReadEntityBody, mob); + + processor_finishedInit (mob->processor); + + mobility_startChildProcess (mob); + + return (mob); +} + +void +mobility_destroy (void *ptr) +{ + Mobility *mob = (Mobility *) ptr; + + http_request_list_destroy (mob->requestList); + + if (mob->pid != -1) + { + kill (mob->pid, SIGHUP); + } + + free (mob->executable); + + free (mob); +} + +int +mobility_getPid (Mobility *mob) +{ + return (mob->pid); +} + +static const char * +mobility_childExitReason (int si_code) +{ + switch (si_code) + { + case CLD_EXITED: + return ("exited"); + break; + case CLD_KILLED: + return ("was killed"); + break; + case CLD_DUMPED: + return ("terminated abnormally"); + break; + default: + return ("exited for an unknown reason"); + break; + } +} + +static void +mobility_sigChildHandler (int signum MECHA_UNUSED, siginfo_t *siginfo, void *data MECHA_UNUSED) +{ + Mobility *mob = mobilitytable_getMobilityEntryByPid ( + mobilitytable_getTable(), siginfo->si_pid); + + waitpid (siginfo->si_pid, NULL, WNOHANG); + + if (mob == NULL) + { + logFmsg (CONT_LOG_WARN, "Recieved termination of unknown child process: %d", + siginfo->si_pid); + + return; + } + + logFmsg (CONT_LOG_DEBUG, "Causality process (%d) %s.", siginfo->si_pid, + mobility_childExitReason (siginfo->si_code)); + + mob->pid = -1; +} + +static void +mobility_setupSigChildWatcher (void) +{ + struct sigaction action; + + action.sa_handler = NULL; + action.sa_sigaction = mobility_sigChildHandler; + action.sa_flags = SA_NOCLDSTOP | SA_SIGINFO; +#ifdef LINUX + action.sa_restorer = NULL; +#endif + + sigemptyset (&action.sa_mask); + + if (sigaction (SIGCHLD, &action, NULL) != 0) + { + int e = errno; + + logFmsg (CONT_LOG_ERROR, "Could not install signal handler for SIGCHLD: %s", + strerror (e)); + } +} + +static void +mobility_startChildProcess (Mobility *mob) +{ + int pid; + char commandLine[4096]; + const char *argv[4]; + + pthread_once (&g_setupChildWatcher_once_control, mobility_setupSigChildWatcher); + + pthread_rwlock_wrlock (&mob->pid_lock); + + if (mob->pid != -1) + { + /* we already got started by another thread */ + + pthread_rwlock_unlock (&mob->pid_lock); + + return; + } + + snprintf (commandLine, sizeof (commandLine), "%s %u", mob->executable, mob->ipcKey); + + argv[0] = "/bin/sh"; + argv[1] = "-c"; + argv[2] = commandLine; + argv[3] = NULL; + + if ((pid = fork()) == 0) + { + /* child */ + + execv (argv[0], (char *const *) argv); + + /* if we are still here.. we failed. */ + + perror ("execv"); + + exit (127); + } + else + { + /* parent */ + + mob->pid = pid; + + logFmsg (CONT_LOG_WARN, "%s executing with pid %d", mob->executable, mob->pid); + + pthread_rwlock_unlock (&mob->pid_lock); + } +} + +static void +mobility_checkChildProcessStatus (Mobility *mob) +{ + bool startChild = false; + + pthread_rwlock_rdlock (&mob->pid_lock); + + if (mob->pid == -1) + { + startChild = true; + } + + pthread_rwlock_unlock (&mob->pid_lock); + + if (startChild == true) + { + mobility_startChildProcess (mob); + } +} + +HttpRequest * +mobility_getRequest (Mobility *mobility, const char *token) +{ + return (http_request_list_getRequest (mobility->requestList, token)); +} + +dynTstring +*mobility_getRequestDiag (Mobility *mobility) +{ + return (http_request_list_getDiag (mobility->requestList)); +} + +int +mobility_sendRequest (Mobility *mob, httpTtrans *trans) +{ + HttpRequest *req = http_request_new (trans, mob->processor); + int response; + + /* spawn a new client process if needed */ + mobility_checkChildProcessStatus (mob); + + http_request_list_addRequest (mob->requestList, req); + + if (http_request_sendRequestStart (req) == false) + { + logFmsg (CONT_LOG_WARN, "Could not process request."); + response = STATUS_PROCEED; + } + else + { + response = http_request_getResponse (req); + } + + /* this should free the request object */ + http_request_list_removeRequest (mob->requestList, + http_request_getToken (req)); + + return (response); +} + diff --git a/lc-continuity/mk4/modmobility/src/mobilitytable.c b/lc-continuity/mk4/modmobility/src/mobilitytable.c new file mode 100644 index 0000000000000000000000000000000000000000..c9d8d09a17ebbcbc52fd3ad856de13bc4bbf86de --- /dev/null +++ b/lc-continuity/mk4/modmobility/src/mobilitytable.c @@ -0,0 +1,122 @@ + +#include +#include + +#include "mobility.h" +#include "mobilitytable.h" + + +static pthread_once_t g_table_once_control = PTHREAD_ONCE_INIT; +static MobilityTable *g_table = NULL; + +struct s_MobilityTable +{ + hshTvoid_list *list; + + pthread_rwlock_t list_lock; +}; + +MobilityTable * +mobilitytable_new() +{ + MobilityTable *mtable = malloc (sizeof (MobilityTable)); + + mtable->list = hshFvoid_init (mobility_destroy); + + pthread_rwlock_init (&mtable->list_lock, NULL); + + return (mtable); +} + +void +mobilitytable_destroy (void *ptr) +{ + MobilityTable *mtable = (MobilityTable *) ptr; + + hshFvoid_destroy (mtable->list); + + pthread_rwlock_destroy (&mtable->list_lock); + + free (mtable); +} + +static void +mobilitytable_createGlobalTable (void) +{ + g_table = mobilitytable_new(); +} + +MobilityTable * +mobilitytable_getTable() +{ + pthread_once (&g_table_once_control, mobilitytable_createGlobalTable); + + return (g_table); +} + +Mobility * +mobilitytable_getMobilityEntryByPid (MobilityTable *mtable, int pid) +{ + hshTiterator *iter; + Mobility *retMob = NULL; + + pthread_rwlock_rdlock (&mtable->list_lock); + + iter = hshFiterator_init (mtable->list); + + while (hshFiterator_next (iter) == 1) + { + Mobility *mob = (Mobility *) hshFiterator_current_value (iter); + + if (mobility_getPid (mob) == pid) + { + retMob = mob; + + break; + } + } + + hshFiterator_free (iter); + + pthread_rwlock_unlock (&mtable->list_lock); + + return (retMob); +} + +Mobility * +mobilitytable_getMobilityEntry (MobilityTable *mtable, const char *executable) +{ + Mobility *entry; + + pthread_rwlock_rdlock (&mtable->list_lock); + + entry = (Mobility *) hshFvoid_find (mtable->list, executable); + + if (entry == NULL) + { + pthread_rwlock_unlock (&mtable->list_lock); + pthread_rwlock_wrlock (&mtable->list_lock); + + entry = (Mobility *) hshFvoid_find (mtable->list, executable); + + if (entry == NULL) + { + entry = mobility_new (executable); + + if (entry != NULL) + { + hshFvoid_add (mtable->list, executable, entry); + } + else + { + printf ("-- couldn't find executable: %s\n", executable); + } + } + } + + pthread_rwlock_unlock (&mtable->list_lock); + + return (entry); +} + + diff --git a/lc-continuity/mk4/modoracle/CVS/Entries b/lc-continuity/mk4/modoracle/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..be241f21a7d60ddeb4c692e4f3b1bc0bf11dac5b --- /dev/null +++ b/lc-continuity/mk4/modoracle/CVS/Entries @@ -0,0 +1,6 @@ +/Makefile.blackwell/1.3/Wed May 12 13:56:07 2004//Tmk4_mod6_rc2 +/Makefile.chiba/1.5/Wed May 12 13:56:07 2004//Tmk4_mod6_rc2 +/Makefile.gorecki/1.1/Thu May 13 07:48:59 2004//Tmk4_mod6_rc2 +/ora.c/1.7/Fri Apr 2 16:05:45 2004//Tmk4_mod6_rc2 +/oracle.xml/1.2/Wed May 12 15:09:20 2004//Tmk4_mod6_rc2 +D diff --git a/lc-continuity/mk4/modoracle/CVS/Repository b/lc-continuity/mk4/modoracle/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..49334f1141d37deed370f8e2ee4a7418b8cda711 --- /dev/null +++ b/lc-continuity/mk4/modoracle/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/modoracle diff --git a/lc-continuity/mk4/modoracle/CVS/Root b/lc-continuity/mk4/modoracle/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/modoracle/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/modoracle/CVS/Tag b/lc-continuity/mk4/modoracle/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/modoracle/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/modoracle/Makefile.blackwell b/lc-continuity/mk4/modoracle/Makefile.blackwell new file mode 100644 index 0000000000000000000000000000000000000000..2f8f09cd9872a2d0f00b43e3a06c1a9cd83e46ec --- /dev/null +++ b/lc-continuity/mk4/modoracle/Makefile.blackwell @@ -0,0 +1,60 @@ +# $Header: /san01/cvs/ashpool/csrc/modoracle/Attic/Makefile.blackwell,v 1.3 2004/05/12 13:56:07 aleigh Exp $ + +include ../continuity/lib/env.mk + +SRCS=ora.c +OBJS=ora.o + +# 64-bit or default install Oracle 9 +#ORALIBS = $(ORACLE_HOME)/lib/libclntst9.a $(ORACLE_HOME)/lib/libcore9.a \ +# $(ORACLE_HOME)/lib/libcommon9.a $(ORACLE_HOME)/lib/libgeneric9.a \ +# $(ORACLE_HOME)/lib/libclient9.a + +# 32-bit install Oracle 9 +#ORALIBS = $(ORACLE_HOME)/lib32/libclntst9.a $(ORACLE_HOME)/lib32/libcore9.a \ +# $(ORACLE_HOME)/lib32/libcommon9.a $(ORACLE_HOME)/lib32/libgeneric9.a \ +# $(ORACLE_HOME)/lib32/libclient9.a + +# 64-bit or default install oracle 8 +#ORALIBS = $(ORACLE_HOME)/lib/libclntst8.a $(ORACLE_HOME)/lib/libcore8.a \ +# $(ORACLE_HOME)/lib/libcommon8.a $(ORACLE_HOME)/lib/libgeneric8.a \ +# $(ORACLE_HOME)/lib/libclient8.a + +#ORALIBS=$(ORACLE_HOME)/lib/libclntsh.dylib + +#ORALIBS = -L$(ORACLE_HOME)/lib -lclntsh -lcore8 -lcommon8 -lgeneric8 -lclient8 +ORALIBS = -L$(ORACLE_HOME)/lib32 -lclntsh -lcore9 -lcommon9 -lgeneric9 -lclient9 +#ORALIBS = -L$(ORACLE_HOME)/lib -lclntsh -lcore9 -lcommon9 -lgeneric9 -lclient9 + +CFLAGS=-I../continuity/include $(CONT_FLAGS) \ + -I$(ORACLE_HOME)/rdbms/demo \ + -I$(ORACLE_HOME)/rdbms/public \ + -I$(ORACLE_HOME)/network/public \ + -I$(ORACLE_HOME)/plsql/public + +world: ../continuity/lib/oracle.so + +../continuity/lib/oracle.so: $(OBJS) + $(LD_SHARECMD) -o ../continuity/lib/oracle.so $(OBJS) $(ORALIBS) + cp oracle.xml ../continuity/lib + +../continuity/lib/oracle.a: $(OBJS) + $(RM) ora_objs/* + (cd ora_objs ; ar x $(ORACLE_HOME)/lib/libclntst8.a) + (cd ora_objs ; ar x $(ORACLE_HOME)/lib/libcore8.a) + (cd ora_objs ; ar x $(ORACLE_HOME)/lib/libcommon8.a) + (cd ora_objs ; ar x $(ORACLE_HOME)/lib/libclient8.a) +# (cd ora_objs ; ar x $(ORACLE_HOME)/lib32/libclntst9.a) +# (cd ora_objs ; ar x $(ORACLE_HOME)/lib32/libcore9.a) +# (cd ora_objs ; ar x $(ORACLE_HOME)/lib32/libcommon9.a) +# (cd ora_objs ; ar x $(ORACLE_HOME)/lib32/libclient9.a) + $(AR_CMD) ../continuity/lib/oracle.a $(OBJS) ora_objs/* + $(RM) ora_objs/* + +clean: + $(RM) $(OBJS) *~ ../continuity/lib/oracle.a ../continuity/lib/oracle.so + $(RM) ora_objs/* + +dep: depend +depend: + makedepend -I ../include $(SRCS) diff --git a/lc-continuity/mk4/modoracle/Makefile.chiba b/lc-continuity/mk4/modoracle/Makefile.chiba new file mode 100644 index 0000000000000000000000000000000000000000..10ba8507f0608fbfb7a7ccb01449270af0bea159 --- /dev/null +++ b/lc-continuity/mk4/modoracle/Makefile.chiba @@ -0,0 +1,60 @@ +# $Header: /san01/cvs/ashpool/csrc/modoracle/Attic/Makefile.chiba,v 1.5 2004/05/12 13:56:07 aleigh Exp $ + +include ../continuity/lib/env.mk + +SRCS=ora.c +OBJS=ora.o + +# 64-bit or default install Oracle 9 +#ORALIBS = $(ORACLE_HOME)/lib/libclntst9.a $(ORACLE_HOME)/lib/libcore9.a \ +# $(ORACLE_HOME)/lib/libcommon9.a $(ORACLE_HOME)/lib/libgeneric9.a \ +# $(ORACLE_HOME)/lib/libclient9.a + +# 32-bit install Oracle 9 +#ORALIBS = $(ORACLE_HOME)/lib32/libclntst9.a $(ORACLE_HOME)/lib32/libcore9.a \ +# $(ORACLE_HOME)/lib32/libcommon9.a $(ORACLE_HOME)/lib32/libgeneric9.a \ +# $(ORACLE_HOME)/lib32/libclient9.a + +# 64-bit or default install oracle 8 +#ORALIBS = $(ORACLE_HOME)/lib/libclntst8.a $(ORACLE_HOME)/lib/libcore8.a \ +# $(ORACLE_HOME)/lib/libcommon8.a $(ORACLE_HOME)/lib/libgeneric8.a \ +# $(ORACLE_HOME)/lib/libclient8.a + +#ORALIBS=$(ORACLE_HOME)/lib/libclntsh.dylib + +#ORALIBS = -L$(ORACLE_HOME)/lib -lclntsh -lcore8 -lcommon8 -lgeneric8 -lclient8 +#ORALIBS = -L$(ORACLE_HOME)/lib32 -lclntsh -lcore9 -lcommon9 -lgeneric9 -lclient9 +ORALIBS = -L$(ORACLE_HOME)/lib -lclntsh -lcore9 -lcommon9 -lgeneric9 -lclient9 + +CFLAGS=-I../continuity/include $(CONT_FLAGS) \ + -I$(ORACLE_HOME)/rdbms/demo \ + -I$(ORACLE_HOME)/rdbms/public \ + -I$(ORACLE_HOME)/network/public \ + -I$(ORACLE_HOME)/plsql/public + +world: ../continuity/lib/oracle.so + +../continuity/lib/oracle.so: $(OBJS) + $(LD_SHARECMD) -o ../continuity/lib/oracle.so $(OBJS) $(ORALIBS) + cp oracle.xml ../continuity/lib + +../continuity/lib/oracle.a: $(OBJS) + $(RM) ora_objs/* + (cd ora_objs ; ar x $(ORACLE_HOME)/lib/libclntst8.a) + (cd ora_objs ; ar x $(ORACLE_HOME)/lib/libcore8.a) + (cd ora_objs ; ar x $(ORACLE_HOME)/lib/libcommon8.a) + (cd ora_objs ; ar x $(ORACLE_HOME)/lib/libclient8.a) +# (cd ora_objs ; ar x $(ORACLE_HOME)/lib32/libclntst9.a) +# (cd ora_objs ; ar x $(ORACLE_HOME)/lib32/libcore9.a) +# (cd ora_objs ; ar x $(ORACLE_HOME)/lib32/libcommon9.a) +# (cd ora_objs ; ar x $(ORACLE_HOME)/lib32/libclient9.a) + $(AR_CMD) ../continuity/lib/oracle.a $(OBJS) ora_objs/* + $(RM) ora_objs/* + +clean: + $(RM) $(OBJS) *~ ../continuity/lib/oracle.a ../continuity/lib/oracle.so + $(RM) ora_objs/* + +dep: depend +depend: + makedepend -I ../include $(SRCS) diff --git a/lc-continuity/mk4/modoracle/Makefile.gorecki b/lc-continuity/mk4/modoracle/Makefile.gorecki new file mode 100644 index 0000000000000000000000000000000000000000..1f195d84585f71b8eb8d41810b5111ed45023e01 --- /dev/null +++ b/lc-continuity/mk4/modoracle/Makefile.gorecki @@ -0,0 +1,60 @@ +# $Header: /san01/cvs/ashpool/csrc/modoracle/Attic/Makefile.gorecki,v 1.1 2004/05/13 07:48:59 eric Exp $ + +include ../continuity/lib/env.mk + +SRCS=ora.c +OBJS=ora.o + +# 64-bit or default install Oracle 9 +#ORALIBS = $(ORACLE_HOME)/lib/libclntst9.a $(ORACLE_HOME)/lib/libcore9.a \ +# $(ORACLE_HOME)/lib/libcommon9.a $(ORACLE_HOME)/lib/libgeneric9.a \ +# $(ORACLE_HOME)/lib/libclient9.a + +# 32-bit install Oracle 9 +#ORALIBS = $(ORACLE_HOME)/lib32/libclntst9.a $(ORACLE_HOME)/lib32/libcore9.a \ +# $(ORACLE_HOME)/lib32/libcommon9.a $(ORACLE_HOME)/lib32/libgeneric9.a \ +# $(ORACLE_HOME)/lib32/libclient9.a + +# 64-bit or default install oracle 8 +#ORALIBS = $(ORACLE_HOME)/lib/libclntst8.a $(ORACLE_HOME)/lib/libcore8.a \ +# $(ORACLE_HOME)/lib/libcommon8.a $(ORACLE_HOME)/lib/libgeneric8.a \ +# $(ORACLE_HOME)/lib/libclient8.a + +#ORALIBS=$(ORACLE_HOME)/lib/libclntsh.dylib + +ORALIBS = -Wl,-rpath -Wl,$(ORACLE_HOME)/lib -L$(ORACLE_HOME)/lib -lclntsh -lcore8 -lcommon8 -lgeneric8 -lclient8 +#ORALIBS = -L$(ORACLE_HOME)/lib32 -lclntsh -lcore9 -lcommon9 -lgeneric9 -lclient9 +#ORALIBS = -L$(ORACLE_HOME)/lib -lclntsh -lcore9 -lcommon9 -lgeneric9 -lclient9 + +CFLAGS=-I../continuity/include $(CONT_FLAGS) \ + -I$(ORACLE_HOME)/rdbms/demo \ + -I$(ORACLE_HOME)/rdbms/public \ + -I$(ORACLE_HOME)/network/public \ + -I$(ORACLE_HOME)/plsql/public + +world: ../continuity/lib/oracle.so + +../continuity/lib/oracle.so: $(OBJS) + $(LD_SHARECMD) -o ../continuity/lib/oracle.so $(OBJS) $(ORALIBS) + cp oracle.xml ../continuity/lib + +../continuity/lib/oracle.a: $(OBJS) + $(RM) ora_objs/* + (cd ora_objs ; ar x $(ORACLE_HOME)/lib/libclntst8.a) + (cd ora_objs ; ar x $(ORACLE_HOME)/lib/libcore8.a) + (cd ora_objs ; ar x $(ORACLE_HOME)/lib/libcommon8.a) + (cd ora_objs ; ar x $(ORACLE_HOME)/lib/libclient8.a) +# (cd ora_objs ; ar x $(ORACLE_HOME)/lib32/libclntst9.a) +# (cd ora_objs ; ar x $(ORACLE_HOME)/lib32/libcore9.a) +# (cd ora_objs ; ar x $(ORACLE_HOME)/lib32/libcommon9.a) +# (cd ora_objs ; ar x $(ORACLE_HOME)/lib32/libclient9.a) + $(AR_CMD) ../continuity/lib/oracle.a $(OBJS) ora_objs/* + $(RM) ora_objs/* + +clean: + $(RM) $(OBJS) *~ ../continuity/lib/oracle.a ../continuity/lib/oracle.so + $(RM) ora_objs/* + +dep: depend +depend: + makedepend -I ../include $(SRCS) diff --git a/lc-continuity/mk4/modoracle/ora.c b/lc-continuity/mk4/modoracle/ora.c new file mode 100644 index 0000000000000000000000000000000000000000..bb44cc30f2464200e4aac89659fbda51f6c83446 --- /dev/null +++ b/lc-continuity/mk4/modoracle/ora.c @@ -0,0 +1,895 @@ +/* + * $Header: /san01/cvs/ashpool/csrc/modoracle/Attic/ora.c,v 1.7 2004/04/02 16:05:45 aleigh Exp $ + * + * Copyright (c) 1994, 2001 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Disclosure, copying, distribution, or transmission of of this code without + * express permission is prohibited. + */ + +/* TODO: + Checkout needs to eval checkin_time and test the connection if it's old + Various oracle functions need to mark the connection as bad if there is an error + */ + +/* Define this if you want connection pooling to be in effect. */ +#define ORA_POOLING + +#include +#include +#include "db.h" +#include + +#define ORA_CONN_AUTOCOMMIT 0 +#define ORA_CONN_TRANSACTION 1 +#define ORA_DML 1 +#define ORA_ROWS 2 + +/* o/~ Words are very unescessary */ + +struct oraSfetch { + struct oraSconn *conn; + /* Oracle will tell us what type this column is */ + OCITypeCode type; + /* will be NULL unless this column happens to be one of the LOB types */ + OCILobLocator *lob; + /* generally used for INSERT and UPDATE; seldom used */ + OCIBind *bind; + /* generally used for SELECT; seldom used except for getting LOBs */ + OCIDefine *def; + /* how many bytes Oracle thinks we need to allocate */ + ub2 size; + /* how many bytes we allocated */ + unsigned buf_size; + /* the stuff above does not change as the rows are fetched */ + /* here's where the actual value from a particular row is kept */ + char *buf; + /* support for array DML: the array of values for this bind variable. */ + int array_count; + char **array_values; + /* 2-byte signed integer indicating null-ness; if null, value will be -1 */ + sb2 is_null; + /* how many bytes are in the buffer above, 0 would mean empty string */ + ub2 fetch_length; + /* these are only used for LONGs; the length of one piece */ + ub4 piecewise_fetch_length; + /* + * in order to implement the clob_dml API call, we need 1 LOB for every + * row/column intersection inserted. I.e., if we do an insert that + * results in 4 rows going into the db, with 3 CLOB columns then we need + * 12 LOBs. This struct is for one column only so we just need one array + * of lobs. + */ + OCILobLocator **lobs; + /* this tells us how many lobs we have above (i.e., only for clob_dml) */ + ub4 n_rows; + /* Whether we determined that this column is a LOB during processing. */ + int is_lob; +}; +typedef struct oraSfetch oraTfetch; + +struct oraSconn { + OCIEnv *envhp; + OCIError *errhp; + OCIServer *srvhp; + OCISvcCtx *svchp; + OCISession *usrhp; + + /* Statement that we are executing. */ + OCIStmt *stmthp; + int mode; + sb4 n_columns; + char padding[10]; + oraTfetch *fetch; + + /* These are used by the pooling functionality + and not otherwise needed. */ + char *name; /* do not free */ + char *service; /* do not free */ + unsigned int checkin_time; + int bad; /* If this is 1, the connection will be closed rather than checked in */ +}; +typedef struct oraSconn oraTconn; + +struct oraSpool { + lstTlist *conns; + char *user; + char *service; + int checked_in; + int checked_out; + struct oraSpool *next; +}; +typedef struct oraSpool oraTpool; + +oraTpool *oraGpools = NULL; +pthread_mutex_t oraLpools = PTHREAD_MUTEX_INITIALIZER; + +dvoid *tmp; + +static int lob_buffer_size = 16384; + +static int oraFerror(oraTconn * conn, sword status); +static void oraFalloc_fetch_bufs(oraTconn * conn); +lstTset *oraFbindrow(oraTconn * conn); +int oraFexec(oraTconn * conn, char *sql); +oraTconn *oraFconnect(char *user, char *password, char *service); +oraTconn *oraFpool_checkout(const char *name, const char *password, const char *service); +int oraFclose(oraTconn * conn); +lstTset *oraFselect(oraTconn * conn, const char *sql); +int oraFgetrow(oraTconn * conn, lstTset * row); +static void oraFfree_fetch_bufs(oraTconn * conn); +int oraFflush(oraTconn * conn); +oraTpool *oraFpool_get(char *name, char *service); + +/* + * Return an oracle connection pool entry. This always succeeds. + * because it will create an entry if one does not exist. The caller + * needs to hold oraLpools. + */ +oraTpool *oraFpool_get(char *name, char *service) +{ + oraTpool *pool; + + assert(name != NULL); + assert(service != NULL); + + for (pool = oraGpools; pool != NULL; pool = pool->next) { + if (strcmp((char *) pool->user, (char *) name) == 0 + && strcmp(pool->service, service) == 0) + return pool; + } + + pool = (oraTpool *) malloc(sizeof(oraTpool)); + assert(pool != NULL); + + bzero(pool, sizeof(oraTpool)); + + pool->user = strFcopy(name); + pool->service = strFcopy(service); + + assert(pool->user != NULL); + assert(pool->service != NULL); + + /* We are going to routinely remove elements from the list + when we check them out, so we don't want a desctructor. */ + +/* logFmsg(3,"mod/ora: Creating pool for %s / %s", name, service); */ + + pool->conns = lstFlist_create((void (*)(void *)) NULL); + + pool->next = oraGpools; + oraGpools = pool; + + return pool; +} + +void oraFpool_checkin(oraTconn * conn) +{ + oraTpool *pool; + + pthread_mutex_lock(&oraLpools); + + pool = oraFpool_get(conn->name, conn->service); + + assert(pool != NULL); + + if (conn->bad == 1) { + logFmsg(1, "ora: Connection to %s/%s was marked bad, destroying.", + pool->user, pool->service); + oraFclose(conn); + pool->checked_out--; + pthread_mutex_unlock(&oraLpools); + return; + } + + oraFflush(conn); + /* Set the checkin time. This will later be used when the connection + * is checked out to see if it needs to be tested or not. */ + conn->checkin_time = utlFtime(); + + lstFlist_add_next(pool->conns, lstFlist_tail(pool->conns), conn); + + pool->checked_out--; + pool->checked_in++; + + pthread_mutex_unlock(&oraLpools); + +/* logFmsg(0,"ora: Checked in connection to %s/%s.", pool->user, pool->service); */ +} + +oraTconn *oraFpool_checkout(const char *name, const char *password, const char *service) +{ + oraTpool *pool; + oraTconn *conn; + lstTlist_elem *el; + + assert(name != NULL); + assert(service != NULL); + + pthread_mutex_lock(&oraLpools); + + pool = oraFpool_get(name, service); + + assert(pool != NULL); + +/* logFmsg(3,"ora: checked in: %d for %s/%s ", pool->checked_in, pool->user, pool->service); */ + + if (pool->checked_in == 0) { + conn = oraFconnect(name, password, service); + if (conn == NULL) { +/* logFmsg(3,"oraFpool_checkout: oraFconnect() failed."); */ + pthread_mutex_unlock(&oraLpools); + return NULL; + } + +/* logFmsg(3,"ora: oraFpool_checkout: Created new connection to %s/%s.", pool->user, pool->service); */ + + conn->name = pool->user; + conn->service = pool->service; + + pool->checked_out++; + + pthread_mutex_unlock(&oraLpools); + return conn; + } + + el = lstFlist_head(pool->conns); + conn = lstFlist_data(el); + lstFlist_remove(pool->conns, el, 0); + pool->checked_in--; + + pthread_mutex_unlock(&oraLpools); + +/* logFmsg(3,"ora: oraFpool_checkout: Checked out connection to %s/%s.", pool->user, pool->service); */ + return conn; +} + +int oraFinit(void *p, lstTset * opts) +{ + dbTvector *vector; + +#ifdef ORA_POOLING + logFmsg(0, "mod/oracle: Oracle RDBMS Interface + Pooling (module)"); +#else + logFmsg(0, "mod/oracle: Oracle RDBMS Interface (module)"); +#endif + + logFmsg(0, "mod/oracle: Copyright (c) 2002, Alex Leigh"); + + OCIInitialize((ub4) OCI_THREADED | OCI_OBJECT, (dvoid *) 0, + (dvoid * (*)())0, (dvoid * (*)())0, (void (*)()) 0); + + vector = (dbTvector *) malloc(sizeof(dbTvector)); + + vector->init_fn = (void (*)(void)) oraFinit; + +#ifndef ORA_POOLING + vector->open_fn = (void *(*)(char *, char *, char *)) oraFconnect; + vector->close_fn = (int (*)(void *)) oraFclose; +#else + vector->open_fn = + (void *(*)(char *, char *, char *)) oraFpool_checkout; + vector->close_fn = (int (*)(void *)) oraFpool_checkin; +#endif + + vector->select_fn = (lstTset * (*)(void *, const char *)) oraFselect; + vector->getrow_fn = (int (*)(void *, lstTset *)) oraFgetrow; + vector->dml_fn = (int (*)(void *, char *)) oraFexec; + dbFvector_register(vector); + + return 0; +} + +/* + * -1 error + * 0 data + * 2 no data + */ +int oraFgetrow(oraTconn * conn, lstTset * row) +{ + sword status; + int i; + ub4 ret_len = 0; + + assert(conn != NULL); + assert(row != NULL); + assert(conn->stmthp != NULL); + assert(conn->errhp != NULL); + + status = + OCIStmtFetch(conn->stmthp, conn->errhp, 1, OCI_FETCH_NEXT, + OCI_DEFAULT); + + if (status == OCI_NO_DATA) { + oraFflush(conn); + return 2; + } + if (oraFerror(conn, status) != 0) { + oraFflush(conn); + return -1; + } + for (i = 0; i < conn->n_columns; i++) { + oraTfetch *fetchbuf = &conn->fetch[i]; + + switch (fetchbuf->type) { + default: + /* Add null termination and then add it to the set */ + if (fetchbuf->is_null == -1) { + fetchbuf->buf[0] = NULL; + } else if (fetchbuf->is_null != 0) { + oraFflush(conn); + return -1; + } + fetchbuf->buf[fetchbuf->fetch_length] = NULL; + + lstFset_add_value(row, i, fetchbuf->buf); +/* logFmsg(3, "value: %s", fetchbuf->buf); */ + break; + } + } + return 0; +} + +/* + * In cases where a "bad" error have occured, this function also will + * now mark the connection as bad. This means that it will be destroyed + * rather than be returned to the pool. + */ +static int oraFerror(oraTconn * conn, sword status) +{ + text errbuf[512]; + ub4 buflen; + ub4 errcode; + + switch (status) { + case OCI_SUCCESS: + return 0; + case OCI_SUCCESS_WITH_INFO: + logFmsg(1, "Error - OCI_SUCCESS_WITH_INFO"); + break; + case OCI_NEED_DATA: + logFmsg(1, "Error - OCI_NEED_DATA"); + break; + case OCI_NO_DATA: + logFmsg(1, "Error - OCI_NO_DATA"); + break; + case OCI_ERROR: + OCIErrorGet((dvoid *) conn->errhp, (ub4) 1, (text *) NULL, + (dvoid *) & errcode, errbuf, (ub4) sizeof(errbuf), + (ub4) OCI_HTYPE_ERROR); + strFstrip_crlf((char *) errbuf, strlen((const char *) errbuf)); + logFmsg(1, "%s", errbuf); + conn->bad = 1; + break; + case OCI_INVALID_HANDLE: + logFmsg(1, "Error - OCI_INVALID_HANDLE"); + conn->bad = 1; + break; + case OCI_STILL_EXECUTING: + logFmsg(1, "Error - OCI_STILL_EXECUTE"); + conn->bad = 1; + break; + case OCI_CONTINUE: + logFmsg(1, "Error - OCI_CONTINUE"); + break; + default: + break; + } + + return 1; +} + +static void oraFfree_fetch_bufs(oraTconn * conn) +{ + if (conn != NULL && conn->fetch != NULL) { + int i; + sword oci_status; + + for (i = 0; i < conn->n_columns; i++) { + /* + * oraTfetch *fetchbuf = (oraTfetch *) conn->fetch + + * (sizeof(oraTfetch) * i); + */ + oraTfetch *fetchbuf = &conn->fetch[i]; + + /* oraTfetch *fetchbuf = (oraTfetch *) & conn->fetch[i]; */ + /* logFmsg(3,"fetchbuf set to %d 0x%x", i, fetchbuf); */ + + + /* + * if (fetchbuf->lob != NULL) { oraFerror(conn, + * OCIDescriptorFree(fetchbuf->lob, OCI_DTYPE_LOB)); fetchbuf->lob = + * NULL; } + */ + /* + * fetchbuf->bind is automatically deallocated when its statement is + * deallocated. + * + * Same for fetchbuf->def, I believe, though the manual doesn't say. + */ + + if (fetchbuf->buf != NULL) { + free(fetchbuf->buf); + fetchbuf->buf = NULL; + fetchbuf->buf_size = 0; + } + /* + * if (fetchbuf->lobs != 0) { for (i = 0; i < fetchbuf->n_rows; i++) + * { oraFerror(conn, OCIDescriptorFree(fetchbuf->lobs[i], + * OCI_DTYPE_LOB)); } free(fetchbuf->lobs); fetchbuf->lobs = NULL; + * fetchbuf->n_rows = 0; } + */ + } + + free(conn->fetch); + conn->fetch = NULL; + } +} + + +static void oraFalloc_fetch_bufs(oraTconn * conn) +{ + int i; + + /* + * logFmsg(3, "alloc: allocating fetch buffers %d", conn->n_columns * + * sizeof(oraTfetch)); + */ + + conn->fetch = malloc(conn->n_columns * sizeof(struct oraSfetch)); + assert(conn->fetch != NULL); + + /* logFmsg(3, "Allocated fetchbuffers at 0x%x", conn->fetch); */ + + for (i = 0; i < conn->n_columns; i++) { + oraTfetch *fetchbuf = &conn->fetch[i]; + /* + * oraTfetch *fetchbuf = (oraTfetch *) conn->fetch + (sizeof(oraTfetch) * + * i); + */ + + bzero(fetchbuf, sizeof(oraTfetch)); + fetchbuf->conn = conn; + } +} + +lstTset *oraFbindrow(oraTconn * conn) +{ + sword status; + lstTset *set; + int i; + + assert(conn != NULL); + + set = lstFset_create("row"); + + if (conn->stmthp == NULL) { + logFmsg(1, "oraFbindrow: No active query statment."); + return NULL; + } + if (conn->fetch != NULL) { + logFmsg(1, "oraFbindrow: Query already bound."); + return NULL; + } + if (oraFerror(conn, OCIAttrGet(conn->stmthp, OCI_HTYPE_STMT, + (dvoid *) & conn->n_columns, NULL, + OCI_ATTR_PARAM_COUNT, + conn->errhp)) != 0) + return NULL; + + oraFalloc_fetch_bufs(conn); + + for (i = 0; i < conn->n_columns; i++) { + OCIParam *param; + char name[512]; + char *name1 = 0; + ub4 name1_size = 0; + + /* Set the current fetch buffer */ + oraTfetch *fetchbuf = &conn->fetch[i]; + /* + * oraTfetch *fetchbuf = (oraTfetch *) conn->fetch + (sizeof(oraTfetch) * + * i); + */ + /* logFmsg(3,"fetchbuf set to %d 0x%x", i, fetchbuf); */ + + /* fetchbuf = (oraTfetch *) & conn->fetch[i]; */ + + if (oraFerror(conn, OCIParamGet(conn->stmthp, OCI_HTYPE_STMT, + conn->errhp, (dvoid *) & param, + i + 1)) != 0) + return NULL; + + if (oraFerror + (conn, + OCIAttrGet(param, OCI_DTYPE_PARAM, (dvoid *) & name1, + &name1_size, OCI_ATTR_NAME, conn->errhp)) != 0) + return NULL; + + /* + * * Oracle gives us back a pointer to a string that is not + * null-terminated so we copy it into our local var and add a 0 at the + * end + */ + memcpy(name, name1, name1_size); + name[name1_size] = 0; + + /* logFmsg(3, "lstFset_add '%s' %s", name, "null"); */ + lstFset_add(set, name, "null"); + + /* Get the column type. */ + + if (oraFerror + (conn, + OCIAttrGet(param, OCI_DTYPE_PARAM, &fetchbuf->type, NULL, + OCI_ATTR_DATA_TYPE, conn->errhp)) != 0) + return NULL; + + + /* logFmsg(3, "type is %d", fetchbuf->type); */ + + switch (fetchbuf->type) { + /* we handle LOBs in the loop below */ + case OCI_TYPECODE_CLOB: + case OCI_TYPECODE_BLOB: + break; + + /* + * RDD is Oracle's happy fun name for ROWID (18 chars long but if + * you ask Oracle the usual way, it will give you a number that is + * too small) + */ + case SQLT_RDD: + fetchbuf->size = 18; + fetchbuf->buf_size = fetchbuf->size + 32; + fetchbuf->buf = malloc(fetchbuf->buf_size); + break; + + case SQLT_NUM: + /* + * OCI reports that all NUMBER values has a size of 22, the size of + * its internal storage format for numbers. We are fetching all + * values out as strings, so we need more space. Empirically, it + * seems to return 41 characters when it does the NUMBER to STRING + * conversion. + */ + fetchbuf->size = 41; + fetchbuf->buf_size = fetchbuf->size + 8; + fetchbuf->buf = malloc(fetchbuf->buf_size); + break; + + /* this might work if the rest of our LONG stuff worked */ + case SQLT_LNG: + fetchbuf->buf_size = lob_buffer_size; + fetchbuf->buf = malloc(fetchbuf->buf_size); + break; + default: + /* get the size */ + + if (oraFerror(conn, OCIAttrGet(param, + OCI_DTYPE_PARAM, + (dword *) & fetchbuf->size, + NULL, + OCI_ATTR_DATA_SIZE, + conn->errhp)) != 0) + return NULL; + + /* logFmsg(3, "column '%s' size '%d'", name, fetchbuf->size); */ + + /* + * this is the important part, we allocate buf to be 8 bytes more + * than Oracle says are necessary (for null termination) + */ + fetchbuf->buf_size = fetchbuf->size + 32; + fetchbuf->buf = malloc(fetchbuf->buf_size); + /* + * logFmsg(0, "Fetchbuf %d 0x%x -> buf = 0x%x", i, &fetchbuf->buf, + * fetchbuf->buf); + */ + + break; + } + } + + /* + * loop over the columns again; this could now be in the loop above but we + * originally did things this way to permit resizing of buffers + * + * Now we're telling Oracle to associate the buffers we just allocated with + * their respective columns + */ + for (i = 0; i < conn->n_columns; i++) { + oraTfetch *fetchbuf = &conn->fetch[i]; + /* + * oraTfetch *fetchbuf = (oraTfetch *) conn->fetch + (sizeof(oraTfetch) * + * i); + */ + /* logFmsg(3,"fetchbuf set to %d 0x%x", i, fetchbuf); */ + + + /* + * logFmsg(3, "2nd pass: conn->fetch[%d]->buf is 0x%x", i, + * fetchbuf->buf); logFmsg(3, "2nd pass: LOB is 0x%x", fetchbuf->lob); + */ + + switch (fetchbuf->type) { + case OCI_TYPECODE_CLOB: + case OCI_TYPECODE_BLOB: + /* + * we allocate descriptors for CLOBs; these are essentially + * pointers. We will not allocate any buffers for them until we're + * actually fetching data from individual rows. + */ + if (oraFerror(conn, OCIDescriptorAlloc(conn->envhp, + (void *) &fetchbuf->lob, + OCI_DTYPE_LOB, + 0, 0)) != 0) + return NULL; + + if (oraFerror(conn, OCIDefineByPos(conn->stmthp, + &fetchbuf->def, + conn->errhp, + i + 1, + (void *) &fetchbuf->lob, + -1, fetchbuf->type, + &fetchbuf->is_null, + 0, 0, OCI_DEFAULT)) != 0) + return NULL; + break; + + case SQLT_LNG: + if (oraFerror(conn, OCIDefineByPos(conn->stmthp, + &fetchbuf->def, + conn->errhp, + i + 1, + 0, + (sb4) SB4MAXVAL, + fetchbuf->type, + &fetchbuf->is_null, + &fetchbuf->fetch_length, + 0, OCI_DYNAMIC_FETCH)) != 0) + return NULL; + break; + + default: + + /* logFmsg(0, "definebypos %d 0x%x", i, fetchbuf->buf); */ + + if (oraFerror(conn, OCIDefineByPos(conn->stmthp, + &fetchbuf->def, + conn->errhp, + i + 1, + fetchbuf->buf, + fetchbuf->buf_size, + SQLT_STR, + &fetchbuf->is_null, + &fetchbuf->fetch_length, + NULL, OCI_DEFAULT)) != 0) + return NULL; + break; + } + } + + return set; +} + + +/* + * Returns 1 for select or 2 for DML + */ +int oraFexec(oraTconn * conn, char *sql) +{ + ub4 iters = 0; + ub2 type; + sword status; + + assert(conn != NULL); + assert(sql != NULL); + + status = + OCIHandleAlloc(conn->envhp, (dvoid **) & conn->stmthp, + OCI_HTYPE_STMT, 0, NULL); + if (oraFerror(conn, status) != 0) + return -1; + + status = + OCIStmtPrepare(conn->stmthp, conn->errhp, (text *) sql, + strlen(sql), OCI_NTV_SYNTAX, OCI_DEFAULT); + if (oraFerror(conn, status) != 0) + return -1; + + status = + OCIAttrGet(conn->stmthp, OCI_HTYPE_STMT, (dvoid *) & type, NULL, + OCI_ATTR_STMT_TYPE, conn->errhp); + if (oraFerror(conn, status) != 0) + return -1; + + /* + * Values returned for AttrGet OCI_HTYPE_STMT OCI_STMT_SELECT + * OCI_STMT_UPDATE OCI_STMT_DELETE OCI_STMT_INSERT OCI_STMT_CREATE + * OCI_STMT_DROP OCI_STMT_ALTER OCI_STMT_BEGIN OCI_STMT_DECLARE + */ + + if (type != OCI_STMT_SELECT) + iters = 1; + + status = + OCIStmtExecute(conn->svchp, conn->stmthp, conn->errhp, iters, 0, + NULL, NULL, OCI_DEFAULT); + if (oraFerror(conn, status) != 0) + return -1; + + if (type == OCI_STMT_SELECT) + return ORA_ROWS; + else { + OCITransCommit(conn->svchp, conn->errhp, OCI_DEFAULT); + return ORA_DML; + } +} + +/* + * TODO: Under error conditions thos code leaks any of the handles previously + * allocated when it frees conn. + */ +oraTconn *oraFconnect(char *user, char *password, char *service) +{ + oraTconn *conn = malloc(sizeof(oraTconn)); + + assert(user != NULL); + assert(password != NULL); + assert(service != NULL); + + assert(conn != NULL); + +/* logFmsg(3,"mod/oracle: oraFconnect() called. [u: %s] [s: %s]",user, service); */ + + bzero(conn, sizeof(oraTconn)); + + OCIHandleAlloc((dvoid *) NULL, (dvoid **) & conn->envhp, + (ub4) OCI_HTYPE_ENV, 52, (dvoid **) & tmp); + + OCIEnvInit(&conn->envhp, (ub4) OCI_DEFAULT, 21, (dvoid **) & tmp); + + OCIHandleAlloc((dvoid *) conn->envhp, (dvoid **) & conn->errhp, + (ub4) OCI_HTYPE_ERROR, 52, (dvoid **) & tmp); + + OCIHandleAlloc((dvoid *) conn->envhp, (dvoid **) & conn->srvhp, + (ub4) OCI_HTYPE_SERVER, 52, (dvoid **) & tmp); + + if (oraFerror + (conn, + OCIServerAttach(conn->srvhp, conn->errhp, (text *) service, + (sb4) strlen(service), (ub4) OCI_DEFAULT)) != 0) { + free(conn); + return NULL; + } + OCIHandleAlloc((dvoid *) conn->envhp, (dvoid **) & conn->svchp, + (ub4) OCI_HTYPE_SVCCTX, 52, (dvoid **) & tmp); + + /* set attribute server context in the service context */ + OCIAttrSet((dvoid *) conn->svchp, (ub4) OCI_HTYPE_SVCCTX, + (dvoid *) conn->srvhp, (ub4) 0, + (ub4) OCI_ATTR_SERVER, (OCIError *) conn->errhp); + + /* allocate a user context handle */ + OCIHandleAlloc((dvoid *) conn->envhp, (dvoid **) & conn->usrhp, + (ub4) OCI_HTYPE_SESSION, (size_t) 0, (dvoid **) 0); + + OCIAttrSet((dvoid *) conn->usrhp, (ub4) OCI_HTYPE_SESSION, + (dvoid *) user, (ub4) strlen(user), + OCI_ATTR_USERNAME, conn->errhp); + + OCIAttrSet((dvoid *) conn->usrhp, (ub4) OCI_HTYPE_SESSION, + (dvoid *) password, (ub4) strlen(password), + OCI_ATTR_PASSWORD, conn->errhp); + + if (oraFerror + (conn, + OCISessionBegin(conn->svchp, conn->errhp, conn->usrhp, + OCI_CRED_RDBMS, OCI_DEFAULT)) != 0) { + free(conn); + return NULL; + } + OCIAttrSet((dvoid *) conn->svchp, (ub4) OCI_HTYPE_SVCCTX, + (dvoid *) conn->usrhp, (ub4) 0, + OCI_ATTR_SESSION, conn->errhp); + + return conn; +} + +int oraFclose(oraTconn * conn) +{ + + /* these are basically redundant now, I think */ + oraFflush(conn); + + OCISessionEnd(conn->svchp, conn->errhp, conn->usrhp, + (ub4) OCI_DEFAULT); + OCIServerDetach(conn->srvhp, conn->errhp, (ub4) OCI_DEFAULT); + oraFerror(conn, + OCIHandleFree((dvoid *) conn->srvhp, + (ub4) OCI_HTYPE_SERVER)); + oraFerror(conn, + OCIHandleFree((dvoid *) conn->svchp, + (ub4) OCI_HTYPE_SVCCTX)); + oraFerror(conn, + OCIHandleFree((dvoid *) conn->errhp, (ub4) OCI_HTYPE_ERROR)); + + oraFerror(conn, + OCIHandleFree((dvoid *) conn->envhp, (ub4) OCI_HTYPE_ENV)); + + free(conn); + + return 0; +} + +lstTset *oraFselect(oraTconn * conn, const char *sql) +{ + + assert(conn != NULL); + assert(sql != NULL); + + oraFflush(conn); + + if (oraFexec(conn, sql) == ORA_ROWS) { + return oraFbindrow(conn); + } else { + return NULL; + } +} + +int oraFflush(oraTconn * conn) +{ + int i; + + assert(conn != NULL); + + if (conn->stmthp != NULL) { + if (oraFerror(conn, OCIHandleFree(conn->stmthp, OCI_HTYPE_STMT)) != + 0) + return -1; + conn->stmthp = NULL; + } + if (conn->fetch != NULL) { + for (i = 0; i < conn->n_columns; i++) { + oraTfetch *fetchbuf = &conn->fetch[i]; + /* + * oraTfetch *fetchbuf = (oraTfetch *) conn->fetch + + * (sizeof(oraTfetch) * i); + */ + + if (fetchbuf->lob != NULL) { + if (oraFerror + (conn, + OCIDescriptorFree(fetchbuf->lob, OCI_DTYPE_LOB)) != 0) + return -1; + fetchbuf->lob = NULL; + } + if (fetchbuf->buf != NULL) + free(fetchbuf->buf); + if (fetchbuf->array_values != NULL) + free(fetchbuf->array_values); + + if (fetchbuf->lobs != 0) { + int k; + for (k = 0; k < fetchbuf->n_rows; k++) { + if (oraFerror + (conn, + OCIDescriptorFree(fetchbuf->lobs[k], + OCI_DTYPE_LOB)) != 0) + return -1; + } + free(fetchbuf->lobs); + fetchbuf->lobs = NULL; + fetchbuf->n_rows = 0; + } + } + free(conn->fetch); + conn->fetch = NULL; + } + return 0; +} diff --git a/lc-continuity/mk4/modoracle/oracle.xml b/lc-continuity/mk4/modoracle/oracle.xml new file mode 100644 index 0000000000000000000000000000000000000000..a5d00efec724d4994d334b892d32f71b2e8aeebc --- /dev/null +++ b/lc-continuity/mk4/modoracle/oracle.xml @@ -0,0 +1,7 @@ + + oracle + oraFinit + + db + + diff --git a/lc-continuity/mk4/modradius/CVS/Entries b/lc-continuity/mk4/modradius/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..cf02f625057890df291d0e6e93313d50ca19a42e --- /dev/null +++ b/lc-continuity/mk4/modradius/CVS/Entries @@ -0,0 +1,5 @@ +/Makefile.in/1.3/Thu May 13 13:38:55 2004//Tmk4_mod6_rc2 +/radius.c/1.11/Wed May 19 18:34:08 2004//Tmk4_mod6_rc2 +/radius.h/1.2/Tue Mar 16 16:25:38 2004//Tmk4_mod6_rc2 +/radius.xml/1.1/Thu May 13 13:38:55 2004//Tmk4_mod6_rc2 +D diff --git a/lc-continuity/mk4/modradius/CVS/Repository b/lc-continuity/mk4/modradius/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..7f2e0e82ef69f5655b3d8449c6d516759c88b1ac --- /dev/null +++ b/lc-continuity/mk4/modradius/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/modradius diff --git a/lc-continuity/mk4/modradius/CVS/Root b/lc-continuity/mk4/modradius/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/modradius/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/modradius/CVS/Tag b/lc-continuity/mk4/modradius/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/modradius/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/modradius/Makefile.in b/lc-continuity/mk4/modradius/Makefile.in new file mode 100644 index 0000000000000000000000000000000000000000..12a0eae49a7bccc4bbdc710f022cf4451447e786 --- /dev/null +++ b/lc-continuity/mk4/modradius/Makefile.in @@ -0,0 +1,24 @@ +# $Header: /san01/cvs/ashpool/csrc/modradius/Attic/Makefile.in,v 1.3 2004/05/13 13:38:55 aleigh Exp $ + +include ../continuity/lib/env.mk + +SRCS=radius.c +OBJS=radius.o + +CFLAGS=-I../continuity/include $(CONT_FLAGS) + +world: install + +radius.so: $(OBJS) + $(LD_SHARECMD) -o radius.so $(OBJS) +clean: + $(RM) $(OBJS) *~ radius.so + +install: radius.so radius.h + (rm -f ../continuity/lib/radius.so ; cp radius.so ../continuity/lib) + cp radius.h ../continuity/include + cp radius.xml ../continuity/lib + +depend: + $(MAKEDEPEND) $(DEPFLAGS) -I ../continuity/include $(SRCS) + diff --git a/lc-continuity/mk4/modradius/radius.c b/lc-continuity/mk4/modradius/radius.c new file mode 100644 index 0000000000000000000000000000000000000000..4f8fcd86f60b1094c78c5b88afeeabe389918206 --- /dev/null +++ b/lc-continuity/mk4/modradius/radius.c @@ -0,0 +1,526 @@ +/* + * $Header: /san01/cvs/ashpool/csrc/modradius/Attic/radius.c,v 1.11 2004/05/19 18:34:08 aleigh Exp $ + */ + +/* + * Copyright (c) 2004 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Use, disclosure, copying, distribution, or transmission of this code without + * express permission is prohibited. + */ + +/* RFC 2865: Radius */ + +#include "radius.h" + +#include + +#define RAD_IPADDR 1 +#define RAD_STRING 2 +#define RAD_INTEGER 3 +#define RAD_TEXT 4 +#define RAD_TIME 5 + +/** Protocol Structures **/ +struct radSheader { + uint8_t code; + uint8_t id; + uint16_t len; + unsigned char resp_auth[16]; +}; +typedef struct radSheader radTheader; + +struct radSattrib_header { + uint8_t type; + uint8_t len; +}; +typedef struct radSattrib_header radTattrib_header; + +/** User Structures **/ +struct radSattrib_def { + int id; // The Radius protocol ID for this attribute. + int type; // The type for this attrib; RAD_IPADDR, RAD_INTEGER, etc + const char *name; // The english name for this attribute. +}; +typedef struct radSattrib_def radTattrib_def; + +struct radSrequest { + int req_code; // The request protocol packet type. + int req_id; // The request protocol sequence identifier. + int res_code; // The response protocol packet type + + unsigned char auth[16]; // The protocol authenticator + lstTset *req_set; + lstTset *res_set; +}; +typedef struct radSrequest radTtrans; + +static int radGsock = -1; +static dicTdictionary *radGattribs; + +static void radFconfig(void); +static void radFconfig_attribs(const xmlTtag *attribs); +static void radFdump(unsigned char *msg, ssize_t msg_len); +static void radFrunloop(void); +void radF_attrib_free(radTattrib_def *attrib); +static int radFtype_find(const char *type); +static int radFattrib_value_format(unsigned char *buf, size_t buf_len, + unsigned char *attrib, size_t attrib_len, + int type, size_t *value_len); +static void radFcalc_digest(unsigned char *digest, + unsigned char *secret, + unsigned char *vector); +static int radFdecrypt_password( + radTtrans *t, + unsigned char *buf, + size_t buf_len, + unsigned char *data, + size_t data_len); +static radTtrans *radFtrans_init(void); +static void radFtrans_free(radTtrans *r); + +/***/ + +static int radFtype_find(const char *type) { + if(strcasecmp(type,"ipaddr")==0) return RAD_IPADDR; + if(strcasecmp(type,"string")==0) return RAD_STRING; + if(strcasecmp(type,"integer")==0) return RAD_INTEGER; + if(strcasecmp(type,"text")==0) return RAD_TEXT; + if(strcasecmp(type,"time")==0) return RAD_TIME; + return -1; +} + +static radTtrans *radFtrans_init(void) { + radTtrans *r=(radTtrans *)malloc(sizeof(radTtrans)); + + assert(r!=NULL); + + bzero(r,sizeof(radTtrans)); + + r->req_set=lstFset_init(); + r->res_set=lstFset_init(); + + assert(r->req_set!=NULL); + assert(r->res_set!=NULL); + + return r; +} + +static void radFtrans_free(radTtrans *r) { + assert(r!=NULL); + assert(r->req_set!=NULL); + assert(r->res_set!=NULL); + + lstFset_free(r->req_set); + lstFset_free(r->res_set); + + free(r); +} + +/* Take a given attribute value and convert it into string form. + * This is intended to be used with the raw data from the radius + * packets, so it does perform network to host byte re-ordering. + * + * Returns 0 on success and -1 on error. + */ +static int radFattrib_value_format(unsigned char *buf, size_t buf_len, + unsigned char *attrib, size_t attrib_len, + int type, size_t *value_len) +{ + unsigned int value; + +// utlFhexdump(attrib,attrib_len); + + switch(type) { + case RAD_IPADDR: + if(buf_len<16) { + return -1; + } + + if(attrib_len!=4) { + return -1; + } + + value=1; + memFcopy(attrib,&value,4); + value=htonl(value); + + utlFip_to_str(value,buf,buf_len); + + *value_len=strlen(buf)+1; + + return 0; + + case RAD_STRING: + /* This really means a binary value */ + if(buf_len in config!"); + exit(5); + } + + child=xmlFfind_first_tag_children(tag,"attribs"); + if(child==NULL) { + logFmsg(2,"mod/radius: Unable to find section!"); + exit(5); + } + + radFconfig_attribs(child); +} + +static void radFconfig_attribs(const xmlTtag *attribs) +{ + xmlTiterator *it; + const xmlTtag *tag; + + assert(attribs!=NULL); + + logFmsg(3,"mod/radius: radFconfig_attribs: Called."); + + it=xmlFiterator_init(attribs); + + assert(it!=NULL); + + while((tag=xmlFiterator_next_name(it,"attrib"))!=NULL) { + const char *id; + const char *name; + size_t name_len; + const char *type; + size_t type_len; + + id=xmlFtag_get_attrib_value(tag,"id"); + + name=xmlFfirst_child_value(tag,"name",&name_len); + type=xmlFfirst_child_value(tag,"type",&type_len); + + if(id!=NULL && name!=NULL && type!=NULL) { + radTattrib_def *def; + + def=(radTattrib_def *)malloc(sizeof(radTattrib_def)); + assert(def!=NULL); + + def->name=name; + def->type=radFtype_find(type); + def->id=atoi(id); + + dicFuserdata_update(radGattribs,def->id,(void *)def); + + logFmsg(3,"mod/radius: %s - %s", id, name); + } + } + + xmlFiterator_free(it); +} + +static radTtrans *radFparse(unsigned char *msg, ssize_t msg_len) +{ + int code; + int id; + int len; + int type; + int i; + radTheader *header = (radTheader *) msg; + radTattrib_header *ah; + size_t attrib_offset=0; + radTtrans *req = radFtrans_init(); + + code = header->code; + id = header->id; + len = header->len; + + memFcopy(header->resp_auth,req->auth,16); + + utlFhexdump(msg,msg_len); + + logFmsg(3, "header is %d", sizeof(radTheader)); + + logFmsg(3,"my size was 0x%x", msg_len); + + logFmsg(3, "code was: %d", code); + logFmsg(3, "id was: %d", id); + logFmsg(3, "len was: %d", len); + + logFmsg(3,"head %d", sizeof(radTattrib_header)); + + for(attrib_offset=0;attrib_offsetlen-20;) { + logFmsg(3,"Offset is %d", attrib_offset); + + ah=(msg+20)+attrib_offset; + + logFmsg(3,"attrib: type %u len %u", ah->type, ah->len); + + radTattrib_def *ad=radFattrib_find_idx(ah->type); + + if(ad==NULL) { + logFmsg(3,"Unable to find attribute defenition."); + } else { + unsigned char buf[1024]; + size_t buf_len; + + if(radFattrib_value_format(buf,1024,(unsigned char *)ah+2, + ah->len-2,ad->type,&buf_len)==0) { + logFmsg(3,"value: %s len: %d", buf, buf_len); + + lstFset_badd(req->req_set, ad->name, strlen(ad->name), buf, buf_len); + } else { + logFmsg(3,"radFattrib_value_format() failed."); + } + logFmsg(3,"Attrib %s", ad->name); + } + attrib_offset+=ah->len; + } + + return req; +} + +static void radFrunloop(void) +{ + unsigned char msg[1024]; + struct sockaddr_in sa; + size_t sa_len; + int ret; + radTtrans *trans; + int radius_auth = dlFpipeline_getid("radius_auth"); + + while (1) { + ret = + netFudp_recv(radGsock, (void *) &msg, sizeof(msg), &sa, + &sa_len); + trans=radFparse(msg, ret); + + ret=dlFpipeline_exec(trans,radius_auth,NULL,NULL); + + radFtrans_free(trans); + } +} + +int radFinit(void *p, lstTset * opt) +{ + uint16_t my_port=0; + + radFconfig(); + + radGsock = netFudp_open(&my_port, 2550, "radius"); + + if (radGsock < 0) { + logFmsg(2, "mod/radius: Unable to open radius UDP socket."); + exit(1); + } + + logFmsg(3, "mod/radius: Opened UDP socket %d on port %d", radGsock, my_port); + + radFrunloop(); + + exit(1); +} + +#define AUTH_VECTOR_LEN 16 +#define AUTH_PASS_LEN 16 +#define AUTH_MAXPASS_LEN 48 + + +/* Given the authentication identifier in the protocol + * and the shared-secret, calculates a digest. + */ +static void radFcalc_digest( + unsigned char *digest, + unsigned char *secret, + unsigned char *vector) +{ + unsigned char buffer[128]; + int secretlen; + + logFmsg(3,"Vector is:"); + utlFhexdump(vector,AUTH_VECTOR_LEN); + + /* Use the secret to setup the decryption digest */ + memset(buffer, 0, sizeof(buffer)); + secretlen = strlen((char *)secret); + memcpy((char *)buffer, (char *)secret,secretlen); + memcpy(buffer + secretlen, vector, AUTH_VECTOR_LEN); + + logFmsg(3,"Calculated string to MD5:"); + utlFhexdump(buffer,secretlen+AUTH_VECTOR_LEN); + + md5_calc(digest, buffer, secretlen + AUTH_VECTOR_LEN); + + logFmsg(3,"Calculated MD5 value:"); + + utlFhexdump(digest,16); + + memset(buffer, 0, secretlen+AUTH_VECTOR_LEN); + + return; +} + +/* I am not entirely convinced that this function works properly + * for passwords that are >16 bytes long. + */ + +static int radFdecrypt_password( + radTtrans *t, + unsigned char *buf, + size_t buf_len, + unsigned char *data, + size_t data_len) +{ + + int i; + int j; + char hold_vector[AUTH_VECTOR_LEN]; + char vector[AUTH_VECTOR_LEN]; + char pw_digest[16]; + char *string; + char *ptr; + + bzero(pw_digest,16); + + radFcalc_digest(pw_digest,"foo",t->auth); + + if(buf_lenreq_set,"User-Name"); + + logFmsg(3,"Packet received."); + + if(un!=NULL) { + logFmsg(3,"Authorization request for user: %s", un); + } + + return STATUS_OK; +} + +int radiusFdecrypt_password(radTtrans *t, lstTset *o) { + const char *pw; + size_t pw_len; + char buf[64]; + + pw=lstFset_get(t->req_set,"Password"); + + if(pw==NULL) { + logFmsg(3,"Password not found?"); + return STATUS_ERROR; + } + + pw_len=lstFset_get_vsize(t->req_set,"Password"); + + utlFhexdump(pw,pw_len); + + radFdecrypt_password(t,buf,sizeof(buf),pw,pw_len); + + lstFset_update(t->req_set,"Password",buf); + + pw=lstFset_get(t->req_set,"Password"); + + logFmsg(3,"Final password is: %s", pw); + + return STATUS_OK; +} + +int radFsend_response(radTtrans *t) { + + +} + + + diff --git a/lc-continuity/mk4/modradius/radius.h b/lc-continuity/mk4/modradius/radius.h new file mode 100644 index 0000000000000000000000000000000000000000..170ec36afd82f15f34199c75418b035b6dd90358 --- /dev/null +++ b/lc-continuity/mk4/modradius/radius.h @@ -0,0 +1,21 @@ +/* + * $Header: /san01/cvs/ashpool/csrc/modradius/Attic/radius.h,v 1.2 2004/03/16 16:25:38 aleigh Exp $ + */ + +/* + * Copyright (c) 1994, 2001 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Use, disclosure, copying, distribution, or transmission of this code without + * express permission is prohibited. + */ + +#ifndef _RADIUS_H +#define _RADIUS_H + +#include + +#endif diff --git a/lc-continuity/mk4/modradius/radius.xml b/lc-continuity/mk4/modradius/radius.xml new file mode 100644 index 0000000000000000000000000000000000000000..16a96a92888cb6a7049228741f5b4372fdc45c90 --- /dev/null +++ b/lc-continuity/mk4/modradius/radius.xml @@ -0,0 +1,4 @@ + + radius + radFinit + diff --git a/lc-continuity/mk4/modsite/CVS/Entries b/lc-continuity/mk4/modsite/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..260dbc8f8f466e6f10e1d57856b041e6852e0fd3 --- /dev/null +++ b/lc-continuity/mk4/modsite/CVS/Entries @@ -0,0 +1,7 @@ +/Makefile.in/1.4/Tue May 25 14:37:43 2004//Tmk4_mod6_rc2 +/log.c/1.3/Tue May 25 14:47:55 2004//Tmk4_mod6_rc2 +/site.c/1.70/Tue Jun 22 15:55:49 2004//Tmk4_mod6_rc2 +/site.h/1.18/Tue Jun 22 14:31:28 2004//Tmk4_mod6_rc2 +/site.xml/1.2/Wed May 12 14:29:44 2004//Tmk4_mod6_rc2 +/siteerror.h/1.1/Tue Jun 1 15:11:35 2004//Tmk4_mod6_rc2 +D diff --git a/lc-continuity/mk4/modsite/CVS/Repository b/lc-continuity/mk4/modsite/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..d5c02239fcbc2b5e28b81b9b552bcff3ae99157d --- /dev/null +++ b/lc-continuity/mk4/modsite/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/modsite diff --git a/lc-continuity/mk4/modsite/CVS/Root b/lc-continuity/mk4/modsite/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/modsite/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/modsite/CVS/Tag b/lc-continuity/mk4/modsite/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/modsite/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/modsite/Makefile.in b/lc-continuity/mk4/modsite/Makefile.in new file mode 100644 index 0000000000000000000000000000000000000000..b8f2445a2a03fe7f71f750afb7bbef930033c918 --- /dev/null +++ b/lc-continuity/mk4/modsite/Makefile.in @@ -0,0 +1,24 @@ +# $Header: /san01/cvs/ashpool/csrc/modsite/Attic/Makefile.in,v 1.4 2004/05/25 14:37:43 aleigh Exp $ + +include ../continuity/lib/env.mk + +SRCS=site.c log.c +OBJS=site.o log.o + +CFLAGS=-I../continuity/include $(CONT_FLAGS) -fPIC + +world: install + +site.so: $(OBJS) + $(LD_SHARECMD) -o site.so $(OBJS) +clean: + $(RM) $(OBJS) *~ site.so + +install: site.so site.h site.xml + (rm -f ../continuity/lib/site.so ; cp site.so ../continuity/lib) + cp site.h ../continuity/include + cp site.xml ../continuity/lib + + +depend: + $(MAKEDEPEND) -I../continuity/include $(DEPFLAGS) $(SRCS) diff --git a/lc-continuity/mk4/modsite/log.c b/lc-continuity/mk4/modsite/log.c new file mode 100644 index 0000000000000000000000000000000000000000..095c0740ac422bfebaa969e36d34ad99a70d383a --- /dev/null +++ b/lc-continuity/mk4/modsite/log.c @@ -0,0 +1,433 @@ +#include "../continuity/include/csys.h" +#include "../continuity/mecha/dyn.h" +#include "../continuity/mecha/net.h" +#include "../continuity/include/continuity.h" +#include "../continuity/mecha/lst.h" +#include +#include +#include "site.h" + +static const char *logroot = NULL; /* Path to logging root */ + +#define LOG_AUX 1 +#define LOG_ACCESS 0 + +struct logSfile { + int day; + int month; + int year; + int hour; + int class; + FILE *fh; + unsigned int last_used; + + + struct logSfile *next; + +}; +typedef struct logSfile logTfile; + +static char hostname[64]; +static size_t hostlen; + +static logTfile *logGfile = NULL; + +static pthread_mutex_t logCfile = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t logCfopen = PTHREAD_MUTEX_INITIALIZER; + +int siteFlog_init(void); +static logTfile *logFopen_file(int m, int d, int y, int h, int class); +static logTfile *logFcur_file(int class); +static void logFfile_add(logTfile * f); +static void logFfile_free(logTfile * p); +static int logFreap(int delta); +void logFfile_remove(logTfile * f); +static FILE *logFget_cur_fh(int class); +static int logFwrite(int class, char *format, va_list ap); +int siteFaccess_log(httpTtrans * t, MECHA_UNUSED_ARGUMENT lstTset * opts); + +void siteFset_logroot(const char *lr) { + logroot=lr; +} + +int siteFlog_init(void) +{ + gethostname(hostname, sizeof(hostname)); + hostlen = strlen(hostname); + + return STATUS_OK; +} + +static logTfile *logFopen_file(int m, int d, int y, int h, int class) +{ + char buf[1024]; + logTfile *lf; + int trycount = 5; + + logFreap(3600); + + if (logroot == NULL) + return NULL; + + /* access-04.24.2002.10 */ + + if (class == 1) { + snprintf(buf, sizeof(buf), "%s/aux-%02d.%02d.%d.%02d", logroot, m, + d, y, h); + } else { + snprintf(buf, sizeof(buf), "%s/access-%02d.%02d.%d.%02d", logroot, + m, d, y, h); + } + + lf = (logTfile *) malloc(sizeof(logTfile)); + bzero(lf, sizeof(logTfile)); + + lf->month = m; + lf->day = d; + lf->year = y; + lf->hour = h; + lf->class = class; + lf->last_used = utlFtime(); + + while (trycount != 0) { + lf->fh = fopen(buf, "a"); + + if (lf->fh == NULL) { + logFmsg(2, + "logFopen_file: fopen failure (fn:%s) (er: %d) (tc: %d)", + buf, errno, trycount); + logFreap(0); + } else { + break; + } + + trycount--; + } + + if (lf->fh == NULL) { + logFmsg(2, "Unable to open log after 5 tries, giving up (fn:%s)", + buf); + free(lf); + return NULL; + } + return lf; +} + +/* + * The world was young, the mountains green, No stain yet on the Moon was + * seen, No words were laid on stream or stone When Durin woke and walked + * alone. He named the nameless hills and dells; He drank from yet untasted + * wells; He stooped and looked in Mirrormere And saw a crown of stars + * appear; As gems upon a silver thread; Above the shadow of his head. + * + * The world is grey, the mountains old, The forge's fire is ashen-cold; No harp + * is wrung, no hammer falls: The darkness dwells in Durin's halls; The + * shadow lies upon his tomb In Moria, in Khazad-d?m. But still the sunken + * stars appear In dark and windless Mirrormere; There lies his crown in + * water deep, Till Durin wakes again from his sleep. + */ + +static logTfile *logFcur_file(int class) +{ + logTfile *p; + const struct tm *tme; + + pthread_mutex_lock(&logCfile); + + if (logGfile == NULL) { + pthread_mutex_unlock(&logCfile); + return NULL; + } + p = logGfile; + tme = (const struct tm *) utlFlocaltime(); + + while (1) { + if ((p->month == (tme->tm_mon + 1)) && + (p->day == tme->tm_mday) && + (p->year == (tme->tm_year + 1900)) && + (p->hour == tme->tm_hour) && (p->class == class)) { + pthread_mutex_unlock(&logCfile); + return p; + } + if (p->next == NULL) { + pthread_mutex_unlock(&logCfile); + return NULL; + } + p = p->next; + } +} + +static void logFfile_add(logTfile * f) +{ + pthread_mutex_lock(&logCfile); + f->next = logGfile; + logGfile = f; + pthread_mutex_unlock(&logCfile); +} + +static void logFfile_free(logTfile * p) +{ + if (p != NULL) + free(p); +} + +/* + * logFreap - Close logfiles that haven't been used for some period of time. + */ +static int logFreap(int delta) +{ + logTfile *p, *next; + struct timeval tv; + int i; + + pthread_mutex_lock(&logCfile); + + if (logGfile == NULL) { + pthread_mutex_unlock(&logCfile); + return 0; + } + p = logGfile; + + while (p != NULL) { + gettimeofday(&tv, NULL); + + next = p->next; + + if ((tv.tv_sec - p->last_used) >= (unsigned int) delta) { + logGfile = p->next; + + fclose(p->fh); + + logFfile_free(p); + i++; + } + p = next; + } + + pthread_mutex_unlock(&logCfile); + + return i; +} + +#if 0 +/* + * logFfile_remove - Remove a logfile reference from the global list + * + * This function requires that the global list contain at least one entry and + * does not return an error if the argument entry is not found in the list. + */ + +void logFfile_remove(logTfile * f) +{ + logTfile *p; + + pthread_mutex_lock(&logCfile); + + p = logGfile; + + while (1) { + if (p == f) { + logGfile = p->next; + break; + } + p = p->next; + if (p == NULL) + break; + } + pthread_mutex_unlock(&logCfile); +} +#endif + +static FILE *logFget_cur_fh(int class) +{ + logTfile *file; + + pthread_mutex_lock(&logCfopen); + + file = logFcur_file(class); + + if (file == NULL) { + const struct tm *tme; + tme = (const struct tm *) utlFlocaltime(); + file = + (logTfile *) logFopen_file(tme->tm_mon + 1, tme->tm_mday, + tme->tm_year + 1900, tme->tm_hour, + class); + if (file == NULL) { + pthread_mutex_unlock(&logCfopen); + return NULL; + } + logFfile_add(file); + } + file->last_used = utlFtime(); + + pthread_mutex_unlock(&logCfopen); + return file->fh; +} + +int siteFaccess_log(httpTtrans * t, MECHA_UNUSED_ARGUMENT lstTset * opts) +{ + FILE *fh; + char buf[1024]; + dynTstring *logline; + int ret; + +#ifdef MODSITE_DEBUG + logFmsg(3,"siteFaccess_log: called"); +#endif + + fh = logFget_cur_fh(LOG_ACCESS); + + if (fh == NULL) { + logFmsg(2, "logFget_cur_fh failed (er: %d)", errno); + return STATUS_ERROR; + } + logline = dynFinit(); + + /* CLIENT IP */ + utlFip_to_str(t->cli_ipv4_addr, buf, sizeof(buf)); + dynFsappend(logline, buf); + dynFappend(logline, " ", 1); + + /* EPOCH */ + { + const char *bp = (const char *) utlFcommonlog_time(); + dynFappend(logline, bp, 29); + } + + /* REQUEST */ + dynFappend(logline, "\"", 1); + + { + + const lstTfield *clf = + lstFset_get_field(t->vars, "clf-request", 11); + if (clf != NULL) { + dynFappend(logline, lstFfield_value(clf), + lstFfield_value_len(clf)); + } else { + dynFappend(logline, "REQ_ERR", 7); + } + + dynFappend(logline, "\" ", 2); + } + + /* STATUS */ + /* + * snprintf(buf, sizeof(buf), "%d ", t->res_code); dynFappend(logline, + * buf, strlen(buf)); + */ + dynFappend_print(logline, "%d ", t->res_code); + + { + const lstTfield *length = + lstFset_get_field(t->res_hdrs, "Content-Length", 14); + + if (length != NULL) { + dynFappend(logline, lstFfield_value(length), + lstFfield_value_len(length)); + dynFappend(logline, " ", 1); + } else { + dynFappend(logline, "- ", 2); + } + } + + { + const lstTfield *referer = + lstFset_get_field(t->req_hdrs, "referer", 7); + + if (referer != NULL) { + dynFappend(logline, "\"", 1); + dynFappend(logline, lstFfield_value(referer), + lstFfield_value_len(referer)); + dynFappend(logline, "\" ", 2); + } else { + dynFappend(logline, "\"\" ", 3); + } + } + + { + const lstTfield *agent = + lstFset_get_field(t->req_hdrs, "user-agent", 10); + + if (agent != NULL) { + dynFappend(logline, "\"", 1); + dynFappend(logline, lstFfield_value(agent), + lstFfield_value_len(agent)); + dynFappend(logline, "\" ", 2); + } else { + dynFappend(logline, "\"\" ", 3); + } + } + + /* Country Code Placeholder */ + { + const lstTfield *ccode = lstFset_get_field(t->vars, "ccode", 5); + + if (ccode != NULL) { + dynFappend(logline, lstFfield_value(ccode), + lstFfield_value_len(ccode)); + + dynFappend(logline, " ", 1); + } else { + dynFappend(logline, "-1 ", 3); + } + } + + /* Referer target URL: http://host/URI */ + { + const lstTfield *uri = + lstFset_get_field(t->res_hdrs, "Location", 8); + + if (uri != NULL) { + dynFappend(logline, "\"", 1); + dynFappend(logline, lstFfield_value(uri), + lstFfield_value_len(uri)); + dynFappend(logline, "\" ", 2); + } else { + dynFappend(logline, "- ", 2); + } + } + + /* Response Time Placeholder */ + dynFappend(logline, "-1 ", 3); + + { + const lstTfield *user = lstFset_get_field(t->vars, "auth-user", 9); + if (user != NULL) { + dynFappend(logline, lstFfield_value(user), + lstFfield_value_len(user)); + dynFappend(logline, " ", 1); + } else { + dynFappend(logline, "- ", 2); + } + } + + { + const lstTfield *siteid = lstFset_get_field(t->vars, "siteid", 6); + + if (siteid != NULL) { + dynFappend(logline, lstFfield_value(siteid), + lstFfield_value_len(siteid)); + } else { + dynFappend(logline, "_SID_ERROR", 10); + } + } + + dynFappend(logline, " ", 1); + dynFappend(logline, hostname, hostlen); + + dynFappend(logline, "\n", 1); + + ret = fwrite(dynFgetstr(logline),dynFgetlen(logline),1,fh); + + if (ret < 0 || ret == EOF) { + logFmsg(1, "Log write unexpectadly returned %d/%d", ret, errno); + } + fflush(fh); + + dynFfree(logline); + + return ret; +} + diff --git a/lc-continuity/mk4/modsite/site.c b/lc-continuity/mk4/modsite/site.c new file mode 100644 index 0000000000000000000000000000000000000000..7f2cdb5aab6afd7c6afdc3483b9d888d6600e6ee --- /dev/null +++ b/lc-continuity/mk4/modsite/site.c @@ -0,0 +1,1343 @@ +/* + * $Header: /cvsroot/csrc/modsite/site.c,v 1.51 2004/03/17 15:06:10 aleigh + * Exp $ + */ + +/* + * Copyright (c) 1994, 2001 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Disclosure, copying, distribution, or transmission of this code without + * express permission is prohibited. + */ + +#include "../continuity/include/csys.h" +#include "../continuity/mecha/dyn.h" +#include "../continuity/mecha/net.h" +#include "../continuity/include/continuity.h" +#include "../continuity/mecha/lst.h" +#include +#include +#include "site.h" +#include "siteerror.h" + +#undef MODSITE_DEBUG + +struct siteSacl { + unsigned int ip; + unsigned int netmask; + struct siteSacl *next; +}; +typedef struct siteSacl siteTacl; + +struct siteSsite { + const char *siteid; + size_t siteid_len; + const char *docroot; + size_t docroot_len; + const char *ip_restrict; + const xmlTtag *config; + lstTset *redirects; + hshTvoid_list *external; + hshTvoid_list *options; /* Used to store

%s error.

%s

%s
%s
\n", + error, serror, conFget_build(), hostname); + } else { + httpFwritef(t, + ERROR_FMT, err_string, err_string, err_rfc, err_txt, conFget_build(), hostname); + } + + return STATUS_EXIT; +} + +int siteFfind_mimetype(httpTtrans * t, MECHA_UNUSED_ARGUMENT lstTset * opt) +{ + const char *path, *ext_p, *type; + + path = lstFset_get(t->vars, "path"); + if (path == NULL) { + logFmsg(1, "find_mimetype: path is missing from t->vars!"); + return STATUS_PROCEED; /* Not really an error... */ + } + if ((t->statb.st_mode & S_IFMT) == S_IFDIR) { + lstFset_bupdate(t->res_hdrs, "Content-Type", 12, + "internal/directory", 18); + return STATUS_EXIT; + } + ext_p = strrchr(path, '.'); + + if (ext_p == NULL) + return STATUS_PROCEED; + + ext_p++; + + /* Check to see if the extension is blank */ + if (*ext_p == 0) + return STATUS_PROCEED; + + type = hshFvoid_find(siteGmime_types, ext_p); + + if (type == NULL) { + return STATUS_PROCEED; + } + lstFset_bupdate(t->res_hdrs, "Content-Type", 12, type, strlen(type)); + + return STATUS_EXIT; +} + +int siteFset_mimetype(httpTtrans * t, lstTset * opt) +{ + const lstTfield *type; + + type = lstFset_get_field(opt, "type", 4); + + if (type == NULL) { + logFmsg(2, "force_type: No default mime-type set!"); + return STATUS_ERROR; + } + lstFset_bupdate(t->res_hdrs, "Content-Type", 12, + lstFfield_value(type), lstFfield_value_len(type)); + + return STATUS_PROCEED; +} + +/* + * Send a file. By the time this is called, the current stat structure in the + * request is expected to point to the file that will be served. This file + * will 404 rather than serve a directory. + */ + +int siteFsend_file(httpTtrans * t, MECHA_UNUSED_ARGUMENT lstTset * opt) +{ + const char *path; + char modified[40]; + int ret; + + assert(t != NULL); + + tasFstat_counter_add("http_svc", 0, "siteFsend_file", 1); + + httpFmaterial_compare(t, t); + + if ((t->statb.st_mode & S_IFMT) == S_IFDIR) { + siteFdo_error(t, "404", "Directory found."); + return STATUS_EXIT; + } + if (t->statb.st_mtime == 0) { + /* + * invalid modification time, the stat was likely never done. The + * file is 404. + */ + siteFdo_error(t, "404", "File not found."); + return STATUS_EXIT; + } + path = lstFset_get(t->vars, "path"); + + /* Setup the last-modified time based on the filesystem */ + ret = + utlFhttp_time_print(t->statb.st_mtime, modified, sizeof(modified)); + lstFset_bupdate(t->res_hdrs, "Last-Modified", 13, modified, ret); + +#if WANT_IF_MODIFIED_CHECK + /* + * Check to see if we the client passed us a modified. If it did, check + * to see if we matched, and if we did, return an empty 304 response. The + * client has it cached. + */ + + { + char *hdr_modified; + + hdr_modified = lstFset_get(t->req_hdrs, "if-modified-since"); + + if (hdr_modified != NULL) { + if (t->has_statb == 1 + && t->statb.st_mtime == + utlFhttp_time_parse(hdr_modified)) { +#ifdef MODSITE_DEBUG + logFmsg(3, "sendfile: returning 304."); +#endif + lstFset_nadd(t->res_hdrs, "Content-Length", 0); + + httpFset_status(t, 304, NULL); + httpFstart_response(t); + + return STATUS_EXIT; + } + } + } +#endif + + /* Set the content length and return the file */ + lstFset_nadd(t->res_hdrs, "Content-Length", t->statb.st_size); + + httpFset_status(t, 200, NULL); + httpFstart_response(t); + httpFsend_response(t); + + xfrFmmap(t->conn, path, &t->statb); + + return STATUS_EXIT; +} + +int siteFip_restrict(httpTtrans * t, MECHA_UNUSED_ARGUMENT lstTset * opts) +{ + const char *siteid; + siteTsite *site; + + siteid = lstFset_get(t->vars, "siteid"); + assert(siteid != NULL); + + site = siteFget_by_siteid(siteid); + + assert(site != NULL); + + if (site->ip_restrict != NULL) { + if (siteFipacl_auth(site->ip_restrict, t->cli_ipv4_addr) == 0) { + httpFset_status(t, HTTP_FORBIDDEN, NULL); + httpFstart_response(t); + httpFsend_response(t); + httpFwritef(t, "Access Forbidden"); + return STATUS_EXIT; + } + } + return STATUS_PROCEED; +} + +int siteFredirect(httpTtrans *t, const char *target) { + const char *siteid = lstFset_get(t->vars,"siteid"); + + assert(siteid!=NULL); + + const char *preserve=siteFoption_get(siteid,"preserve_query_on_302"); + if(preserve==NULL) { + return httpFredirect(t,target); + } + + const char *query = lstFset_get(t->vars,"query"); + if(query==NULL) { + return httpFredirect(t,target); + } + + dynTstring *newurl = dynFinit(); + + assert(newurl!=NULL); + + // TODO PERF: This could be done by geting the values and using append rather + // than the more expensive _print() + + if(strstr(target,"?")==NULL) { + dynFappend_print(newurl,"%s?%s",target,query); + } else { + dynFappend_print(newurl,"%s&%s",target,query); + } + + int ret=httpFredirect(t,dynFgetstr(newurl)); + + dynFfree(newurl); + + return ret; +} + + diff --git a/lc-continuity/mk4/modsite/site.h b/lc-continuity/mk4/modsite/site.h new file mode 100644 index 0000000000000000000000000000000000000000..27ffdbfe3e6fda3acdc7b6c53779210c9b442e03 --- /dev/null +++ b/lc-continuity/mk4/modsite/site.h @@ -0,0 +1,56 @@ +/* $Header: /san01/cvs/ashpool/csrc/modsite/Attic/site.h,v 1.18 2004/06/22 14:31:28 aleigh Exp $ */ + +/* Copyright (c) 1994, 2001 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH + * The copyright notice above does not evidence any + * actual or intended publication of such source code. + * + * Disclosure, copying, distribution, or transmission of + * this code without express permission is prohibited. + */ + +#ifndef SITE_H +#define SITE_H + +#include "continuity.h" +#include "mecha.h" +#include "http.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Handlers */ +int siteFinit(void *p, const lstTset *opts); +int siteFset_siteid(httpTtrans *t, lstTset *opts); +int siteFset_userdir(httpTtrans *t, lstTset *opts); +int siteFfind_index(httpTtrans * t, lstTset * opt); +int siteFfind_mimetype(httpTtrans * t, lstTset * opt); +int siteFset_mimetype(httpTtrans * t, lstTset * opt); +int siteFsend_file (httpTtrans * t, lstTset * opt); +int siteFaccess_log(httpTtrans * t, lstTset *opts); +int siteFip_restrict(httpTtrans *t, lstTset *opts); +int siteFset_setup_path (httpTtrans * t, lstTset * opt); +int siteFset_path_info (httpTtrans * t, lstTset * opt); +int siteFredirects(httpTtrans *t, lstTset *opt); + +int siteFsite_data_set(const char *siteid, const char *name, void *data); +void *siteFsite_data_get(const char *siteid, const char *name); + +const xmlTtag *siteFconfig_get_by_siteid (const char *siteid); + +const char *siteFoption_get(const char *siteid, const char *name); +int siteFoption_set(const char *siteid, const char *name, const char *data); +int siteFredirect(httpTtrans *t, const char *target); + +/* depricated */ +int siteFset_pathinfo(httpTtrans *t, lstTset *opts); +int siteFset_path_translated(httpTtrans *t, lstTset *opts); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lc-continuity/mk4/modsite/site.xml b/lc-continuity/mk4/modsite/site.xml new file mode 100644 index 0000000000000000000000000000000000000000..12356e25ed0ddc0233aa13c9ed9dd01acce6daf6 --- /dev/null +++ b/lc-continuity/mk4/modsite/site.xml @@ -0,0 +1,8 @@ + + site + siteFinit + + cmd + http + + diff --git a/lc-continuity/mk4/modsite/siteerror.h b/lc-continuity/mk4/modsite/siteerror.h new file mode 100644 index 0000000000000000000000000000000000000000..063451ea5b646cbc4b6d1d1b6f0ea4c14de79ae4 --- /dev/null +++ b/lc-continuity/mk4/modsite/siteerror.h @@ -0,0 +1,36 @@ +#ifndef _SITEERROR_H +#define _SITEERROR_H + +#define ERROR_FMT "Error %s
" \ +"
" \ +"

Error %s

" \ +"
" \ +"

From RFC 2068 Hypertext Transfer Protocol -- HTTP/1.1:

" \ +"

%s

" \ +"

%s

" \ +"
%s
%s
" + +#endif + diff --git a/lc-continuity/mk4/modssl/CVS/Entries b/lc-continuity/mk4/modssl/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..0f0353a45ae6c57223d6c2e342fbe73da26c8616 --- /dev/null +++ b/lc-continuity/mk4/modssl/CVS/Entries @@ -0,0 +1,10 @@ +/LICENSE/1.1/Fri Mar 12 20:32:51 2004//Tmk4_mod6_rc2 +/Makefile/1.3/Fri Mar 26 21:04:45 2004//Tmk4_mod6_rc2 +/Makefile.osx/1.1/Fri Mar 12 21:07:20 2004//Tmk4_mod6_rc2 +/client.pem/1.1/Fri Mar 12 20:01:06 2004//Tmk4_mod6_rc2 +/dh1024.pem/1.1/Fri Mar 12 20:01:06 2004//Tmk4_mod6_rc2 +/root.pem/1.1/Fri Mar 12 20:01:06 2004//Tmk4_mod6_rc2 +/server.pem/1.1/Fri Mar 12 20:01:06 2004//Tmk4_mod6_rc2 +/ssl.c/1.7/Wed Apr 21 21:47:05 2004//Tmk4_mod6_rc2 +/ssl.h/1.3/Fri Mar 12 20:10:41 2004//Tmk4_mod6_rc2 +D diff --git a/lc-continuity/mk4/modssl/CVS/Repository b/lc-continuity/mk4/modssl/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..d44d7ff90ead77595d74f5685305bd2c46bff904 --- /dev/null +++ b/lc-continuity/mk4/modssl/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/modssl diff --git a/lc-continuity/mk4/modssl/CVS/Root b/lc-continuity/mk4/modssl/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/modssl/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/modssl/CVS/Tag b/lc-continuity/mk4/modssl/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/modssl/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/modssl/LICENSE b/lc-continuity/mk4/modssl/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..72cd3f24f8231f5e50b28707d5e9d2bdbff2b27d --- /dev/null +++ b/lc-continuity/mk4/modssl/LICENSE @@ -0,0 +1,5 @@ + +This product includes software developed by the OpenSSL Project +for use in the OpenSSL Toolkit (http://www.openssl.org/) + + diff --git a/lc-continuity/mk4/modssl/Makefile b/lc-continuity/mk4/modssl/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..d8faa39aedd1cad8de0ea7b982059bbceb8ae474 --- /dev/null +++ b/lc-continuity/mk4/modssl/Makefile @@ -0,0 +1,23 @@ +# $Header: /san01/cvs/ashpool/csrc/modssl/Attic/Makefile,v 1.3 2004/03/26 21:04:45 aleigh Exp $ + +include ../continuity/lib/env.mk + +SRCS=ssl.c +OBJS=ssl.o +OPENSSL=/usr/local/ssl + +CFLAGS=-I../continuity/include $(CONT_FLAGS) -I $(OPENSSL)/include + +world: install + +ssl.so: $(OBJS) + $(LD_SHARECMD) -o ssl.so $(OBJS) -L$(OPENSSL)/lib -lssl -lcrypto + +clean: + $(RM) $(OBJS) *~ ssl.so + +install: ssl.so ssl.h + (rm -f ../continuity/lib/ssl.so ; cp ssl.so ../continuity/lib) + cp ssl.h ../continuity/include + + diff --git a/lc-continuity/mk4/modssl/Makefile.osx b/lc-continuity/mk4/modssl/Makefile.osx new file mode 100644 index 0000000000000000000000000000000000000000..636cdda4e310401ea34ecbc176b449a7c6b83408 --- /dev/null +++ b/lc-continuity/mk4/modssl/Makefile.osx @@ -0,0 +1,23 @@ +# $Header: /san01/cvs/ashpool/csrc/modssl/Attic/Makefile.osx,v 1.1 2004/03/12 21:07:20 aleigh Exp $ + +include ../continuity/lib/env.mk + +SRCS=ssl.c +OBJS=ssl.o +OPENSSL=/usr/local/ssl + +CFLAGS=-I../continuity/include $(CONT_FLAGS) -I $(OPENSSL)/include + +world: install + +ssl.so: $(OBJS) + $(LD_SHARECMD) -o ssl.so $(OBJS) -lssl -lcrypto + +clean: + $(RM) $(OBJS) *~ ssl.so + +install: ssl.so ssl.h + (rm -f ../continuity/lib/ssl.so ; cp ssl.so ../continuity/lib) + cp ssl.h ../continuity/include + + diff --git a/lc-continuity/mk4/modssl/client.pem b/lc-continuity/mk4/modssl/client.pem new file mode 100644 index 0000000000000000000000000000000000000000..06f2e6ce026489d88bbbb61988416b0727cc8136 --- /dev/null +++ b/lc-continuity/mk4/modssl/client.pem @@ -0,0 +1,32 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,6D3B09E4CA5421FF + +SaDJA2MhJ12ZmDxfGkSLhQgjYPEQYqVfs5b4DZTz+9pJqzuNxHrZZU43oArbWBdB +3DKc1THejbyHF2lY7xgPLk/5iax5r+CXesDKZroSliHyERBIOCUgDN6ecwvVGtYv +C8IhlwGPEXyxr59lyV37RjkSUVXYBqiRbLlNIcQtp5T6GkFe+yftOnv6/UADCLTS +Pu8xwkda1rf7dgPwYIKuk2SOTTe1VMDtWacRUGu8NteTJ4aiVaeeo9wdsKId5U2b +Z7NTJjOjvdXOLRonfkGvDXmrmN4eICks0bV0ZBtkULAfGjKNGs6riY+XNGKNRmjI +idRRB0za+EGorpiJ/vbe7n7uaFXIJlfqCwhTi4Up3mS8sR4tLHfmdjp85GV9P9B3 +xX3CHIeG5/EYDt0Qn1gRL5ODL/0O7nFGJslhcQUS6bMmcg9nSzhClTE2gREz0j9g +pwzvRpEkIl3Tw4niZLIX8fW2cEIyKTBMCCG2MDwHHgXRL3SUXkOGeitFefkcXN/z +/UWRS8XQcX7/lGWCiuEpgn+esoirjf8lFNVsx6OT0UXj3oBxGrz1iB/vpu/PMBVQ +JsbEPSh/ElHSDUItw2ytjJmkolRtM01b7cFj16ZxbHjinXWTIGZFWUYIlaeA2zHK +D/NRMFJwjrQYhjRgPqltvbw7M01Co7SNFBwSotARr36FBjsxbOH3F1jY6w+kXvJU +X5m83C9UONM2K7kkKYXbE2yW+kzJF2LFX0Uu4yDluxNG767/WwqiQSI63aIzNAPp +rSsaIMBSbVZia8q49gcvGyuvqBZpwm/PcZwr/PHJjvGs8hdU1ACmyQ== +-----END RSA PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIICFTCCAX4CAgECMA0GCSqGSIb3DQEBBAUAMFcxCzAJBgNVBAYTAlVTMRMwEQYD +VQQKEwpSVEZNLCBJbmMuMRkwFwYDVQQLExBXaWRnZXRzIERpdmlzaW9uMRgwFgYD +VQQDEw9UZXN0IENBMjAwMTA1MTcwHhcNMDEwNTE3MTYxMTM2WhcNMDQwMzA2MTYx +MTM2WjBOMQswCQYDVQQGEwJVUzETMBEGA1UEChMKUlRGTSwgSW5jLjEZMBcGA1UE +CxMQV2lkZ2V0cyBEaXZpc2lvbjEPMA0GA1UEAxMGY2xpZW50MIGfMA0GCSqGSIb3 +DQEBAQUAA4GNADCBiQKBgQCHNWSoNh6msUwYGGd7TYQDsdSG0ao6QXaYjk+78ZyM +QeZUBu2dZFjG4wnzkKwrD4rp/J5PLR9AdxR72lb9AavEOKL2UDHJGsscZkGVw/bz +ZbxrKF2rvdpZSvKP1OhV1MOds/WTpRm1gcmVSoV5vLOMqVjzjHoxQ/+1zpjzMxWL +0wIDAQABMA0GCSqGSIb3DQEBBAUAA4GBACTJhRR5tv8A7dc5+zmKR1Q/i8qE3Mrn +mp/MOXHfX+ifJ/w+twoc/yd4En+7pr+hGsiTofct1JOZDW9Akq/ZGu1+NpVRT7Cw +53EdMwpi7ArwZAsLIUBsKA7QmLTbdwjU5S7WlZ24eygZHyqZrK4Few+JuzlFkkoI +FIDCfinyz24m +-----END CERTIFICATE----- diff --git a/lc-continuity/mk4/modssl/dh1024.pem b/lc-continuity/mk4/modssl/dh1024.pem new file mode 100644 index 0000000000000000000000000000000000000000..aa68d98ec7ba927f8280ada80bb64278409a4d59 --- /dev/null +++ b/lc-continuity/mk4/modssl/dh1024.pem @@ -0,0 +1,5 @@ +-----BEGIN DH PARAMETERS----- +MIGHAoGBANmAnfkETuKHOCWaE+W+F3kM/e7z5A8hZb7OqwGMQrUOaBEAr4BWeZBn +G/87hhwZgNP69/KUchm714qd/PpOspCaUJ20x6PcmKujpAgca/f19HGMBjRawQMk +R9oaBwazuQT0l0rTTKmvpMEcrQQIcVWii3CZI56I56oqF8biGPD7AgEC +-----END DH PARAMETERS----- diff --git a/lc-continuity/mk4/modssl/root.pem b/lc-continuity/mk4/modssl/root.pem new file mode 100644 index 0000000000000000000000000000000000000000..db0c59fbf7bc0ff00c352d8c33f404a059c1cfe4 --- /dev/null +++ b/lc-continuity/mk4/modssl/root.pem @@ -0,0 +1,14 @@ +-----BEGIN CERTIFICATE----- +MIICIjCCAYugAwIBAgIBADANBgkqhkiG9w0BAQQFADBXMQswCQYDVQQGEwJVUzET +MBEGA1UEChMKUlRGTSwgSW5jLjEZMBcGA1UECxMQV2lkZ2V0cyBEaXZpc2lvbjEY +MBYGA1UEAxMPVGVzdCBDQTIwMDEwNTE3MB4XDTAxMDUxNzE2MDExNFoXDTA2MTIy +NTE2MDExNFowVzELMAkGA1UEBhMCVVMxEzARBgNVBAoTClJURk0sIEluYy4xGTAX +BgNVBAsTEFdpZGdldHMgRGl2aXNpb24xGDAWBgNVBAMTD1Rlc3QgQ0EyMDAxMDUx +NzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAmkX40warmH0+lnwD9YjsJhRz +ZX6qXadFry0y2trZ6gMs8Mv33IKPwOu8TE7V+3PESEtjI2wr8juV9OkbIPOm+td5 +M8+6vXyIW+JBo3ch99i0QMTf5/jTgsW+3IjV8yEdiGcZFp2NWKLRvZPq2VRbuF7R +1pvgcaRuBJ0wGOohwnsCAwEAATANBgkqhkiG9w0BAQQFAAOBgQCUB8zMKIlX5io8 +TalbzH9Qke7BcvFAL+wp/5w1ToVsWkNrINSWKv6bl/jcqOD3aPhK7qhaeOU8ZWKL +PoPPCnRl9Wo+1JtsOO3qIgJP79Bl9ooLGahixF2v/gea5qNISjQvwYllLSa//APP +6kXHngO0RIRbiTBYHSkAzm6hDdsvVA== +-----END CERTIFICATE----- diff --git a/lc-continuity/mk4/modssl/server.pem b/lc-continuity/mk4/modssl/server.pem new file mode 100644 index 0000000000000000000000000000000000000000..87376dbf0f258d78856b31a09346f08bf06facf2 --- /dev/null +++ b/lc-continuity/mk4/modssl/server.pem @@ -0,0 +1,32 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,5772A2A7BE34B611 + +1yJ+xAn4MudcIfXXy7ElYngJ9EohIh8yvcyVLmE4kVd0xeaL/Bqhvk25BjYCK5d9 +k1K8cjgnKEBjbC++0xtJxFSbUhwoKTLwn+sBoJDcFzMKkmJXXDbSTOaNr1sVwiAR +SnB4lhUcHguYoV5zlRJn53ft7t1mjB6RwGH+d1Zx6t95OqM1lnKqwekwmotVAWHj +ncu3N8qhmoPMppmzEv0fOo2/pK2WohcJykSeN5zBrZCUxoO0NBNEZkFUcVjR+KsA +1ZeI1mU60szqg+AoU/XtFcow8RtG1QZKQbbXzyfbwaG+6LqkHaWYKHQEI1546yWK +us1HJ734uUkZoyyyazG6PiGCYV2u/aY0i3qdmyDqTvmVIvve7E4glBrtDS9h7D40 +nPShIvOatoPzIK4Y0QSvrI3G1vTsIZT3IOZto4AWuOkLNfYS2ce7prOreF0KjhV0 +3tggw9pHdDmTjHTiIkXqheZxZ7TVu+pddZW+CuB62I8lCBGPW7os1f21e3eOD/oY +YPCI44aJvgP+zUORuZBWqaSJ0AAIuVW9S83Yzkz/tlSFHViOebyd8Cug4TlxK1VI +q6hbSafh4C8ma7YzlvqjMzqFifcIolcbx+1A6ot0UiayJTUra4d6Uc4Rbc9RIiG0 +jfDWC6aii9YkAgRl9WqSd31yASge/HDqVXFwR48qdlYQ57rcHviqxyrwRDnfw/lX +Mf6LPiDKEco4MKej7SR2kK2c2AgxUzpGZeAY6ePyhxbdhA0eY21nDeFd/RbwSc5s +eTiCCMr41OB4hfBFXKDKqsM3K7klhoz6D5WsgE6u3lDoTdz76xOSTg== +-----END RSA PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIICGDCCAYECAgEBMA0GCSqGSIb3DQEBBAUAMFcxCzAJBgNVBAYTAlVTMRMwEQYD +VQQKEwpSVEZNLCBJbmMuMRkwFwYDVQQLExBXaWRnZXRzIERpdmlzaW9uMRgwFgYD +VQQDEw9UZXN0IENBMjAwMTA1MTcwHhcNMDEwNTE3MTYxMDU5WhcNMDQwMzA2MTYx +MDU5WjBRMQswCQYDVQQGEwJVUzETMBEGA1UEChMKUlRGTSwgSW5jLjEZMBcGA1UE +CxMQV2lkZ2V0cyBEaXZpc2lvbjESMBAGA1UEAxMJbG9jYWxob3N0MIGfMA0GCSqG +SIb3DQEBAQUAA4GNADCBiQKBgQCiWhMjNOPlPLNW4DJFBiL2fFEIkHuRor0pKw25 +J0ZYHW93lHQ4yxA6afQr99ayRjMY0D26pH41f0qjDgO4OXskBsaYOFzapSZtQMbT +97OCZ7aHtK8z0ZGNW/cslu+1oOLomgRxJomIFgW1RyUUkQP1n0hemtUdCLOLlO7Q +CPqZLQIDAQABMA0GCSqGSIb3DQEBBAUAA4GBAIumUwl1OoWuyN2xfoBHYAs+lRLY +KmFLoI5+iMcGxWIsksmA+b0FLRAN43wmhPnums8eXgYbDCrKLv2xWcvKDP3mps7m +AMivwtu/eFpYz6J8Mo1fsV4Ys08A/uPXkT23jyKo2hMu8mywkqXCXYF2e+7pEeBr +dsbmkWK5NgoMl8eM +-----END CERTIFICATE----- diff --git a/lc-continuity/mk4/modssl/ssl.c b/lc-continuity/mk4/modssl/ssl.c new file mode 100644 index 0000000000000000000000000000000000000000..d272c59ecc3b21ba429d1141efb4cdfd711f38f1 --- /dev/null +++ b/lc-continuity/mk4/modssl/ssl.c @@ -0,0 +1,196 @@ +/* + * $Header: /san01/cvs/ashpool/csrc/modssl/Attic/ssl.c,v 1.7 2004/04/21 21:47:05 aleigh Exp $ + */ + +/* + * Copyright (c) 1994, 2001 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Use, disclosure, copying, distribution, or transmission of this code without + * express permission is prohibited. + */ + +#include +#include +#include "ssl.h" + +#define KEYFILE "server.pem" +#define PASSWORD "password" + +static SSL_CTX *ctx; +static const char *pass; +static int (*sslGhandler) (netTconn * conn, lstTset * o) = NULL; + +struct sslScontext { + SSL *ssl; + BIO *bio; +}; +typedef struct sslScontext sslTcontext; + +static int password_cb(char *buf, int num, int rwflag, void *userdata) +{ + if (num < strlen(pass) + 1) + return (0); + + strcpy(buf, pass); + return (strlen(pass)); +} + +static SSL_CTX *initialize_ctx(const char *keyfile, const char *password) +{ + SSL_METHOD *meth; + SSL_CTX *ctx; + BIO *bio_err = 0; + + if (!bio_err) { + /* Global system initialization */ + SSL_library_init(); + SSL_load_error_strings(); + + /* An error write context */ + bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); + } + + /* Create our context */ + meth = SSLv23_server_method(); + ctx = SSL_CTX_new(meth); + + /* Load our keys and certificates */ + if (!(SSL_CTX_use_certificate_chain_file(ctx, keyfile))) { + logFmsg(2, "Can't read certificate file."); + exit(1); + } + pass = password; + SSL_CTX_set_default_passwd_cb(ctx, password_cb); + if (!(SSL_CTX_use_PrivateKey_file(ctx, keyfile, SSL_FILETYPE_PEM))) { + logFmsg(2, "Can't read key file."); + exit(1); + } +#if (OPENSSL_VERSION_NUMBER < 0x00905100L) + SSL_CTX_set_verify_depth(ctx, 1); +#endif + + return ctx; +} + +int sslFinit(void *p, lstTset * o) +{ + const char *password, *keyfile, *handler; + + logFmsg(0, "mod/ssl: Secure Sockets Layer (SSL) Engine"); + logFmsg(0, "Copyright (c) 2004, Alex Leigh."); + + password = lstFset_get(o, "cert_password"); + keyfile = lstFset_get(o, "cert_file"); + handler = lstFset_get(o, "handler"); + + if (!keyfile) { + logFmsg(2, "cert_file not specified!"); + exit(1); + } + + if (!password) { + logFmsg(2, "cert_password not specified!"); + exit(1); + } + + if (!handler) { + logFmsg(2, "handler not specified!"); + exit(1); + } + + sslGhandler = dlFget_addr(handler); + if (sslGhandler == NULL) { + logFmsg(2, "Could not map handler: %s", handler); + exit(1); + } + + /* Build our SSL context */ + ctx = initialize_ctx(keyfile, password); +} + +ssize_t sslFio_write(netTconn * conn, const void *buf, size_t len) +{ + sslTcontext *c = (sslTcontext *) conn->data; + ssize_t ret; + + ret = SSL_write(c->ssl, buf, len); + return ret; +} + +ssize_t sslFio_read(netTconn * conn, void *buf, size_t len) +{ + sslTcontext *c = (sslTcontext *) conn->data; + ssize_t ret; + + ret = SSL_read(c->ssl, buf, len); + return ret; +} + +int sslFio_close(netTconn * conn) +{ + sslTcontext *c = (sslTcontext *) conn->data; + int r; + + r = SSL_shutdown(c->ssl); + if (!r) { + shutdown(conn->sd, 1); + r = SSL_shutdown(c->ssl); + } + return close(conn->sd); +} + +ssize_t sslFio_writev(struct netSconn * conn, const struct iovec * iov, + int iovcnt) +{ + int i, r; + ssize_t written = 0; + sslTcontext *c = (sslTcontext *) conn->data; + + for (i = 0; i < iovcnt; i++) { + r = SSL_write(c->ssl, iov[i].iov_base, iov[i].iov_len); + if (r < 1) { + return written; + } + written += r; + } +} + +void sslFprivate_free(sslTcontext * c) +{ + free(c); +} + +int sslFhandler(void *p, const lstTset * arg) +{ + netTconn *conn = (netTconn *) p; + sslTcontext *private = (sslTcontext *) malloc(sizeof(sslTcontext)); + SSL *ssl; + BIO *sbio; + int r; + + sbio = BIO_new_socket(conn->sd, BIO_NOCLOSE); + ssl = SSL_new(ctx); + SSL_set_bio(ssl, sbio, sbio); + + SSL_set_accept_state(ssl); + + if (SSL_accept(ssl) < 1) { + conn->io_close(conn); + return STATUS_ERROR; + } + + private->ssl = ssl; + private->bio = sbio; + + conn->io_close = sslFio_close; + conn->io_write = sslFio_write; + conn->io_read = sslFio_read; + conn->data = private; + conn->data_free = sslFprivate_free; + + return (sslGhandler) (p, arg); +} diff --git a/lc-continuity/mk4/modssl/ssl.h b/lc-continuity/mk4/modssl/ssl.h new file mode 100644 index 0000000000000000000000000000000000000000..244b5b3f599fea39a4d5f0a33d1241591ebadd4e --- /dev/null +++ b/lc-continuity/mk4/modssl/ssl.h @@ -0,0 +1,30 @@ +/* + * $Header: /san01/cvs/ashpool/csrc/modssl/Attic/ssl.h,v 1.3 2004/03/12 20:10:41 aleigh Exp $ + */ + +/* + * Copyright (c) 1994, 2001 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Use, disclosure, copying, distribution, or transmission of this code without + * express permission is prohibited. + */ + +#ifndef _SSL_H +#define _SSL_H + +#include +#include + +int sslFinit(void *p, lstTset * o); +int sslFhandler(void *p, const lstTset * arg); + +ssize_t sslFio_write(netTconn * conn, const void *buf, size_t len); +ssize_t sslFio_read(netTconn * conn, void *buf, size_t len); +int sslFio_close(netTconn * conn); +ssize_t sslFio_writev(struct netSconn * conn, const struct iovec * iov, int iovcnt); + +#endif diff --git a/lc-continuity/mk4/modtcl/CVS/Entries b/lc-continuity/mk4/modtcl/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..e0a8e8713d771abef93364301d2e21d0479b8a1b --- /dev/null +++ b/lc-continuity/mk4/modtcl/CVS/Entries @@ -0,0 +1,3 @@ +/Makefile.in/1.1/Wed May 19 19:48:27 2004//Tmk4_mod6_rc2 +D/src//// +D/tcl8.3.4//// diff --git a/lc-continuity/mk4/modtcl/CVS/Repository b/lc-continuity/mk4/modtcl/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..358366ae72be64a2ff10e16d80615744dda9d7a6 --- /dev/null +++ b/lc-continuity/mk4/modtcl/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/modtcl diff --git a/lc-continuity/mk4/modtcl/CVS/Root b/lc-continuity/mk4/modtcl/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/modtcl/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/modtcl/CVS/Tag b/lc-continuity/mk4/modtcl/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/modtcl/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/modtcl/Makefile.in b/lc-continuity/mk4/modtcl/Makefile.in new file mode 100644 index 0000000000000000000000000000000000000000..74a84407f7992698012433afb9e82240b96a330d --- /dev/null +++ b/lc-continuity/mk4/modtcl/Makefile.in @@ -0,0 +1,17 @@ +# $Id: Makefile.in,v 1.1 2004/05/19 19:48:27 aleigh Exp $ + +world: tcl8.3.4/unix/libtcl8.3.a + (cd src;$(MAKE)) + +clean: + (cd src;$(MAKE) clean) + +realclean: clean + (cd tcl8.3.4/unix;make clean) + +tcl8.3.4/unix/libtcl8.3.a: + (cd tcl8.3.4/unix;./configure --disable-shared --enable-threads;make) +# cp tcl8.3.4/unix/libtcl83.a tcl8.3.4/unix/libtcl8.3.a + +depend: + echo No depend diff --git a/lc-continuity/mk4/modtcl/src/CVS/Entries b/lc-continuity/mk4/modtcl/src/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..300a137ed573cd96ac51d70cd60c5b80e1ba27fb --- /dev/null +++ b/lc-continuity/mk4/modtcl/src/CVS/Entries @@ -0,0 +1,6 @@ +/Makefile/1.6/Wed May 12 18:00:19 2004//Tmk4_mod6_rc2 +/cmds.c/1.5/Wed Apr 21 21:47:06 2004//Tmk4_mod6_rc2 +/modtcl.c/1.7/Wed Apr 21 21:47:06 2004//Tmk4_mod6_rc2 +/modtcl.h/1.3/Thu Mar 11 00:52:02 2004//Tmk4_mod6_rc2 +/modtcl.xml/1.1/Wed May 12 18:00:19 2004//Tmk4_mod6_rc2 +D diff --git a/lc-continuity/mk4/modtcl/src/CVS/Repository b/lc-continuity/mk4/modtcl/src/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..41cf584d2ca0dee2b2a35513e08287451f7d7a4f --- /dev/null +++ b/lc-continuity/mk4/modtcl/src/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/modtcl/src diff --git a/lc-continuity/mk4/modtcl/src/CVS/Root b/lc-continuity/mk4/modtcl/src/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/modtcl/src/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/modtcl/src/CVS/Tag b/lc-continuity/mk4/modtcl/src/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/modtcl/src/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/modtcl/src/Makefile b/lc-continuity/mk4/modtcl/src/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..11cbf751ef41df8f5b398adc2eed0d311d93ec75 --- /dev/null +++ b/lc-continuity/mk4/modtcl/src/Makefile @@ -0,0 +1,22 @@ +# $Header: /san01/cvs/ashpool/csrc/modtcl/src/Attic/Makefile,v 1.6 2004/05/12 18:00:19 aleigh Exp $ + +include ../../continuity/lib/env.mk + +SRCS=modtcl.c cmds.c +OBJS=modtcl.o cmds.o + +CFLAGS=-I../../continuity/include -I../tcl8.3.4/generic/ $(CONT_FLAGS) -fPIC + +world: install + +modtcl.so: $(OBJS) + $(LD_SHARECMD) -o modtcl.so $(OBJS) ../tcl8.3.4/unix/libtcl8.3.a +clean: + $(RM) $(OBJS) *~ modtcl.so + +install: modtcl.so modtcl.h + (rm -f ../../continuity/lib/modtcl.so ; cp modtcl.so ../../continuity/lib) + cp modtcl.h ../../continuity/include + cp ../tcl8.3.4/generic/tcl.h ../../continuity/include + cp ../tcl8.3.4/generic/tclDecls.h ../../continuity/include + cp modtcl.xml ../../continuity/lib diff --git a/lc-continuity/mk4/modtcl/src/cmds.c b/lc-continuity/mk4/modtcl/src/cmds.c new file mode 100644 index 0000000000000000000000000000000000000000..cc6d37a887284721acb90e61c519439f24c7834c --- /dev/null +++ b/lc-continuity/mk4/modtcl/src/cmds.c @@ -0,0 +1,764 @@ +#pragma ident "$Header: /san01/cvs/ashpool/csrc/modtcl/src/Attic/cmds.c,v 1.5 2004/04/21 21:47:06 aleigh Exp $" + +/* + * Copyright (c) 1994, 2002 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Disclosure, copying, distribution, or transmission of this code without + * express permission is prohibited. + */ + +#include +#include "db.h" +#include "modtcl.h" + +struct tclSfn_vector { + void (*tclFbind_dyn_command) (char *name, Tcl_CmdProc * proc); +}; +typedef struct tclSfn_vector tclTfn_vector; + +static tclTcmd tclGcmds[] = { + {"ta_log", tclFta_log, NULL}, + {"ta_write", tclFta_write, NULL}, + {"ta_startresponse", tclFta_startresponse, NULL}, + {"ta_setstatus", tclFta_setstatus, NULL}, + {"ta_http_var_get", tclFta_http_vars_get, NULL}, + {"ta_http_res_get", tclFta_http_res_get, NULL}, + {"ta_http_req_get", tclFta_http_req_get, NULL}, + {"ta_http_query_get", tclFhttp_query_get, NULL}, + {"ta_http_var_set", tclFta_http_var_set, NULL}, + {"ta_http_res_set", tclFta_http_res_set, NULL}, + {"ta_http_req_set", tclFta_http_req_set, NULL}, + {"ta_http_query_value", tclFhttp_query_value, NULL}, + {"ta_pwd", tclFta_pwd, NULL}, + {"ta_list_get", tclFlist_get, NULL}, + {"ta_http_query_parse", tclFhttp_query_parse, NULL}, + {"ta_db_open", tclFdb_open, NULL}, + {"ta_db_select", tclFdb_select, NULL}, + {"ta_db_getrow", tclFdb_getrow, NULL}, + {"ta_db_close", tclFdb_close, NULL}, + {"ta_jpg_getsize", tclFjpg_getsize, NULL}, + {"ta_urldecode", tclFurl_decode, NULL}, + {"ta_urlencode", tclFurl_encode, NULL}, + {"tav_set", tclFtav_set, NULL}, + {"tav_get", tclFtav_get, NULL}, + {"tav_exists", tclFtav_exists, NULL}, + {NULL, NULL, NULL} +}; + +static tclTcmd *tclGdyn_cmds = NULL; +static int tclGdyn_count = 0; +/* TLS classes: */ +static int tclGtls_db; /* Database Connections */ + +static hshTvoid_list *tclGtav_hash; +static pthread_rwlock_t tclLtav_hash; + +void tclFbind_dyn_command(char *name, Tcl_CmdProc * proc) +{ + char *n; + + assert(name != NULL); + assert(proc != NULL); + + logFmsg(3, + "Bind external TCL command. cmd: %s addr: 0x%x", + name, proc); + + if (tclGdyn_cmds == 0) { + tclGdyn_cmds = malloc(sizeof(tclTcmd) * 2); + tclGdyn_cmds->name = NULL; + tclGdyn_count = 1; + } else { + tclGdyn_count++; + tclGdyn_cmds = + realloc(tclGdyn_cmds, sizeof(tclTcmd) * (tclGdyn_count + 1)); + } + + n = malloc(strlen(name) + 1); + strcpy(n, name); + + tclGdyn_cmds[tclGdyn_count - 1].name = n; + tclGdyn_cmds[tclGdyn_count - 1].proc = proc; + tclGdyn_cmds[tclGdyn_count].name = NULL; + + return; +} + +/* + * Setup various locals in this file. this is called from the + * initialization function in modtcl.c + */ +void tclFcmd_init(void) +{ + tclGtls_db = tlsFregister((void *(*)(void *)) dbFclose); + tclGtav_hash = hshFvoid_init((void (*)(void *)) lstFset_free); + pthread_rwlock_init(&tclLtav_hash, NULL); +} + +void tclFsetup_cmds(Tcl_Interp * interp) +{ + tclFcmds_register(interp, tclGcmds); + tclFcmds_register(interp, tclGdyn_cmds); +} + +void tclFcmds_register(Tcl_Interp * interp, tclTcmd * cmd) +{ + if (cmd == NULL) + return; + + while (cmd->name != NULL) { + /* + * logFmsg(3,"mod/tcl: tclFcmds_register: Binding proc %s to 0x%x", + * cmd->name, cmd->proc); + */ + Tcl_CreateCommand(interp, cmd->name, cmd->proc, cmd->clientData, + NULL); + ++cmd; + } +} + +int tclFta_log(ClientData ignored, Tcl_Interp * interp, int argc, + char **argv) +{ + if (argc != 3) { + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " loglevel string\"", NULL); + return TCL_ERROR; + } + logFmsg(atoi(argv[1]), "TCL: %s", argv[2]); + + return TCL_OK; +} + +int tclFta_write(ClientData ignored, Tcl_Interp * interp, int argc, + char **argv) +{ + httpTtrans *t; + + if (argc != 2) { + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " string\"", NULL); + return TCL_ERROR; + } + t = httpFthread_gettrans(); + assert(t != NULL); + + httpFwrite(t, argv[1], strlen(argv[1])); + + return TCL_OK; +} + +int tclFta_startresponse(ClientData ignored, Tcl_Interp * interp, int argc, + char **argv) +{ + httpTtrans *t; + + if (argc != 1) { + Tcl_AppendResult(interp, "wrong # args: No arguments", NULL); + return TCL_ERROR; + } + t = httpFthread_gettrans(); + assert(t != NULL); + + httpFstart_response(t); + + return TCL_OK; +} + +int tclFta_setstatus(ClientData ignored, Tcl_Interp * interp, int argc, + char **argv) +{ + httpTtrans *t; + + if (argc != 2) { + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " respcode\"", NULL); + return TCL_ERROR; + } + t = httpFthread_gettrans(); + assert(t != NULL); + + httpFset_status(t, atoi(argv[1]), NULL); + + return TCL_OK; +} + +int tclFta_http_vars_get(ClientData ignored, Tcl_Interp * interp, int argc, + char **argv) +{ + httpTtrans *t; + char *v; + + if (argc != 2) { + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " string\"", NULL); + return TCL_ERROR; + } + t = httpFthread_gettrans(); + assert(t != NULL); + + v = lstFset_get(t->vars, argv[1]); + + if (v != NULL) { + Tcl_SetResult(interp, v, TCL_VOLATILE); + return TCL_OK; + } + Tcl_SetResult(interp, "", TCL_STATIC); + return TCL_OK; +} + + +int tclFta_http_req_get(ClientData ignored, Tcl_Interp * interp, int argc, + char **argv) +{ + httpTtrans *t; + char *v; + + if (argc != 2) { + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " string\"", NULL); + return TCL_ERROR; + } + t = httpFthread_gettrans(); + assert(t != NULL); + + v = lstFset_get(t->req_hdrs, argv[1]); + + if (v != NULL) { + Tcl_SetResult(interp, v, TCL_VOLATILE); + return TCL_OK; + } + Tcl_SetResult(interp, "", TCL_STATIC); + return TCL_OK; +} + +int tclFhttp_query_get(ClientData ignored, Tcl_Interp * interp, int argc, + char **argv) +{ + httpTtrans *t; + char *v; + + if (argc != 2) { + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " string\"", NULL); + return TCL_ERROR; + } + t = httpFthread_gettrans(); + assert(t != NULL); + + v = lstFset_get(t->query, argv[1]); + + if (v != NULL) { + Tcl_SetResult(interp, v, TCL_VOLATILE); + return TCL_OK; + } + Tcl_SetResult(interp, "", TCL_STATIC); + return TCL_OK; +} + + +int tclFta_http_res_get(ClientData ignored, Tcl_Interp * interp, int argc, + char **argv) +{ + httpTtrans *t; + char *v; + + if (argc != 2) { + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " string\"", NULL); + return TCL_ERROR; + } + t = httpFthread_gettrans(); + assert(t != NULL); + + v = lstFset_get(t->res_hdrs, argv[1]); + + if (v != NULL) { + Tcl_SetResult(interp, v, TCL_VOLATILE); + return TCL_OK; + } + Tcl_SetResult(interp, "", TCL_STATIC); + return TCL_OK; +} + +int tclFta_pwd(ClientData ignored, Tcl_Interp * interp, int argc, + char **argv) +{ + httpTtrans *t; + char *path, *pb, *p; + int len; + + if (argc != 1) { + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + NULL); + return TCL_ERROR; + } + t = httpFthread_gettrans(); + assert(t != NULL); + + path = lstFset_get(t->vars, "path"); + if (path == NULL) { + Tcl_AppendResult(interp, "Could not get path.", NULL); + return TCL_ERROR; + } + len = strlen(path); + + pb = Tcl_Alloc(len + 1); + strncpy(pb, path, len + 1); + + p = (pb + len); + + while (1) { + if (*p == '/') { + *p = '\0'; + Tcl_SetResult(interp, pb, TCL_DYNAMIC); + return TCL_OK; + break; + } + if (p == pb) { + Tcl_SetResult(interp, "", TCL_STATIC); + return TCL_OK; + } + p--; + } +} + +int tclFta_http_var_set(ClientData ignored, Tcl_Interp * interp, int argc, + char **argv) +{ + httpTtrans *t; + + if (argc != 3) { + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + "name value", NULL); + return TCL_ERROR; + } + t = httpFthread_gettrans(); + if (t == NULL) { + Tcl_AppendResult(interp, "Could not find transaction.", NULL); + return TCL_ERROR; + } + lstFset_update(t->vars, argv[1], argv[2]); + + return TCL_OK; +} + +int tclFta_http_res_set(ClientData ignored, Tcl_Interp * interp, int argc, + char **argv) +{ + httpTtrans *t; + + if (argc != 3) { + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + "name value", NULL); + return TCL_ERROR; + } + t = httpFthread_gettrans(); + if (t == NULL) { + Tcl_AppendResult(interp, "Could not find transaction.", NULL); + return TCL_ERROR; + } + lstFset_update(t->res_hdrs, argv[1], argv[2]); + + return TCL_OK; +} + +int tclFta_http_req_set(ClientData ignored, Tcl_Interp * interp, int argc, + char **argv) +{ + httpTtrans *t; + + if (argc != 3) { + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + "name value", NULL); + return TCL_ERROR; + } + t = httpFthread_gettrans(); + if (t == NULL) { + Tcl_AppendResult(interp, "Could not find transaction.", NULL); + return TCL_ERROR; + } + lstFset_update(t->req_hdrs, argv[1], argv[2]); + + return TCL_OK; +} + +int tclFurl_decode(ClientData ignored, Tcl_Interp * interp, int argc, + char **argv) +{ + dynTstring *dyn; + + if (argc != 2) { + Tcl_AppendResult(interp, "bad argumentation: should be \"", + argv[0], "url\"", NULL); + return TCL_ERROR; + } + dyn = dynFinit(); + utlFurl_decode(dyn, argv[1]); + + Tcl_AppendResult(interp, dynFgetstr(dyn), NULL); + dynFfree(dyn); + return TCL_OK; +} + +int tclFurl_encode(ClientData ignored, Tcl_Interp * interp, int argc, + char **argv) +{ + dynTstring *dyn; + + if (argc != 2) { + Tcl_AppendResult(interp, "bad argumentation: should be \"", + argv[0], "url\"", NULL); + return TCL_ERROR; + } + dyn = dynFinit(); + utlFurl_encode(dyn, argv[1]); + + Tcl_AppendResult(interp, dynFgetstr(dyn), NULL); + dynFfree(dyn); + return TCL_OK; +} + + + +int tclFlist_get(ClientData ignored, Tcl_Interp * interp, int argc, + char **argv) +{ + lstTset *p; + char *d; + + if (argc != 3) { + Tcl_AppendResult(interp, "bad argumentation: should be \"", + argv[0], "list name\"", NULL); + return TCL_ERROR; + } + + p = tlsFget(argv[1], 0); + + if (p == NULL) { + Tcl_SetResult(interp, "", TCL_STATIC); + return TCL_OK; + } + d = lstFset_get(p, argv[2]); + if (d == NULL) { + Tcl_SetResult(interp, "", TCL_STATIC); + return TCL_OK; + } + Tcl_AppendResult(interp, d, NULL); + return TCL_OK; +} + +int tclFhttp_query_value(ClientData ignored, Tcl_Interp * interp, int argc, + char **argv) +{ + httpTtrans *t; + char *query, *value; + lstTset *set; + + if (argc != 2) { + Tcl_AppendResult(interp, "bad argumentation: should be \"", + argv[0], "name\"", NULL); + return TCL_ERROR; + } + + t = httpFthread_gettrans(); + if (t == NULL) { + Tcl_AppendResult(interp, "Could not find transaction.", NULL); + return TCL_ERROR; + } + + set = httpFget_query (t); + if (set == NULL) { + Tcl_SetResult(interp, "", TCL_STATIC); + return TCL_OK; + } + + value = lstFset_get(set, argv[1]); + if (value == NULL) { + Tcl_SetResult(interp, "", TCL_STATIC); + return TCL_OK; + } + + Tcl_AppendResult(interp, value, NULL); + + return TCL_OK; +} + + +int tclFhttp_query_parse(ClientData ignored, Tcl_Interp * interp, int argc, + char **argv) +{ + httpTtrans *t; + char *tlsid, *query; + lstTset *set; + + if (argc != 1) { + Tcl_AppendResult(interp, "bad argumentation: should be \"", + argv[0], "\"", NULL); + return TCL_ERROR; + } + t = httpFthread_gettrans(); + if (t == NULL) { + Tcl_AppendResult(interp, "Could not find transaction.", NULL); + return TCL_ERROR; + } + query = lstFset_get(t->vars, "query"); + if (query == NULL) { + Tcl_SetResult(interp, "", TCL_STATIC); + return TCL_OK; + } + set = qryFlst_parse(query); + if (set == NULL) { + Tcl_SetResult(interp, "", TCL_STATIC); + return TCL_OK; + } + tlsid = tlsFadd_makeid(set, 0); + Tcl_AppendResult(interp, tlsid, NULL); + + return TCL_OK; +} + +int tclFdb_close(ClientData ignored, Tcl_Interp * interp, int argc, + char **argv) +{ + void *db; + + if (argc != 2) { + Tcl_AppendResult(interp, "bad argumentation: should be \"", + argv[0], " db\""); + return TCL_ERROR; + } + /* Doing this will cause the close if it's a valid handle */ + tlsFdel(argv[1], tclGtls_db); + + return TCL_OK; +} + +int tclFdb_open(ClientData ignored, Tcl_Interp * interp, int argc, + char **argv) +{ + httpTtrans *t; + void *db; + char *tlsid, *query; + + assert(interp != NULL); + + if (argc != 4) { + Tcl_AppendResult(interp, "bad argumentation: should be \"", + argv[0], " user password service\"", NULL); + return TCL_ERROR; + } + t = httpFthread_gettrans(); + if (t == NULL) { + Tcl_AppendResult(interp, "Could not find transaction.", NULL); + return TCL_ERROR; + } + db = dbFopen(argv[1], argv[2], argv[3]); + if (db == NULL) { + Tcl_AppendResult(interp, "Database open failed.", NULL); + return TCL_ERROR; + } + tlsid = tlsFadd_makeid(db, tclGtls_db); + Tcl_AppendResult(interp, tlsid, NULL); + + return TCL_OK; +} + +int tclFdb_select(ClientData ignored, Tcl_Interp * interp, int argc, + char **argv) +{ + httpTtrans *t; + char *tlsid, *query; + void *db; + lstTset *set; + + if (argc != 3) { + Tcl_AppendResult(interp, "bad argumentation: should be \"", + argv[0], " conn sql\"", NULL); + return TCL_ERROR; + } + t = httpFthread_gettrans(); + if (t == NULL) { + Tcl_AppendResult(interp, "Could not find transaction.", NULL); + return TCL_ERROR; + } + db = tlsFget(argv[1], tclGtls_db); + if (db == NULL) { + Tcl_AppendResult(interp, "Invalid database handle.", NULL); + return TCL_ERROR; + } + set = dbFselect(db, argv[2]); + if (set == NULL) { + Tcl_AppendResult(interp, "dbFselect failed.", NULL); + return TCL_ERROR; + } + tlsid = tlsFadd_makeid(set, 0); + Tcl_AppendResult(interp, tlsid, NULL); + + return TCL_OK; +} + +int tclFdb_getrow(ClientData ignored, Tcl_Interp * interp, int argc, + char **argv) +{ + httpTtrans *t; + int res; + void *db; + lstTset *set; + + if (argc != 3) { + Tcl_AppendResult(interp, "bad argumentation: should be \"", + argv[0], " conn resultset\"", NULL); + return TCL_ERROR; + } + t = httpFthread_gettrans(); + if (t == NULL) { + Tcl_AppendResult(interp, "Could not find transaction.", NULL); + return TCL_ERROR; + } + db = tlsFget(argv[1], tclGtls_db); + if (db == NULL) { + Tcl_AppendResult(interp, "Invalid database handle.", NULL); + return TCL_ERROR; + } + set = tlsFget(argv[2], 0); + if (set == NULL) { + Tcl_AppendResult(interp, "Invalid resource set handle.", NULL); + return TCL_ERROR; + } + res = dbFgetrow(db, set); + + if (res == -1) { + Tcl_AppendResult(interp, "dbFgetrow failed.", NULL); + return TCL_ERROR; + } + if (res == 2) + Tcl_SetResult(interp, "0", TCL_STATIC); + else + Tcl_SetResult(interp, "1", TCL_STATIC); + + return TCL_OK; +} + +/* + * Return the height and width of a given jpeg file. This requires mod/image + * to work. Returns the string "width height" or "" on error. + */ +int tclFjpg_getsize(ClientData ignored, Tcl_Interp * interp, int argc, + char **argv) +{ + int h, w; + char buf[32]; + + if (argc != 2) { + Tcl_AppendResult(interp, "bad argumentation: should be \"", + argv[0], " filename\"", NULL); + return TCL_ERROR; + } + if (imgFjpeg_size(argv[1], &w, &h) == -1) { + Tcl_AppendResult(interp, "Invalid file.", NULL); + return TCL_ERROR; + } + snprintf(buf, 32, "%d %d", w, h); + + Tcl_AppendResult(interp, buf, NULL); + + return TCL_OK; +} + +/* + * tav_set array key value + */ +int tclFtav_set(ClientData ignored, Tcl_Interp * interp, int argc, + char **argv) +{ + lstTset *set; + + if (argc != 4) { + Tcl_AppendResult(interp, + "bad argumentation: should be tav_set array key value", + NULL); + return TCL_ERROR; + } + + pthread_rwlock_wrlock(&tclLtav_hash); + + set = (lstTset *) hshFvoid_find(tclGtav_hash, argv[1]); + + if (set == NULL) { + set = lstFset_create(argv[1]); + hshFvoid_add(tclGtav_hash, argv[1], set); + } + + lstFset_update(set, argv[2], argv[3]); + + pthread_rwlock_unlock(&tclLtav_hash); + + return TCL_OK; +} + +/* + * tav_get array key + */ +int tclFtav_get(ClientData ignored, Tcl_Interp * interp, int argc, + char **argv) +{ + lstTset *set; + + if (argc != 3) { + Tcl_AppendResult(interp, + "bad argumentation: should be tav_get array key", + NULL); + return TCL_ERROR; + } + + pthread_rwlock_wrlock(&tclLtav_hash); + + set = (lstTset *) hshFvoid_find(tclGtav_hash, argv[1]); + + if (set != NULL) + Tcl_AppendResult(interp, lstFset_get(set, argv[2]), NULL); + + pthread_rwlock_unlock(&tclLtav_hash); + + return TCL_OK; +} + +/* + * tav_exists array key + */ +int tclFtav_exists(ClientData ignored, Tcl_Interp * interp, int argc, + char **argv) +{ + lstTset *set; + char *value; + + if (argc != 3) { + Tcl_AppendResult(interp, + "bad argumentation: should be tav_exists array key", + NULL); + return TCL_ERROR; + } + + pthread_rwlock_wrlock(&tclLtav_hash); + + set = (lstTset *) hshFvoid_find(tclGtav_hash, argv[1]); + + if (set != NULL) { + if (lstFset_get(set, argv[2]) != NULL) { + Tcl_AppendResult(interp, "1", NULL); + } else { + Tcl_AppendResult(interp, "0", NULL); + } + } else { + Tcl_AppendResult(interp, "0", NULL); + } + + pthread_rwlock_unlock(&tclLtav_hash); + + return TCL_OK; +} diff --git a/lc-continuity/mk4/modtcl/src/modtcl.c b/lc-continuity/mk4/modtcl/src/modtcl.c new file mode 100644 index 0000000000000000000000000000000000000000..a96f5b339609fd01fccb0ff85869bbd772064b45 --- /dev/null +++ b/lc-continuity/mk4/modtcl/src/modtcl.c @@ -0,0 +1,432 @@ +#pragma ident "$Header: /san01/cvs/ashpool/csrc/modtcl/src/Attic/modtcl.c,v 1.7 2004/04/21 21:47:06 aleigh Exp $" + +/* + * Copyright (c) 1994, 2002 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright + * notice above does not evidence any actual or intended publication of such + * source code. + * + * Disclosure, copying, distribution, or transmission of this code without + * express permission is prohibited. + */ + +/* + The biggest problem with the TCL system is the fact that TCL doesn't really + support a mechanism to *copy* an interpreter. This is too bad, too. Ideally + what really ought to happen is that we create an interpreter, run it through + all of it's init tcl scripts to load people's various library functions, and + then just clone it for each of the threads that happens to need one. That would + save having to constantly run through the script initialization for each time the + interpreter is created. +*/ + +#include +#include +#include +#include "../tcl8.3.4/generic/tclInt.h" +#include "modtcl.h" + +#define CLEANUP_PROC "_cont_cleanup" +#define GETINIT_PROC "_cont_getinit" + +static void tclFinterp_create(tclTthr_data * data); +static void tclFinterp_delete(tclTthr_data * data); + +/* + * The init interpreter which is used to create the init script. + */ +Tcl_Interp *tclGinterp = NULL; + +/* + * Init script contianing all the procs. This was generated after the + * libraries were loaded and it used by tclFinterp_create. + */ +char *tclGinit_script = NULL; + +/* pthread key used to hold tclTthr_data in TLS */ +pthread_key_t tclKdata; + +/* She shines, in a world full of ugliness */ + +static char tclGhard_procs[] = + "proc " CLEANUP_PROC " {{autoclose 0}} {\n" + " foreach g [info globals] {\n" + " if {![string match tcl* $g]\n" + " && ![string match error* $g]\n" + " && [string compare env $g] != 0} {\n" + " upvar #0 $g gv\n" + " if [info exists gv] {\n" + " unset gv\n" + " }\n" + " }\n" + " }\n" + "}\n" + "proc " GETINIT_PROC " {} {\n" + " set script {}\n" + " foreach p [info procs] {\n" + " set args {}\n" + " foreach a [info args $p] {\n" + " if [info default $p $a def] {\n" + " set a [list $a $def]\n" + " }\n" + " lappend args $a\n" + " }\n" + " append script [list proc $p $args [info body $p]]\n" + " append script \\n\n" " }\n" " return $script\n" "}\n"; + + +/* + * Output a TCL script error message to the log. + */ +void tclFerror(Tcl_Interp * interp) +{ + char *err; + + assert(interp != NULL); + + logFmsg(1, "TCL error: %s", interp->result); + + err = Tcl_GetVar(tclGinterp, "errorInfo", TCL_GLOBAL_ONLY); + if (err != NULL) + logFmsg(1, "%s", err); +} + +/* + * CAPI function to be called from module.cfg to initialize the TCL module. + * This function should initialize the master interpreters and run any + * required startup scripts. + */ +int tclFinit(void *p, lstTset * opts) +{ + char *initfile; + + logFmsg(0, "mod/tcl: TCL Script Engine (module)"); + logFmsg(0, + "Copyright (c) 2002, Alex Leigh. All Rights Reserved"); + logFmsg(0, + "TCL 8.3.4 Copyright (c) Regents of UC, Sun Microsystems, Scriptics"); + + tclFcmd_init(); + + /* She reads the minds of all the people that pass her by */ + + if (pthread_key_create(&tclKdata, &tclFdata_free) != 0) { + logFmsg(2, "Unable to create tclKdata."); + abort(); + } + + tclGinterp = Tcl_CreateInterp(); + + assert(tclGinterp != NULL); + + if (Tcl_Eval(tclGinterp, tclGhard_procs) != TCL_OK) { + tclFerror(tclGinterp); + logFmsg(2, "Tcl_Eval for hard procs failed."); + abort(); + } + + /* Bind all the continuity commands */ + tclFsetup_cmds(tclGinterp); + + /* Load .tcl library files here to setup the global init state. */ + initfile = lstFset_get(opts, "init"); + if (initfile != NULL) { + if (Tcl_EvalFile(tclGinterp, initfile) != TCL_OK) { + tclFerror(tclGinterp); + } else { + logFmsg(0, "Loaded %s", initfile); + } + } + + /* + * Create one proc that will be used to initialize future procs to this + * state. This is because there is no a mechanism in libtcl to actually + * copy an interpreter. + */ + + if (Tcl_Eval(tclGinterp, GETINIT_PROC) != TCL_OK) { + tclFerror(tclGinterp); + logFmsg(2, "Unable to create init interp. Aborting."); + abort(); + } + + tclGinit_script = (char *) malloc(strlen(tclGinterp->result) + 1); + assert(tclGinit_script != NULL); + + strcpy(tclGinit_script, tclGinterp->result); + + return STATUS_PROCEED; +} + +int tclFinterp_cleanup(tclTthr_data * data) +{ + Tcl_Interp *interp = data->interp; + Tcl_DString script; + + Tcl_ResetResult(interp); + + Tcl_DStringInit(&script); + Tcl_DStringAppendElement(&script, CLEANUP_PROC); + if (Tcl_Eval(interp, script.string) != TCL_OK) { + tclFerror(interp); + } + Tcl_DStringFree(&script); + + if (data->delete == 0) { + Tcl_ResetResult(interp); + } else { + /* Delete Function */ + } + return 0; +} + +/* + * Destructor for TLS memory to destroy the data structure. + */ +void tclFdata_free(void *p) +{ + tclTthr_data *data = (tclTthr_data *) p; + + assert(p != NULL); + + if (data->interp != NULL) + Tcl_DeleteInterp(data->interp); + free(data); +} + +tclTthr_data *tclFdata_get(void) +{ + tclTthr_data *data; + + data = pthread_getspecific(tclKdata); + if (data == NULL) { + data = malloc(sizeof(tclTthr_data)); + bzero(data, sizeof(tclTthr_data)); + pthread_setspecific(tclKdata, data); + } + return data; +} + +/* + * Allocate an interpreter, or, if one is already associated with this + * thread, return that one. + * + * Results: TCL Interpreter + * + * Side Effects; May create a new TCL interpreter. + */ +Tcl_Interp *tclFinterp_get(char *server) +{ + tclTthr_data *data; + + data = tclFdata_get(); + + assert(data != NULL); + +#ifdef TCL_DEBUG + if (data->interp == NULL) { + logFmsg(3, "No TCL interpreter previously allocated."); + } else { + logFmsg(3, "TCL Interpreter previously allocated."); + } +#endif + + /* Update times in thread data */ + + if (data->interp == NULL) { + tclFinterp_create(data); + } + return data->interp; +} + +/* + * Create a TCL Interpreter and initialize it + */ +static void tclFinterp_create(tclTthr_data * data) +{ + Tcl_Interp *interp; + + data->interp = interp = Tcl_CreateInterp(); + + tclFsetup_cmds(interp); + + /* Evaluate the script to create all procs. */ + Tcl_Eval(interp, tclGinit_script); +} + + + /* In the machina, you can hear her scream. */ + +/* + * tclFeval - Evaluate a TCL script in the current thread for the given + * server. + */ +int tclFeval(char *server, char *script) +{ + Tcl_Interp *interp; + + interp = tclFinterp_get(server); + + assert(interp != NULL); + +#ifdef TCL_DEBUG + logFmsg(3, "tclFeval: tclFinterp_get returned interp 0x%x", interp); +#endif + + if (Tcl_Eval(interp, script) != TCL_OK) { + logFmsg(3, "tclFeval: result is %s", interp->result); + } +} + +static void tclFinterp_delete(tclTthr_data * data) +{ + Tcl_DeleteInterp(data->interp); + data->interp = NULL; + data->delete = 0; +} + +/* + * Process a TCL script that is the entire file, IE, not an embedded TCL + * script. + */ +int tclFhandler(httpTtrans * t, lstTset * opts) +{ + Tcl_Interp *interp; + char *ppath = lstFset_get(t->vars, "path"); + + interp = tclFinterp_get("tessier"); + assert(interp != NULL); + + lstFset_update(t->res_hdrs, "Content-Type", "text/html"); + + if (Tcl_EvalFile(interp, ppath) != TCL_OK) { + tclFerror(interp); + httpFwrite(t, interp->result, strlen(interp->result)); + } + return STATUS_EXIT; +} + +static void tclFtext_chunk(dynTstring * dsPtr, char *text) +{ + dynFappend(dsPtr, "t", 1); + dynFappend(dsPtr, text, strlen(text) + 1); +} + +static void tclFpage_parse(dynTstring * dsPtr, char *page) +{ + register char *s, *e, *t = page; + + assert(page != NULL); + assert(dsPtr != NULL); + + while ((s = strstr(t, "<%")) != NULL && (e = strstr(s, "%>")) != NULL) { + + *s = '\0'; + tclFtext_chunk(dsPtr, t); + *s = '<'; + s += 2; + dynFappend(dsPtr, "s", 1); + if (*s == '=') { + ++s; + } + *e = '\0'; + dynFappend(dsPtr, s, e - s + 1); + *e = '%'; + t = e + 2; + } + tclFtext_chunk(dsPtr, t); +} + +/* + * Dyn should be a dynamic string that contains a chunked + * page, in this format; + * tSometexthere\0sAscript\0tMoretext\0\0 + */ +static void tclFpage_render(dynTstring * dyn, httpTtrans * t) +{ + char *p; + Tcl_Interp *interp; + + assert(dyn != NULL); + assert(t != NULL); + + interp = tclFinterp_get("tessier"); + + assert(interp != NULL); + + p = dynFgetstr(dyn); + + assert(p != NULL); + + while (1) { + if (*p == 't') { + p++; + httpFwrite(t, p, strlen(p)); + } else { + p++; + if (Tcl_Eval(interp, p) != TCL_OK) { + char *err; + logFmsg(2, "script failed: [%d] %s", + interp->errorLine, interp->result); + err = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY); + if (err != NULL) + logFmsg(2, "%s", err); + } + } + + p += strlen(p) + 1; + + if ((p - dynFgetstr(dyn)) >= dynFgetlen(dyn)) + break; + } +} + +/* + * Process an HTML file that may contain embedded TCL. + */ +int tclFembed_handler(httpTtrans * t, lstTset * opts) +{ + char *ppath; + char *map, *page; + dynTstring *script; + lstTset *query; + + assert(t != NULL); + + ppath = lstFset_get(t->vars, "path"); + + assert(ppath != NULL); + + script = dynFinit(); + + assert(script != NULL); + + map = (char *) mmcFmap(ppath, &t->statb, NULL); + if (map == NULL) { + logFmsg(1, "mmcFmap returned NULL for %s", + ppath); + dynFfree(script); + return STATUS_ERROR; + } + + if (map == (char *) 0x1) { + logFmsg(1, "map returned 0x1 for %s", ppath); + dynFfree(script); + return STATUS_ERROR; + } + + page = strFcopy(map); + + lstFset_update(t->res_hdrs, "Content-Type", "text/html"); + httpFset_status(t, 200, NULL); + httpFstart_response(t); + + tclFpage_parse(script, page); + tclFpage_render(script, t); + + dynFfree(script); + free(page); + + return STATUS_EXIT; +} diff --git a/lc-continuity/mk4/modtcl/src/modtcl.h b/lc-continuity/mk4/modtcl/src/modtcl.h new file mode 100644 index 0000000000000000000000000000000000000000..01637fe2d158fdec92787001bb3daca6db9c7a53 --- /dev/null +++ b/lc-continuity/mk4/modtcl/src/modtcl.h @@ -0,0 +1,73 @@ +/* Copyright (c) 1994, 2002 Alex Leigh, All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH + * The copyright notice above does not evidence any + * actual or intended publication of such source code. + * + * Disclosure, copying, distribution, or transmission of + * this code without express permission is prohibited. + */ + +#ifndef MODTCL_H +#define MODTCL_H + +#ifndef __GNUC__ +#pragma ident "$Header: /san01/cvs/ashpool/csrc/modtcl/src/Attic/modtcl.h,v 1.3 2004/03/11 00:52:02 eric Exp $" +#endif + +#include +#include +#include + +struct tclSthr_data { + Tcl_Interp *interp; + int delete; +}; +typedef struct tclSthr_data tclTthr_data; + +struct tclScmd { + char *name; + Tcl_CmdProc *proc; + ClientData clientData; +}; +typedef struct tclScmd tclTcmd; + +void tclFdata_free(void *p); +int tclFinit(void *p, lstTset * opts); +tclTthr_data *tclFdata_get(void); +Tcl_Interp *tclFinterp_get(char *server); +int tclFeval(char *server, char *script); +int tclFinterp_cleanup(tclTthr_data *data); +void tclFerror(Tcl_Interp *interp); + +/* cmds.c */ +void tclFsetup_cmds(Tcl_Interp *interp); +void tclFcmds_register(Tcl_Interp *interp, tclTcmd *cmd); +int tclFta_log(ClientData ignored, Tcl_Interp *interp, int argc, char **argv); +int tclFta_write(ClientData ignored, Tcl_Interp *interp, int argc, char **argv); +int tclFta_startresponse(ClientData ignored, Tcl_Interp *interp, int argc, char **argv); +int tclFta_setstatus(ClientData ignored, Tcl_Interp *interp, int argc, char **argv); +void tclFbind_dyn_command(char *name, Tcl_CmdProc *proc); +int tclFta_http_vars_get(ClientData ignored, Tcl_Interp *interp, int argc, char **argv); +int tclFta_http_res_get(ClientData ignored, Tcl_Interp *interp, int argc, char **argv); +int tclFta_http_req_get(ClientData ignored, Tcl_Interp *interp, int argc, char **argv); +int tclFta_pwd(ClientData ignored, Tcl_Interp *interp, int argc, char **argv); +int tclFta_http_req_set(ClientData ignored, Tcl_Interp *interp, int argc, char **argv); +int tclFta_http_res_set(ClientData ignored, Tcl_Interp *interp, int argc, char **argv); +int tclFta_http_var_set(ClientData ignored, Tcl_Interp *interp, int argc, char **argv); +int tclFhttp_query_value(ClientData ignored, Tcl_Interp *interp, int argc, char **argv); +int tclFlist_get(ClientData ignored, Tcl_Interp *interp, int argc, char **argv); +int tclFhttp_query_parse(ClientData ignored, Tcl_Interp *interp, int argc, char **argv); +int tclFdb_open(ClientData ignored, Tcl_Interp *interp, int argc, char **argv); +int tclFdb_select(ClientData ignored, Tcl_Interp *interp, int argc, char **argv); +int tclFdb_getrow(ClientData ignored, Tcl_Interp *interp, int argc, char **argv); +int tclFjpg_getsize(ClientData ignored, Tcl_Interp *interp, int argc, char **argv); +int tclFurl_encode(ClientData ignored, Tcl_Interp *interp, int argc, char **argv); +int tclFurl_decode(ClientData ignored, Tcl_Interp *interp, int argc, char **argv); +int tclFdb_close(ClientData ignored, Tcl_Interp *interp, int argc, char **argv); +int tclFtav_set(ClientData ignored, Tcl_Interp * interp, int argc, char **argv); +int tclFtav_get(ClientData ignored, Tcl_Interp * interp, int argc, char **argv); +int tclFtav_exists(ClientData ignored, Tcl_Interp * interp, int argc, char **argv); +int tclFhttp_query_get(ClientData ignored, Tcl_Interp * interp, int argc, char **argv); +#endif + diff --git a/lc-continuity/mk4/modtcl/src/modtcl.xml b/lc-continuity/mk4/modtcl/src/modtcl.xml new file mode 100644 index 0000000000000000000000000000000000000000..aed371e77d6150b2120411e640b2a1e6cbb41fe6 --- /dev/null +++ b/lc-continuity/mk4/modtcl/src/modtcl.xml @@ -0,0 +1,8 @@ + + tcl + tclFinit + + db + image + + diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/CVS/Entries b/lc-continuity/mk4/modtcl/tcl8.3.4/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..84f1347dc0bf4a0bada7d51ca40b891e530684f9 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/CVS/Entries @@ -0,0 +1,13 @@ +/ChangeLog/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/README/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/changes/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/license.terms/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +D/compat//// +D/doc//// +D/generic//// +D/library//// +D/mac//// +D/tests//// +D/tools//// +D/unix//// +D/win//// diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/CVS/Repository b/lc-continuity/mk4/modtcl/tcl8.3.4/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..2f60d22bea675572069512765e73f60d7eee6895 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/modtcl/tcl8.3.4 diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/CVS/Root b/lc-continuity/mk4/modtcl/tcl8.3.4/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/CVS/Tag b/lc-continuity/mk4/modtcl/tcl8.3.4/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/ChangeLog b/lc-continuity/mk4/modtcl/tcl8.3.4/ChangeLog new file mode 100644 index 0000000000000000000000000000000000000000..4a2d4ba82b6b66672bb06f792b4015c333f2df3b --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/ChangeLog @@ -0,0 +1,5515 @@ +2001-10-19 Jeff Hobbs + + ************************ + **** 8.3.4 TAGGED **** + ************************ + + * generic/tclInt.h: + * generic/tclObj.c: added -DPURIFY object allocation option. + + * unix/configure: + * unix/tcl.m4: added -lc to LIBS on AIX + +2001-10-19 Daniel Steffen + + * mac/tclMacFile.c: fix to glob -join, wasn't traversing aliased + folders + + * mac/tclMacLoad.c: : corrected utf8 handling, comparison of + package names to code fragment names changed to only match on the + length of package name, this allows for fragment names with version + numbers appended (backport from 8.4) + +2001-10-18 Jeff Hobbs + + * unix/configure: regend + * unix/tcl.m4 (SC_ENABLE_GCC): enabled better recognition of gcc. + + * tests/clock.test (clock-8.1): + * generic/tclDate.c (RelativeMonth): + * generic/tclGetDate.y (RelativeMonth): corrected off-by-one-day + error in clock scan with relative months and years during swing + hours. [Bug #413397, Patch #414024] (lavana) + +2001-10-17 Jeff Hobbs + + * unix/tclUnixPipe.c (PipeInputProc, PipeOutputProc): do immediate + retry when error is returned with errno == EINTR. + [Bug #415131] (leger) + +2001-10-17 Daniel Steffen + + * mac/tclMacProjects.sea.hqx: updated projects with new version + numbers and resource reorganization; included XML versions of + the projects for CW Pro5 or Pro7 users. + + * mac/tcltkMacBuildSupport.sea.hqx: updated build instructions + and readme's; MoreFiles 1.5.2 added; XML versions of projects. + +2001-10-17 Daniel Steffen + + Backport of mac specific changes added to 8.4 since 8.3.3: + + * generic/tcl.h: removed line continuation in #if clause as this + breaks the mac resource compiler (note that *.r files include tcl.h) + + * compat/strftime.c: + * mac/tclMacTime.c: + * mac/tclMacPort.h: + * generic/tclInt.decls: + * generic/tclIntPlatDecls.h: + * generic/tclStubInit.c: timezone support for mac via + TclpGetTZName() like on windows, using an inverse timezone table + adapted from tclDate.c to map gmtoffset in seconds gotten from + the MacOS APIs to a timezone string, as there is no good way to get + this info from MacOS. I had to make up some unusual timezones and + arbitrarily decide on the most standard of the multiple choices + + * generic/tclCmdAH.c: + * generic/tclDate.c: + * generic/tclGetDate.y: + * mac/tclMacInt.h: + * mac/tclMacFile.c: default mac epoch changed to standard unix + epoch and related mac time/date handling changes from TIP17. + + * mac/tclMacFile.c: glob -dir compatibility for unix style + relative paths, from TIP17 + + * mac/tclMacAppInit.c: support for WASTE text library using + temporary memory, setting has no effect if WASTE is not used. + + * tests/cmdAH.test: access time not available on the mac, skip the + atime touch test + + * mac/tclMacApplication.r: + * mac/tclMacLibrary.r: + * mac/tclMacOSA.r: + * mac/tclMacResource.r: updated copyrights/dates in version + strings; reorganized resources among these files to avoid + multiple copies in applications and shared libraries, the script + libraries are now no longer duplicated in Tclsh but are only + included in the resources of Tcl.shlb. + + * tests/cmdMZ.test: + * tests/exec.test: + * tests/fileName.test: added missing cleanups/tests/catches that + caused tests to fail on the mac. + + * doc/tclvars.n: documentation error, env(PWD) should be env(HOME) + +2001-10-17 Jeff Hobbs + + * unix/tclUnixFCmd.c: minor casts to prevent warnings + + * unix/configure: regened + * unix/configure.in: added preset CFLAGS check from HEAD to + prevent --enable-gcc from adding "-g -O2" + +2001-10-17 Don Porter + + * changes: First draft of Tcl changes for 8.3.4 release. + +2001-10-16 Don Porter + + * unix/Makefile.in: Restored install of tclConfig.sh file + to $TCL_EXEC_PREFIX/lib. It contains platform-dependent + definitions, and must not be installed under $TCL_PREFIX. + +2001-10-16 Jeff Hobbs + + * unix/tclLoadAout.c (TclGuessPackageName): removed unused vars + and fixed warnings. [Bug #446622] (lim) + +2001-10-16 Daniel Steffen + + * unix/Makefile.in: + * unix/configure.in: + * unix/tcl.m4: Added support for MacOSX / Darwin + * unix/configure: Autoconf + + * unix/mkLinks: + * unix/mkLinks.tcl: Added check for case-insensitive + filesystems and conditionalized links that only differ by + case (needed for MacOSX/Darwin on HFS+ FS) + + * unix/tclLoadDyld.c: change in binary extension format from + MachO bundles to standard .dylib dynamic libraries like on + other unices. **POTENTIAL INCOMPATIBILITY*** extensions + will have to be recompiled as .dylib's. + Improved error handling and use of DStrings and + Tcl_UtfToExternalDString instead of sprintf to build up + symbol and library names. [Patch 435258] + +2001-10-16 Don Porter + + * tests/trace.test (trace-18.1): Added test to demonstrate + memory corruption problems. [Bug 219393]. + + * unix/mkLinks: 'make mklinks' for Tcl_SetMainLoop. + + * unix/Makefile.in (dist: target): Removed copy of files + matching mac/*.exp; no such files. + +2001-10-15 Andreas Kupries + + * generic/tclInt.decls (TclExpandCodeArray,TclGetInstructionTable): + Added to internal stubs table. Tclcompiler (Tclpro project) + needs them if used as loadable package under Windows. Changed + signatures. We don't want to describe compiler internal + structures in "tclInt.h". + + * generic/tclCompile.h: S.a. Removed function declarations. + * generic/tclCompile.c: S.a. Adapted to changed signatures. + +2001-10-15 Jeff Hobbs + + * unix/configure: + * unix/configure.in: + * win/configure: + * win/configure.in: + * win/tcl.m4: reworked to be a little cleaner in comparison to + each other, and to AC_SUBST even empty vars for win/tclConfig.sh + + * generic/tcl.h: + * win/tclWinPort.h: moved #define of WIN32 to tcl.h where __WIN32__ + is defined and added #ifndef check. + +2001-10-12 Jeff Hobbs + + * tests/winPipe.test: removed obsolete cat16 tests, fixed + winpipe-1.22 to only run on Win9*. + + * tests/timer.test: slight skewing of after values to allow for + correct results on burdened machines. + + * tests/winFCmd.test: differentiated test results for win2k + versus not. + + * win/tclWinInit.c: cleanup back-ported from 8.4 HEAD. + + * win/tclWinPort.h: move winsock2.h include, header cleanup + back-ported from 8.4 HEAD. + + * library/encoding/ebcdic.enc: + * tools/encoding/ebcdic.txt: EBCDIC charset mapping. + [Patch #219323] (nijtmans) + + * library/encoding/tis-620.enc: + * tools/encoding/tis-620.txt: TIS-620 charset mapping. + [Patch #467423] (poonlap) + +2001-10-11 Miguel Sofer + + * generic/tclLiteral.c: (TclReleaseLiteral) insured that + self-referential bytecodes are properly cleaned up on interpreter + deletion [Bug 467523] (Ronnie Brunner) + +2001-10-10 Don Porter + + * tests/unixInit.test: Corrected restore of ::env(LANG). + +2001-10-10 Donal K. Fellows + + * generic/tclCmdMZ.c: Removed pointless #include and SCAN_* flags. + (Tcl_RegexpObjCmd): Fixed match area offset bug. + (Tcl_StringObjCmd): Fixed STR_INDEX and STR_REPEAT, and tidied up + STR_IS and STR_LENGTH. + +2001-10-09 Miguel Sofer + + * generic/tclObj.c: removed duplicate definition of tclObjsAlloced + and tclObjsFreed. These variables only exist when compiling with + TCL_COMPILE_STATS, and are already defined in generic/tclExecute.c + +2001-10-09 Jeff Hobbs + + * generic/tclFileName.c (ExtractWinRoot): corrected ABR error + + * doc/bgerror.n: back-port from 8.4 that indicates new behavior of + bgerror in Tk. + +2001-10-09 Miguel Sofer + + * generic/tclLiteral.c: (TclReleaseLiteral) reverted previous + patch for [Bug 467523] - cure is worse than the illness. + +2001-10-09 Donal K. Fellows + + * tests/io.test (io-32.8): Fixed typo. + +2001-10-08 Donal K. Fellows + + * tests/cmdIL.test: test improvement. + * doc/lsort.n: Doc improvement. + * generic/tclCmdIL.c (InfoBodyCmd): Strengthened bytecode + isolation [fix orig. by Miguel Sofer] + (Tcl_LsortObjCmd, SortCompare): Symbolic indexing values plus + correct handling of indexing relative to end in [lsort]. + +2001-10-05 Miguel Sofer + + * generic/tclLiteral.c: (TclReleaseLiteral) insured that + self-referential bytecodes are properly cleaned up on interpreter + deletion [Bug 467523] (Ronnie Brunner) + +2001-10-04 Jeff Hobbs + + * library/encoding/cp1250.enc: + * library/encoding/cp1251.enc: + * library/encoding/cp1252.enc: + * library/encoding/cp1253.enc: + * library/encoding/cp1254.enc: + * library/encoding/cp1255.enc: + * library/encoding/cp1256.enc: + * library/encoding/cp1257.enc: + * library/encoding/cp1258.enc: + * library/encoding/cp874.enc: + * library/encoding/cp936.enc: + * library/encoding/cp949.enc: + * library/encoding/cp950.enc: + * library/encoding/iso8859-10.enc: + * library/encoding/iso8859-13.enc: + * library/encoding/iso8859-14.enc: + * library/encoding/iso8859-15.enc: + * library/encoding/iso8859-16.enc: + * library/encoding/iso8859-6.enc: + * library/encoding/iso8859-7.enc: + * library/encoding/iso8859-8.enc: + * library/encoding/koi8-u.enc: + * library/encoding/macCroatian.enc: + * library/encoding/macCyrillic.enc: + * library/encoding/macGreek.enc: + * library/encoding/macIceland.enc: + * library/encoding/macRoman.enc: + * library/encoding/macTurkish.enc: + * tools/encoding/cp1250.txt: + * tools/encoding/cp1251.txt: + * tools/encoding/cp1252.txt: + * tools/encoding/cp1253.txt: + * tools/encoding/cp1254.txt: + * tools/encoding/cp1255.txt: + * tools/encoding/cp1256.txt: + * tools/encoding/cp1257.txt: + * tools/encoding/cp1258.txt: + * tools/encoding/cp874.txt: + * tools/encoding/cp932.txt: + * tools/encoding/cp936.txt: + * tools/encoding/cp949.txt: + * tools/encoding/cp950.txt: + * tools/encoding/iso8859-1.txt: + * tools/encoding/iso8859-10.txt: + * tools/encoding/iso8859-13.txt: + * tools/encoding/iso8859-14.txt: + * tools/encoding/iso8859-15.txt: + * tools/encoding/iso8859-16.txt: + * tools/encoding/iso8859-2.txt: + * tools/encoding/iso8859-3.txt: + * tools/encoding/iso8859-4.txt: + * tools/encoding/iso8859-5.txt: + * tools/encoding/iso8859-6.txt: + * tools/encoding/iso8859-7.txt: + * tools/encoding/iso8859-8.txt: + * tools/encoding/iso8859-9.txt: + * tools/encoding/koi8-r.txt: + * tools/encoding/macCentEuro.txt: + * tools/encoding/macCroatian.txt: + * tools/encoding/macCyrillic.txt: + * tools/encoding/macGreek.txt: + * tools/encoding/macIceland.txt: + * tools/encoding/macRoman.txt: + * tools/encoding/macTurkish.txt: + Updated encodings with latest mappings from www.unicode.org. This + did not include some Mac encodings that have special multi-unichar + translations now (like symbols, dingbats and japanese). Also does + not include big5, gb or euc* as those have different formats in + the latest Unicode version that need new conversion tools. Not + all related .enc files changed as some had been updated separately. + +2001-10-03 Jeff Hobbs + + * README: + * generic/tcl.h: + * mac/README: + * tools/tcl.hpj.in: + * tools/tcl.wse.in: + * unix/Makefile.in: + * unix/README: + * unix/configure: + * unix/configure.in: + * unix/tcl.m4: + * unix/tcl.spec: + * win/README: + * win/REAME.binary: updated patchlevel to 8.3.4. Changed urls to + point to www.tcl-tk.net where applicable. + + * win/configure: + * win/configure.in: + * win/tcl.m4: + * win/Makefile.in: added proper Win64 build support. + updated patchlevel to 8.3.4. + + * generic/tclEvent.c (Tcl_FinalizeThread): moved freeing of + tclLibraryPath to before the thread exit handlers are called. + Slight modification to change on 2001-09-24. + +2001-09-28 Miguel Sofer + + * doc/FindExec.3: added a comment not to change the working + directory before calling Tcl_GetNameOfExecutable [Bug 219215] + +2001-09-28 Andreas Kupries + + * generic/tclIO.c: added (on behalf of Kevin Kenny + ) two more '(ClientData)' casts + on calls to Tcl_Preserve and Tcl_Release -- ones that Vince + apparently missed. + +2001-09-27 Don Porter + + * generic/tclIO.c (ChannelTimerProc): Added Tcl_Preserve() + and Tcl_Release() to fix segfault introduced by the 2001-09-26 + changes. [Bug 465494] + + * doc/TCL_MEM_DEBUG.3: Updated out-of-date reference to + #define GUARD_SIZE. + +2001-09-26 Andreas Kupries + + * The changes below fix [Bug #462317] where Expect tried to read + more than was in the buffers and then blocked in the OS call as + its pty channel driver provides no blockmodeproc through which + the OS could be notified of blocking-behaviour. Because of this + the general I/O core has to take more care than usual to + preserve the semantics of non-blocking channels. + + * generic/tclIO.c (Tcl_ReadRaw): Do not read from the driver if + the channel is non-blocking and the fileevent causing the read + was generated by a timer. We do not know if there is data + available from the OS. Instead of going to the OS for more and + potentially blocking we simply signal EWOULDBLOCK to the higher + levels to cause the system to wait for true fileevents. + (GetInput): Same as before. + (ChannelTimerProc): Added set and clear of CHANNEL_TIMER_FEV. + + * generic/tclIO.h (CHANNEL_TIMER_FEV): New flag for channels. Is + set if a fileevent was generated by a timer, the channel is not + blocking and the driver did not provide a blockmodeproc. In that + case the I/O core has to be especially careful about going to + the driver for more data. + +2001-09-24 Andreas Kupries + + * The change below fixes [Bug #464380]. The bug was reported by + Ronnie Brunner . He also + provided the patch. + + * generic/tclEvent.c (Tcl_Finalize): Moved release of + 'tclLibraryPath' to Tcl_FinalizeThread. + (Tcl_FinalizeThread): See above, new place for release of + 'tclLibraryPath'. + +2001-09-20 Jeff Hobbs + + * win/makefile.vc: updated IA64 compile settings + + * win/tclWinInit.c: added extra processor definitions. (mstacy) + + * win/tclWinSock.c (SocketThread): corrected pointer cast for _WIN64. + + * win/tclWinNotify.c: removed unnecessary winsock include (it is + already in from tclWinPort.h). + + * win/tclWinPort.h: changed winsock.h include to winsock2.h. + Reverses change from 2000-11-16, but is necessary for WIN64. + Extensions should comply with defined OS words, or use #ifndef. + +2001-09-19 Jeff Hobbs + + * generic/tclTest.c (TestcmdtokenCmd): corrected pointer + storage/retrieval for 64bit machines. + + * generic/tclCmdAH.c (Tcl_FormatObjCmd): + * generic/tclScan.c (Tcl_ScanObjCmd): corrected handling of format + and scan on 64-bit machines. [Bug 219223, Patch #412696] (rmax) + + * unix/configure: regen'ed + * unix/tcl.m4: added --enable-64bit support for HP-11 with the + 64-bit kernel. + + * generic/tcl.h: removed forced #define USE_TCLALLOC 1 for + Windows. This means the native system allocator will be used by + default. This should be binary and source compatible with + extensions, as Tcl_Alloc is a properly stubbed function. + +2001-09-18 Don Porter + + * unix/configure: Regen. + * unix/tcl.m4 (SC_CONFIG_CFLAGS): On Linux, disable inlining when + one of the compat/*.c routines is to be linked in. [Patch 440891] + +2001-09-13 Jeff Hobbs + + * generic/tclUtf.c (Tcl_UtfPrev): corrected to return the proper + location when the middle of a UTF-8 byte was passed in. + [Tk Bug #450504] + +2001-09-13 Andreas Kupries + + * tests/ioCmd.test: Changed the computation of the result for + iocmd-8.1[123] so that the tests work for single- and + multi-process execution of the testsuite. Depending on the + choice of the user stdout is a tty or not and thus reports + different channel options. Fixes [460993] reported by Don + Porter. + +2001-09-12 Don Porter + + Backport several bug fixes from HEAD to core-8-3-1-branch: + + * tests/rename.test: + * tests/split.test: Corrected tests to better isolate tests in + one file from influencing tests in other files. [Bug 460591] + + * unix/tclLoadShl.c: Added #include of tclInt.h; access to Tcl + internals, notably TclpUnloadFile(), is required. Thanks to + Bob Techentin for report and patch. [Bug 459305] + + * generic/tclInitScript.h (initScript): + * win/tclWinInit.c (TCL_REGISTRY_KEY, TclpSetVariables): Removed + vestiges of Tcl's old initialization from registry variables. + [Bug 455645] + + * tests/unixInit.test (unixInit-3.2): Updated test to support + newer HP-UX releases that properly report euc-jp as the system + encoding for Japanese. Bug report and patch verification by Bob + Techentin. [Bug 453883] + + * compat/strtod.c (strtod): Fixed failure to handle expressions + like 3eq2 and failure to set errno on overflow. [Bug 440894] + +2001-09-10 Jeff Hobbs + + * generic/tclEvent.c (TclInExit): Corrected handling of tsd in + late stages of finalization. [Bug #419449] (darley) + + * tests/stack.test: + * generic/tclInterp.c (AliasObjCmd): Check the numLevels to ensure + that we aren't hitting some alias loop condition. [Bug #443184] + +2001-09-10 Andreas Kupries + + * generic/tclInt.decls: Added 'TclWinFlushDirtyChannels' to + the internal platform specific stub table. + +2001-09-06 Andreas Kupries + + * All the changes below serve to fix bug [219148] which reports a + 80x performance hit for file I/O on Win* systems. On my system + it was closer to a 120x hit. Problem report by Uwe Traum . + + The fix goes like this: The obstacle is 'FlushFileBuffers', + executed whenever Tcl writes data to the OS, as Tcl has to wait + for the disk to complete I/O, and disks are slow. We remove that + obstacle. This opens another problem, [file size] reports back + wrong numbers. So for [file size] we add the call back in. As + optimization we keep track of the channels which were written to + and flush only these. + + * win/tclWinFile.c (TclpObjStat): Added a call to + 'TclWinFlushDirtyChannels'. This ensures that [file size] and + related commands report the correct size of a file even if Tcl + has recently written to it. Unixoid OS's always report the + correct size even for files with pending data, but Win* + syssystem don't. They only report what is actually on disk. + + * win/tclWinInt.h: Added declaration of + 'TclWinFlushDirtyChannels', making it available to other parts + of the tcl core. + + * win/tclWinChan.c (TclWinFlushDirtyChannels): New, internal, + procedure. Goes through the list of open file channels and + forces the OS to flush its file buffers for all which were + written to since the last call of this function. This is an + expensive operation as Tcl has to wait for the OS to complete + actual writes to the disk. + + (FileInfo): Added dirty flag required by the procedure above. + + (FileOutputProc): Removed flushing of file buffers, setting the + dirty flag instead. This means that the previously incurred + delays do not happen anymore. + + (TclWinOpenFileChannel): Added initialization of 'dirty' flag. + +2001-09-06 Don Porter + + * doc/http.n: + * library/http/*.tcl: + * tools/tcl.wse.in: + * tools/tclmin.wse: + * unix/Makefile.in: + * win/{Mm}akefile.*: Updated http package to version 2.4, + reflecting the new features just added. + +2001-09-06 Jeff Hobbs + + * doc/http.n: noted -binary, charset and coding state keys. + * tests/http.test: + * library/http/pkgIndex.tcl: + * library/http/http.tcl (geturl): correctly get charset parameter + and convert text according to specified encoding (if known). + RFC iso8859-1 is used by default. Also recognize + Content-encoding to see if we should do binary translation. + Added a CYA -binary switch for the cases that were missed. [Bug + #219211 #219399] + + * tests/ioUtil.test: changed to make better use of constraints and + remove knownBug constraints that weren't valid. + +2001-09-01 David Gravereaux + + -=[ Tcl_Async* API merge from HEAD ]=- + + * generic/tclInt.decls: Removed TclpAsyncMark permanently and left + the hole not to upset the positions. + + * generic/tclDecls.h: + * generic/tclIntDecls.h: + * generic/tclIntPlatDecls.h: + * generic/tclPlatDecls.h: + * generic/tclStubInit.c: regen'd tables. + + * generic/tclAsync.c: Brought source to match -r1.6 on the HEAD + branch. + + * generic/tclEvent.c: + * generic/tclInt.h: Added prototype to and use of new + TclFinalizeAsync() found in tclAsync.c. + + * unix/tclUnixPort.h: + * mac/tclMacPort.h: removed #defines for TclpAsyncMark. + + * win/tclWinInit.c: Removed the TclpAsyncMark function and the + thread ID saving that was going on in TclpInitPlatform(). [the old + hack] + + * win/tclWinThread.c: TclpFinalizeCondition() and + TclpFinalizeMutex() are now properly returning the old + CriticalSection handle to the system. Tcl_CreateThread() is now + decrementing its handle reference, so the system will recover + resources when the thread closes (doh!). These changes are all + already up on the HEAD. + + * doc/Async.3: matches HEAD. + +2001-08-30 Jeff Hobbs + + * generic/tclIndexObj.c: fixed some casting problems that upset + Crays. [Bug #419528] (andreasen) + + * tests/httpd (httpdRespond): added response to timeout value in + query string. + +2001-08-30 Don Porter + + * generic/tcl.h: Silence warning from Sun compiler. [Bug 454374] + +2001-08-27 Jeff Hobbs + + * doc/Encoding.3: added note that tclPlatDecls.h must be included + for use of Tcl_WinTCharToUtf and Tcl_WinUtfToTChar. + + * doc/Tcl_Main.3: added docs for Tcl_SetMainLoop + + * generic/tclStubInit.c: + * generic/tclDecls.h: + * generic/tcl.decls: added Tcl_SetMainLoop proc that allows people + to set a main loop that will run for tclsh. + * generic/tcl.h: added Tcl_MainLoopProc typedef + * generic/tclMain.c (Tcl_SetMainLoop, StdinProc, Prompt): new + StdinProc and Prompt static procs and Tcl_SetMainLoop stubs proc. + The first two handle a fileevent based prompt (taken from + tkMain.c). Tcl_SetMainLoop enables the interactive setting of a + main loop procedure. This enables Tk to be a loadable package. + +2001-08-24 Don Porter + + * tests/unixInit.test (unixInit-2.9): Corrected expected result + to match Tcl's quirky construction of its init library path. + + * tests/ioUtil.test (ioUtil-3.*): Corrected errors in tests + revealed by fix of overagressive compiler. [Bug 451200] + + * doc/tclsh.1: Added note that the tclsh program is frequently + installed with the Tcl version numer as part of the name. + [Patch 402725] + + * generic/tclPkg.c: + * tests/pkg.test: [package forget] now forgets all of the + package arguments it receives, not stopping when a package is + not found. [Bug 415273] + + * doc/pkgMkindex.n: + * library/package.tcl: Corrected documentation and usage + message of [pkg_mkIndex]. + + * tests/unixInit.test (unixInit-2.8): Added extra constraint, + notInstalledInTmp, to stop this test from damaging installations + in /tmp; not much fun to have to reinstall the Tcl library every + time you run the test suite! + + * tests/unixInit.test (unixInit-2.9): + * unix/tclUnixInit.c (TclpInitLibraryPath): + * win/tclWinInit.c (TclpInitLibraryPath): Corrected buggy + construction of search path entries relative to executable. + Added test for bad construction. [Bug 438014] + + * tests/cmdMZ.test (cmdMZ-1.4): added notLinux constraint to test + to prevent failure message on Linux due to OS caching bug. + + * doc/library.n: + * library/init.tcl: + * tests/autoMkindex.t*: Modified [auto_import] to apply + pattern matching in the [namespace import] style. [Bug 420186] + ***POTENTIAL INCOMPATIBILITY*** for any callers of [auto_import] + from outside Tcl that expect the pattern matching to be like that + of [string match]. + + * tools/genStubs.tcl: Add a package require of Tcl 8 + at the beginning of the script so that the script + will print a descriptive error message when run + in an old Tcl 7 shell. + +2001-08-23 Andreas Kupries + + * win/tclWinPipe.c (BuildCommandLine): Fixed tcl Bug + [432499]. Part of the code used the non-absolute path to the + executable to determine quoting. This failed if the absolute + path contained spaces, but the application name itself not. This + bug caused no trouble on Win NT 5, but does for other variants + in the Win* family. Report and fix due to Ken Poole + . + +2001-08-23 Jeff Hobbs + + * unix/configure: + * unix/tcl.m4: added QNX-6 build support. [Bug #219410] (loverso) + +2001-08-20 Jeff Hobbs + + * library/http/http.tcl (geturl): added port number to Host: + header to comply with HTTP/1.1 spec (RFC 2068). [Bug #452217] + +2001-08-08 Don Porter + + * library/dde1.1/pkgIndex.tcl: + * library/reg1.0/pkgIndex.tcl: Package dependencies. [Patch 448931] + + * library/http/http.tcl: + * library/http/pkgIndex.tcl: Upgrade to http 2.3.2. + + * library/msgcat/msgcat.tcl: + * library/msgcat/pkgIndex.tcl: Upgrade to msgcat 1.1.1. + + * library/opt/optparse.tcl: + * library/opt/pkgIndex.tcl: Upgrade to opt 0.4.3. + + * library/tcltest/tcltest.tcl: + * library/tcltest/pkgIndex.tcl: Upgrade to tcltest 1.0.1. + +2001-08-07 Miguel Sofer + + * generic/tclExecute.c: Avoid panic when there are extra items in + the tcl stack [Bugs #406709 and 439843, Patch #414470] + * tests/foreach.test: test to exercise the patch + +2001-08-06 Jeff Hobbs + + * generic/tclCmdMZ.c (Tcl_RegexpObjCmd, Tcl_RegsubObjCmd): + reordered the retrieval of arguments to avoid shimmering bug when + the pattern and string referenced the same object. + + * unix/configure: regenerated + * unix/tcl.m4: added GNU (HURD) configuration target. (brinkmann) + [Patch: #442974] + +2001-08-03 Jeff Hobbs + + * win/configure: regenerated + * win/tcl.m4: fixed DLLSUFFIX definition to always be ${DBGX}.dll. + This is necessary for TEA compliant builds that build shared + against a static-built Tcl. + * win/Makefile.in ($(TCLSH)): added $(TCL_STUB_LIB_FILE) to build + target, otherwise it wouldn't get generated in a static build. + +2001-08-06 Andreas Kupries + + * generic/tclIOCmd.c (Tcl_GetsObjCmd): Applied patch from SF item + [442665] to fix the bug reported by it. The function can corrupt + a freed object if it is called with objc == 3. This is because + it retrieves resultPtr and does not increment its reference + count, but then calls Tcl_ObjSetVar2, which causes the retrieved + resultPtr object to be released. + +2001-07-18 Andreas Kupries + + * doc/bgerror.n: Fixed Tk! Bug #415757. + +2001-07-18 Andreas Kupries + + * generic/tclIO.c: Aftermath to [SF #427196]. Squash empty buffers + if they are smaller than the requested buffersize, to prevent + reusage of old buffers and to honor changes in the requested + buffersize made by the user. + +2001-07-17 Andreas Kupries + + * generic/tclIO.c (GetInput): Fixed [SF #427196]. Memory was + overwritten because a buffer was used after a change of the + requested buffersize together with that requested buffersize and + not its actual size, which was smaller. Note that the continous + reuse of the smaller buffer negatively impacts performance. The + system never allocates a buffer with the newly requested bigger + buffersize. + +2001-07-16 Jeff Hobbs + + * win/tclWinPipe.c (PipeClose2Proc): constrained the mutex lock to + just the TerminateThread call and waiting for termination. (jsmith) + +2001-07-02 Jeff Hobbs + + * tests/util.test: added util-4.6 + * generic/tclUtil.c (Tcl_ConcatObj): Corrected walking backwards + over utf-8 chars. [Bug #227512] + +2001-06-27 Jeff Hobbs + + * generic/tclUtf.c (Tcl_UtfBackslash): Corrected backslash + handling of multibyte utf-8 chars. [Bug #217987] + + * generic/tclCmdIL.c (InfoProcsCmd): fixed potential mem leak in + info procs that created objects without using them. + + * generic/tclCompCmds.c (TclCompileStringCmd): fixed mem leak when + string command failed to parse the subcommand. + +2001-05-22 Jeff Hobbs + + * generic/tclObj.c (TclAllocateFreeObjects): simplified + objSizePlusPadding to use sizeof(Tcl_Obj) (max) + +2001-05-04 Daniel Steffen + + ** Mac 8.3.3 binary release + + ** detailed change log for changes to mac code for 8.3.3 + ** (expands on log entries below marked 2001-04-04 Jeff Hobbs) + + * generic/tcl.h: MAC_TCL: addition of ConditionalMacros.h and use of + DLLIMPORT and DLLEXPORT like on other platforms. ( => no longer need + the .exp files and can remove use of #pragma export that never worked + well) + + * mac/tclMacShLib.exp: + * mac/tclMacOSA.exp: + * mac/tclMacMSLPrefix.h: removed files + + * mac/MW_TclBuildLibHeader.h: + * mac/MW_TclBuildLibHeader.pch: + * mac/MW_TclHeaderCommon.h: + * mac/MW_TclStaticHeader.h: + * mac/MW_TclStaticHeader.pch: new precompiled header files + + * mac/MW_TclAppleScriptHeader.pch: + * mac/MW_TclHeader.pch: + * mac/MW_TclTestHeader.pch: + * mac/tclMacCommonPch.h: revised precompiled header handling: now + include a common header file 'MW_TclHeaderCommon.h' from all .pch + files, the .pch files themselves now only setup #defines (e.g. + BUILD_tcl, STATIC_BUILD, TCL_DEBUG, TCL_THREADS) like in makefiles on + other platforms. + + * mac/tclMac.h: + * mac/tclMacPort.h: + * mac/tclMacInt.h: use of BUILD_tcl and TCL_STORAGE_CLASS like on other + platforms, standardize #include'd files to what's done on other + platforms, removed use of #pragma export. + + * mac/tcltkMacBuildSupport.sea.hqx: new archive of mac build support + files & suggested build environment directory hierarchy: + - 'Building MacTclTk' & 'CW Pro6 changes' readme's. + - projects for MoreFiles 1.5.1 static & shared libraries. + - project & sources for 'pseudoCarbonSupport', see below. + + * mac/tclMacProjects.sea.hqx: updated mac build project files: + - build support for CodeWarrior Pro6, UnivIntf 3.4 & shared runtime + libraries: the MSL libraries and MoreFiles are no longer compiled into + Tcl.shlb, all non-static binaries now use the Pro6 shared runtime + libraries and MoreFiles.shlb. These shlbs are merged into the standard + Wish and TclShell, but 3rd party applications linking with Tcl.shlb or + Tk.shlb need to setup access to them. (see the "(sh-ppc)" targets + for how to do this.) + - Merging the full MSL.shlb and the other shlbs into Wish & TclShell + makes them a bit larger than before, use unmerged binaries to avoid + copying the shared code with every application, e.g. when deploying + numerous Wish based droplets. + - Note that using CW Pro5 to compile extensions is in principle still + possible, but need to link with Pro6 runtime libraries. + - Tclapplescript now loads and runs on CFM68k. + - Highly experimental "pseudoCarbon" support for Tcl only on OS 8/9: + binaries in "Build:(Carbon):" link against CarbonLib instead of + InterfaceLib, however the actual code has not been carbonized! i.e. it + will not run on OSX and may not even run properly with CarbonLib. + This should in principle allow you to build & test OS9 CFM Carbon + binaries that need to link with Tcl.shlb. On OSX you can use the + native Tcl.framework, but you have to build a MachO binary as there + is no CFM glue lib for Tcl.framework. + the library pseudoCarbonSupport.shlb manually loads the symbols + from InterfaceLib that are not in CarbonLib but are needed by the + uncarbonized code in Tcl.shlb and TclShell. + + * generic/tclMain.c: MAC_TCL: workaround for broken/non-standard isatty + on MW Pro6, #include instead of defining isatty + + * mac/tclMacPort.h: MW Pro6 changes for MSL fcntl.h, stat.h & isatty + + * mac/tclMacAppInit.c: add EXTERN to InstallConsole to enable DLL + export via the TCL_STORAGE_CLASS mechanism. + + * mac/tclMacFCmd.c: fix for FSpDirectoryCopy API change + + * mac/tclMacLibrary.c: emit compile time error when + TCL_REGISTER_LIBRARY and USE_TCL_STUBS are both defined at the same + time in an extension, this use is not currently supported and will + result in a crash when dynamically loading the extension. + + * mac/tclMacApplication.r: + * mac/tclMacLibrary.r: + * mac/tclMacOSA.r: + * mac/tclMacResource.r: fixed obsolete copyrights/dates in version + strings; updated version strings to standard usage; added support for + '(Support Libraries)' subfolder for shared runtime libraries in + unmerged binaries; commented out demo setting of "Tcl Environment + Variables" + + * mac/tclMacChan.c: + * mac/tclMacSock.c: cast for *BlockMode + + * mac/tclMacUtil.c: + * mac/tclMacMath.h: removed obsolete hypot() definition + + * generic/tclIntPlatDecls.h: + * generic/tclInt.decls: + * generic/tclStubInit.c: + * mac/tclMacNotify.c: + * mac/tclMacOSA.c: + * mac/tclMacUtil.c: + * generic/tclThreadTest.c: renamed routines conflicting with standard + Apple or MoreFiles headers (at compile or link time): + GetGlobalMouse -> GetGlobalMouseTcl + FSpGetDirectoryID -> FSpGetDirectoryIDTcl + FSpOpenResFileCompat -> FSpOpenResFileCompatTcl + FSpCreateResFileCompat -> FSpCreateResFileCompatTcl + NewThread -> NewTestThread + the renamed MoreFiles *Tcl routines are just wrappers calling into the + MoreFiles DLL. + + * mac/tclMacCommonPch.h: + * mac/tclMacThrd.c: + * mac/tclMacPanic.c: removed OLDROUTINENAMES define, renamed obsolete + apple API names to modern equivalents; UH3.4 support: added #include + , updated New*Proc() calls to New*UPP(). + + * mac/tclMacUnix.c: added missing (Tcl_Obj ***) cast to + Tcl_ListObjGetElements call + + * mac/tclMacAlloc.c: modernized TclpSysAlloc() to use temporary + memory instead of system heap memory when available (MacOS + >= 7.5 and possibly earlier, use of system heap has been + discouraged for a long time and has many disadvantages, e.g. memory + isn't paged out, and errors can very easily bring the system down); + fixed crashing bug in TclpSysRealloc() and CleanUpExitProc() where + memory was being accessed after having been deallocated; fixed + memory leak in (de)allocation code (for every block ever allocated + with TclpSysAlloc, a Ptr was leaked), if temporary memory is + available, don't track allocated memory, instead use + RecoverHandle() to get Handle from Ptr, otherwise use doubly linked + list to correctly track memory and free all allocated memory; added + new option for ConfigureMemory: MEMORY_DONT_USE_TEMPMEM, disables + use of temporary memory even when it would be available, only + necessary when writing e.g. a driver (using tcl??); increased + fraction of application heap reserved for OS routines to 512K + +2001-04-06 Jeff Hobbs + + * unix/install-sh: added -S option + * unix/tcl.m4: added Rhapsody/Darwin target + * unix/tclLoadDyld.c (TclpLoadFile): + * unix/tclMtherr.c (matherr): added support for Mac OS X + +2001-04-05 Jeff Hobbs + + * generic/tclObj.c (TclAllocateFreeObjects): simplified + objSizePlusPadding to use sizeof(Tcl_Obj) (max) + + * win/README: + * win/README.binary: removed note about use of registry (hasn't + been used for loading since 8.0). + + * win/configure: + * win/tcl.m4: added -link50compat + + * mac/tclMacProjects.sea.hqx: fixed accidental swap with Tk + project files. + +2001-04-04 Jeff Hobbs + + ** Start changes for improved mac build (steffen) ** + + * mac/tclMacShLib.exp: + * mac/tclMacMSLPrefix.h: removed files + + * generic/tcl.h: addition of ConditionalMacros.h and use of + DLLIMPORT and DLLEXPORT. + + * generic/tclIntPlatDecls.h: + * generic/tclInt.decls: + * generic/tclMain.c: + * generic/tclStubInit.c: + * generic/tclThreadTest.c: NewThread -> NewTestThread + * mac/MW_TclAppleScriptHeader.pch: + * mac/MW_TclHeader.pch: + * mac/MW_TclTestHeader.pch: + * mac/tclMac.h: + * mac/tclMacAppInit.c: + * mac/tclMacApplication.r: + * mac/tclMacChan.c: cast for *BlockMode + * mac/tclMacCommonPch.h: + * mac/tclMacFCmd.c: + * mac/tclMacInt.h: + * mac/tclMacLibrary.c: + * mac/tclMacLibrary.r: + * mac/tclMacMath.h: + * mac/tclMacNotify.c: + * mac/tclMacOSA.c: + * mac/tclMacOSA.r: + * mac/tclMacPanic.c: + * mac/tclMacPort.h: + * mac/tclMacResource.r: + * mac/tclMacSock.c: cast for *BlockMode + * mac/tclMacThrd.c: + * mac/tclMacUnix.c: + * mac/tclMacUtil.c: changed mac declarations to use Tcl ending, + fixed copyrights, updated headers, fixed comments, updated + resource files. Mac builds are now meant to be build with + MetroWerks CW 6. + + * mac/MW_TclBuildLibHeader.h: + * mac/MW_TclBuildLibHeader.pch: + * mac/MW_TclHeaderCommon.h: + * mac/MW_TclStaticHeader.h: + * mac/MW_TclStaticHeader.pch: + * mac/tcltkMacBuildSupport.sea.hqx: new files + + * mac/tclMacProjects.sea.hqx: new mac build project files. + + ** End changes for improved mac build (steffen) ** + + * unix/configure: + * unix/tcl.m4: extended test of termios vs. termio vs. sgtty to + better detect result on Linux and when certain configure + redirections are being used. (max) [Patch #402923; Bug #227412, + #219194] + +2001-04-03 Jeff Hobbs + + * generic/tclListObj.c (Tcl_SetListObj): set objPtr->length = 0 in + empty object case to maintain sanctity of Tcl_Obj bytes/length + pairing. (porter) [Patch #405998] + + * README: + * mac/README: + * win/README: + * win/README.binary: + * unix/README: updated patchlevel information to 8.3.3 and + updated links and notes. + + * generic/tcl.h: + * tools/tcl.wse.in: + * win/configure.in (TCL_PATCH_LEVEL): + * win/configure: + * unix/configure: + * unix/configure.in (TCL_PATCH_LEVEL): + * unix/tcl.spec: updated patchlevel information to 8.3.3 + + *************************************************************** + ** START OF ASYNC BACKPORT LOG (8.4aCVS 2001-04-03 -> 8.3.3) ** + *************************************************************** + + * doc/CrtChannel.3: + * doc/CrtSlave.3: + * doc/DetachPids.3: + * doc/Eval.3: + * doc/ObjectType.3: + * doc/StrMatch.3: + * doc/after.n: + * doc/append.n: + * doc/bgerror.n: + * doc/binary.n: + * doc/break.n: + * doc/case.n: + * doc/cd.n: + * doc/close.n: + * doc/concat.n: + * doc/continue.n: + * doc/dde.n: + * doc/encoding.n: + * doc/eof.n: + * doc/error.n: + * doc/eval.n: + * doc/exec.n: + * doc/exit.n: + * doc/fblocked.n: + * doc/fileevent.n: + * doc/filename.n: + * doc/flush.n: + * doc/for.n: + * doc/foreach.n: + * doc/format.n: + * doc/gets.n: + * doc/glob.n: + * doc/global.n: + * doc/http.n: + * doc/if.n: + * doc/incr.n: + * doc/join.n: + * doc/lappend.n: + * doc/library.n: + * doc/lindex.n: + * doc/linsert.n: + * doc/list.n: + * doc/llength.n: + * doc/load.n: + * doc/lrange.n: + * doc/lreplace.n: + * doc/lsort.n: + * doc/man.macros: + * doc/memory.n: + * doc/open.n: + * doc/package.n: + * doc/packagens.n: + * doc/pid.n: + * doc/pkgMkIndex.n: + * doc/proc.n: + * doc/puts.n: + * doc/pwd.n: + * doc/read.n: + * doc/regexp.n: + * doc/regsub.n: + * doc/rename.n: + * doc/resource.n: + * doc/return.n: + * doc/scan.n: + * doc/seek.n: + * doc/set.n: + * doc/split.n: + * doc/string.n: + * doc/subst.n: + * doc/switch.n: + * doc/tclvars.n: + * doc/tell.n: + * doc/time.n: + * doc/unknown.n: + * doc/update.n: + * doc/uplevel.n: + * doc/upvar.n: + * doc/variable.n: + * doc/vwait.n: + * doc/while.n: doc clarifications and cleanup from 8.4aCVS docs + +2001-04-02 Jeff Hobbs + + * win/configure: + * win/tcl.m4 (SHLIB_LD): added -incremental:no. [Bug #219381] + +2001-03-30 Jeff Hobbs + + * generic/tclCkalloc.c (TclFinalizeMemorySubsystem): set curTagPtr + to NULL to allow for reuse. + * generic/tclEvent.c (Tcl_Finalize): moved the tsdPtr + initialization inside the subsystemsInitialized check to prevent + it potentially getting called twice during finalization. (wu) + [Patch #403532, Bug #219391] + + * win/tclWinSock.c (SocketEventProc): Fixed race condition in + readability of socket on Windows. + [Patch #410674, Bug #219205 #219333] + + * win/tcl.m4: added imm32.lib to LIBS_GUI for Tk IME support. + + * win/Makefile.in (install-doc): improved install-* targets to use + their base build dependency. + +2001-03-29 Mo DeJong + + * tests/interp.test: Print out warning when + testinterpdelete command is not defined. + Add tests that checks to make sure a + child interp inherits the parent's cwd. + +2001-03-29 Jeff Hobbs + + * unix/tclUnixPipe.c (TclpCreateTempFile): prevent potential race + condition and security leak in tmp filename creation. + (max) [Patch #402924] + + * unix/configure: + * unix/tcl.m4: corrected IRIX-5.x config to not use -n32. + (english) [Patch #403626] + + * unix/tclUnixThrd.c (Tcl_ConditionWait): fixed handling of + timeout for threads (corrects excessive CPU usage issue for Tk on + Unix in threaded Tcl environment). (ruppert) [Bug #411603] + +2001-03-26 Donal K. Fellows + + * win/tclWinInt.h (tclWinTCharEncoding): Removed as now a static + variable in win/tclWin32Dll.c instead. + +2001-03-23 Jeff Hobbs + + * generic/tclVar.c (Tcl_ArrayObjCmd): Corrected retrieval of + resultPtr to prevent possible corruption. + + * generic/tclNamesp.c (Tcl_Import): Correctly freed a DString. + (lavana) [Patch #403755] + +2001-03-14 Don Porter + * library/package.tcl (pkg_mkIndex): Added patch from Vince + Darley to make [pkg_mkIndex -verbose] even more verbose. + [Bug 219349, Patch 403529] + +2001-03-13 Donal K. Fellows + + * generic/tclCmdMZ.c (Tcl_StringObjCmd): A missing + {return TCL_OK;} was causing memory corruption. [Bug #408002] + + * generic/tclExecute.c (TclDeleteExecEnv, GrowEvaluationStack, + TclExecuteByteCode): Added some casts to ClientData that are + apparently needed on some architectures. + +2001-03-02 Donal K. Fellows + + * generic/tclExecute.c (TclExecuteByteCode): Fixed bug that could + pass pointers to freed memory to command implementations, which + most obviously caused some weird behaviour with [info level], but + could have caused problems with user code and command traces too. + [Bug 404865, Patch 405436] + +2001-02-15 Donal K. Fellows + + * generic/tclCmdMZ.c (Tcl_SplitObjCmd): Improved efficiency of + splitting strings into individual characters by adding hash so + that only one Tcl_Obj per character is created. Improves + performance of splitting of short strings and makes a huge + difference to splitting of long strings, such as is done in the + mime package in tcllib. [Bug #131523] + +2001-01-30 Don Porter + * generic/tclIO.c (CopyData): Moved code that updates the count + of how many bytes are left to copy. Corrects bug that when + writing occurs in the background, the copy loop could be + escaped without updating the count, causing CopyData() to try + to copy more bytes than the toRead value originally passed to + TclCopyChannel(), leading to hangs and misreporting of number + of bytes copied. [Bug 118203, Patch 103432] + +2001-01-04 Don Porter + * tests/unixInit.test: + * unix/tclUnixInit.c (TclpInitLibraryPath): + * win/tclWinInit.c (TclpInitLibraryPath): Several entries in + the library path ($tcl_libPath) are determined relative to the + absolute path of the executable. When the executable is + installed in or near the root directory of the file system, + relative pathnames were being incorrectly generated, and in + the worst case, memory access violations were crashing the program. + [Bug 119416, Patch 102972] + +2000-12-14 Don Porter + + * generic/tclExecute.c: + * tests/expr-old.test: Re-wrote Tcl's [expr rand()] and + [expr srand($seed)] implementations, fixing a range error + on some 64-bit platforms. Added tests that detect the bug. + The rewrite changes the seed -> sequence map on 64-bit + platforms, only for seed >= 2^31, a slight incompatibility. + [Bug 121072, Patch 102781] + +2000-12-10 Don Porter + + * library/init.tcl: + * library/msgcat/msgcat.tcl: + * library/msgcat/pkgIndex.tcl: + * library/opt/optparse.tcl: + * library/opt/pkgIndex.tcl: Where [uplevel] is used in a proc + to evaluate a Tcl built-in command in the caller's context, + the built-in commands are now fully namespace-qualified. This + prevents problems when the caller context is in a namespace where + the built-in command name has been used by a command in the + namespace. (For example, [::ns::set] might be called instead + of the intended [::set]). [Bug #119422, Patch #102545] + +2000-12-09 jeff hobbs + + * docs/scan.n: + * tests/scan.test: + * generic/tclScan.c (Tcl_ScanObjCmd): changed %o and %x to use + strtoul instead of strtol to correctly preserve scan<>format + conversion of large integers. [Patch #102663, Bug #124600] + + * generic/tclExecute.c (TclExecuteByteCode): Commited patch fixing + handling of {!} in expressions. [Patch #102702] + +2000-12-08 jeff hobbs + + * library/init.tcl: Added support for PATHEXT variable in + auto_execok, recognizing the proper set of executable extensions + on Windows. [Patch #102719] + +2000-12-08 Andreas Kupries + + * generic/tclEncoding.c (LoadTableEncoding): Changed dangerous + code to something less critical. This fixes bug 119417, part A + without affecting the speed when loading encodings. + +2000-11-24 Donal K. Fellows + + * generic/tclExecute.c (TclExecuteByteCode): Logical negation "!" + can now handle string booleans, provided those values are placed + in variables. + + * tests/expr.test (expr-13.17): Check that [expr {!$var}] can + negate the string-versions of booleans "yes", "false", etc. + + * library/tcltest/tcltest.tcl (getMatchingFiles, + getMatchingDirectories): + * tools/man2html.tcl (doDir): + * tools/man2help.tcl (doDir): + * library/package.tcl (tclPkgUnknown,tclMacPkgSearch): + * library/safe.tcl (AddSubDirs): [glob] uses -directory instead of + unsafe [file join] to fix Bug #123313 + + * generic/tclIndexObj.c: + * generic/tclTestObj.c (TestindexobjCmd): Changed internal + representation of index objects to fix Bug #119082; fix + shouldn't be visible to outside world... + + * generic/tclTest.c (TestGetIndexFromObjStructObjCmd): + * tests/indexObj.test: (indexObj-6.*) Added to test for presence + of Bug #119082. + +2000-11-23 Donal K. Fellows + + * generic/tclCmdIL.c (Tcl_LsortObjCmd): Fixed memory leak from Bug + #119398 + + * library/init.tcl (unknown): Added specific level parameters to + all uplevel invokations to boost performance; didn't dare touch + the "namespace inscope" stuff though, since it looks sensitive + to me! Should fix Bug #123217, though testing is tricky... + +2000-11-16 Andreas Kupries + + * win/tclWinPort.h (line 69): Changed reference to winsock2.h into + winsock.h. This was a leftover from a foray into using winsock + version 2 (History lesson from Scott Redman and Jeff + Hobbs). This code was no problem when compiling Tcl itself, but + could trip extensions. Fixes bug 122568. + +2000-11-02 David Gravereaux + + * generic/tclEvent.c: tclLibraryPath Tcl_Obj didn't have a way + to share its data among threads. This caused Tcl_Init() to + always fail in threads. Added a way to pass the data around + with a global char*. [BUG: 5301] + +2000-11-02 Jeff Hobbs + + * unix/configure: + * unix/dltest/configure: + * win/configure: + * tools/configure: checked in configure scripts so people doing + CVS checkouts aren't required to have autoconf. Changes to + configure.in in the future will require the corresponding + configure script to also be re-autoconf'ed and checked in. + + * win/makefile.vc: + * win/tcl.m4: makefile fixes for Win64 support + + * generic/tclIndexObj.c (Tcl_GetIndexFromObjStruct): minor cast + changes. + +2000-11-01 Jeff Hobbs + + * unix/tcl.m4: removed use of -lbsd and -ldl for AIX-5. + + * tests/subst.test: added tests for non-zero return code handling + by subst. + * generic/tclParse.c (Tcl_EvalEx): corrected handling of non-zero, + non-error return code cases for subst. [BUG: 119829] + + * generic/tclVar.c (TclVarTraceExists): Corrected excessive mem + use when info exists was called on a non-existent array element. + [BUG: 119213, 119336] + +2000-10-30 David Gravereaux + + * win/configure.in: + * win/Makefile.in: + * win/makefile.vc: + * win/tcl.rc: + * win/tclsh.rc: Added logic to derive filenames better in the resource + scripts based on compile options. + +2000-10-30 Jeff Hobbs + + * unix/tclUnixInit.c: added default encoding map from + "ja_JP.eucJP" to "euc-jp". (takahashi) + + * tests/clock.test: corrected clock-2.* test numbering + + * unix/configure.in (SC_TCL_LINK_LIBS): removed code that was + commented out (it had been moved to tcl.m4's SC_TCL_LINK_LIBS + already). + + * unix/tcl.m4: consolidated gettimeofday check for AIX. + +2000-10-27 Jeff Hobbs + + * unix/configure.in: + * unix/tcl.m4: added support for AIX-5. + + * generic/tclIO.c (Tcl_NotifyChannel): removed #ifdef around code + for old channel structures, placed preserve/release around statePtr + * generic/tclIO.c (CloseChannel): the statePtr for a channel was + not being freed when the last channel in a stack was freed, + causing a mem leak. + + * unix/tclUnixChan.c: updated channel types to strict + TCL_CHANNEL_VERSION_2 style to avoid compiler warnings. They work + either way, but this avoids compiler warnings (that worries people). + +2000-10-26 David Gravereaux + + * win/tclWinFile.c (TclpMatchFilesTypes): NULL was being set to + "attr" which was a DWORD. Changed NULL to zero because a 'void *' + can't be set to a DWORD to avoid the compiler warning. + +2000-10-20 Jeff Hobbs + + * win/tclWinFile.c (TclpMatchFilesTypes): made the stat call only + occur when necessary (for 'glob' command). Significantly speeds + up glob command from 8.3. [BUG: 6216] + +2000-10-06 David Gravereaux + + * win/tclWinChan.c: moved Win2K bug case test with GetStdHandle() + from TclpGetDefaultStdChannel into Tcl_MakeFileChannel to enable + a more general method in detecting invalid OS handles rather than + just a specific known case. [BUG: 5971] + +2000-10-06 Jeff Hobbs + + * tests/cmdAH.test: extra tests for 'file channels' that include + multiple interpreter tests and channel sharing + * generic/tclIO.c (Tcl_GetChannelNamesEx): corrected function (and + consequently 'file channels') to return channels that are actually + registered for this specific interp, rather than this thread. + +2000-09-29 Jeff Hobbs + + * win/tclWinSerial.c (SerialGetOptionProc): corrected reporting of + space parity on Windows (Eason) [Bug 6057]. + + * win/Makefile.in: commented use of TESTFLAGS + * unix/Makefile.in: added TESTFLAGS to test target to + conform with Windows makefile and TEA style. + + * tests/stack.test: prevented possible crash on systems with low + default stacksize (Tru64, AIX) in infinite recursion test. A + solution to check remaining stack space in the core is best, but + hard to do in a cross-platform manner. + + * generic/tclIOGT.c (FLUSH_DELAY): renamed DELAY define to + FLUSH_DELAY to avoid defn conflict using Tru64's cc. + +2000-09-28 Jeff Hobbs + + * tools/tcl.wse.in: added tclPlatDecls.h and tkPlatDecls.h to the + Windows .exe install. + + * tests/fCmd.test (fCmd-6.20): corrected test to remove + c:/tcl8975@ after creating it. + + * tests/fileName.test: cleaned up the testing of glob patterns for + c:/globTest (Windows) to directly create/remove directory. +2000-09-27 Jeff Hobbs + + * generic/tclIO.c (StopCopy): fixed a bug introduced by a partial + fix in 8.3.2 that didn't set nonBlocking correctly when resetting + the flags for the write side. [Bug: 6261] + + *************************************************************** + ** END OF ASYNC BACKPORT LOG (8.4aCVS 2001-04-03 -> 8.3.3) ** + *************************************************************** + +2000-08-08 Jeff Hobbs + + 8.3.2 RELEASE finalized + + * changes: updated for release notes version of ChangeLog + + * library/msgcat1.0/pkgIndex.tcl: + * library/msgcat1.0/msgcat.tcl: bumped msgcat version to 1.1. + +2000-08-07 Jeff Hobbs + + * doc/ChnlStack.3: + * doc/CrtChannel.3: updated the docs to be aware of the + TCL_CHANNEL_VERSION_2 style of Tcl channels. + + * generic/tclIO.c (Tcl_CreateChannel): added assertion to verify + that the new channel versioning will be binary compatible with + older channel drivers. + + * BACKPORTED FROM 8.4 (HEAD) BRANCH: + + * doc/memory.n: Man page for Tcl "memory" command, which is + created when TCL_MEM_DEBUG is defined at compile time. + + * doc/TCL_MEM_DEBUG.3: Man page with overall information about + TCL_MEM_DEBUG usage. + + * doc/DumpActiveMemory.3: Man page for Tcl_DumpActiveMemory, + Tcl_InitMemory, and Tcl_ValidateAllMemory [Bug: 1816, 1835]. + + * doc/Init.3: Man page for Tcl_Init [Bug: 1820]. + + * unix/Makefile.in: add tclsh.ico and tcl.spec to dist target + + * unix/mkLinks: Regen'd with new mkLinks.tcl. + * unix/mkLinks.tcl: Fixed indentation, made link setup more + intelligent (only do one existance test per man page, instead of + one per function). + + * doc/AddErrInfo.3: + * doc/ChnlStack.3: + * doc/Exit.3: + * doc/GetIndex.3: + * doc/Notifier.3: + * doc/Object.3: + * doc/RegExp.3: + * doc/SetResult.3: + * doc/SplitList.3: + * doc/Thread.3: Added missing entries to NAME section. + + * doc/AddErrInfo.3: + * doc/CrtObjCmd.3: + * doc/RecEvalObj.3: Changed Tcl_EvalObj to Tcl_EvalObjEx + + * doc/library.n: Added entries for auto_qualify and auto_import + [Bug: 1271]. + * doc/library.n: Fixed .SH NAME macro to include each function + documented on the page, so that mkLinks will know about the + functions listed there, and so that the Windows help file index + will get set up correctly [Bug: 1898, 5273]. + + * doc/expr.n: Added documentation for each of the math library + functions that expr supports [Bug: 1054]. + + * doc/regsub.n: correct regsub docs [Bug: 5346] + + * doc/scan.n: minor doc fixes [Bug: 5396] + + * doc/RegExp.3: Replaced instances of "Tcl_GetRegExpInfo" with + "Tcl_RegExpGetInfo", the correct name of the function [Bug: 5901]. + + * doc/package.n: Corrected information about [package forget] + arguments [Bug: 5418]. + + * generic/tclCkalloc.c: Fixed some function headers. + + * tests/clock.test: Added test for "2 days 2 hours ago" style + specifications. + + * generic/tclDate.c: Regenerated from tclGetDate.y. + + * generic/tclGetDate.y: Tweaked grammar to properly handle the + "ago" keyword when it follows multiple relative unit specifiers, + as in "2 days 2 hours ago". [Bug: 5497]. + + * generic/tclClock.c (FormatClock): correct code to handle locale + specific return values from strftime, if any. [Bug: 3345] + + * unix/tclUnixInit.c (TclpSetInitialEncodings): attempt to + correct setlocale calls for XIM support and locale issues. + [BUG: 5422 3345 4236 2522 2521] + + * library/init.tcl (auto_import): added check to see if a valid + pattern was coming in, to avoid simple error cases [Bug: 3326] + + * library/history.tcl: Corrected an off-by-one error in HistIndex, + which was causing [history redo] to start its search at the wrong + event index. [Bug: 1269]. + + * generic/tclPosixStr.c (Tcl_SignalMsg): clarified #defines for + Linux on Sparc to compile correctly. [Bug: 5364] + + * generic/tclEnv.c: cast cleanup [Bug: 5624] + * win/tclWinFCmd.c: cast cleanup [Bug: 5627] + + * generic/tclIndexObj.c (Tcl_GetIndexFromObjStruct): Corrected + caching of the index ptr to account for offsets != sizeof(char *). + [Bug: 5153] + + * tests/opt.test: + * library/opt0.4/optparse.tcl: Applied patch from [Bug: 5922], which + corrected an incorrect use of [string match]. + + * tests/stringObj.test: Tweaked tests to avoid hardcoded + high-ASCII characters (which will fail in multibyte locales); + instead used \uXXXX syntax. [Bug: 3842]. + +2000-08-05 Jeff Hobbs + + * generic/tclIOGT.c (TclChannelTransform): fixed segfault that + would occur when transforming a channel with a proc that did not + yet exist. (Kupries) + + * generic/tclTest.c (TestChannelCmd): added some lint init'ing of + statePtr and chan vars. + +2000-07-28 Mo DeJong + + * win/Makefile.in: + * win/configure.in: + * win/tcl.m4: + * win/tclConfig.sh.in: Back port of gcc for windows + build system from 8.4. + +2000-07-26 Jeff Hobbs + + * merged core-8-3-1-io-rewrite back into core-8-3-1-branch. + The core-8-3-1-io-rewrite branch should now be considered defunct. + + * generic/tclStubInit.c: + * generic/tclDecls.h: + * generic/tcl.decls: + * generic/tcl.h: + * generic/tclIO.c: moved the Tcl_Channel* macros from tcl.h to + tclIO.c and made them proper stubbed functions. These are: + Tcl_ChannelName, Tcl_ChannelVersion, Tcl_ChannelBlockModeProc, + Tcl_ChannelCloseProc, Tcl_ChannelClose2Proc, Tcl_ChannelInputProc, + Tcl_ChannelOutputProc, Tcl_ChannelSeekProc, Tcl_ChannelSetOptionProc, + Tcl_ChannelGetOptionProc, Tcl_ChannelWatchProc, + Tcl_ChannelGetHandleProc, Tcl_ChannelFlushProc, + and Tcl_ChannelHandlerProc. These should be used to access the + Tcl_ChannelType structure instead of direct pointer dereferencing. + + * unix/Makefile.in: undid 07-25 Makefile.in changes because we + don't really want to force all private makefiles on everyone. + This needs to be addressed again in the future. Best possible + solution is to create a tcl/ subdir in the installing include dir + (as is done already with the lib dir). + + * tests/iogt.test: added RCS string, marked tests 2.* to be + unixOnly due to underlying system differences. + + * tests/all.tcl: corrected additional sets by Kupries for testing. + +2000-07-25 Brent Welch + + * unix/Makefile.in: Need to install all the Tcl headers because + Itcl depends on internal headers. + +2000-07-25 Andreas Kupries + + * tests/iogt.test: (line 866f) New tests iogt-6.[01], highlighting + buffering trouble when stacking and unstacking transformations. + iogt-6.0 is solved, see the changes below. iogt-6.1 remains, for + now, due to the perceived complexity of solutions. + + * generic/tclIO.h: (line 139f) struct Channel, added a buffer + queue, to hold data pushed back when stacking a transformation. + + * generic/tclIO.c: + (line 91f, line 7434f) New internal function 'CopyBuffer'. + Derived from 'CopyAndTranslateBuffer', with translation + removed. + (line 1025f, line 1212f): Initialization of new queue. + (line 1164f, Tcl_StackChannel): Pushback of input queue. + (line 1293f, Tcl_UnstackChannel): Discard input and pushback. + (line 3748f, Tcl_ReadRaw): Modified to use data in the push back + area before going to the driver. Uses 'CopyBuffer', s.a. + (line 4702f, GetInput): Modified to use data in the push back + area before going to the driver. + (line 4867f, Tcl_Seek): Modified to take pushback of the topmost + channel in a stack into account. + (line 5620f, Tcl_InputBuffered): See above. Added + 'Tcl_ChannelBuffered'. Analogue to 'Tcl_InputBuffered' but for + the buffer area in the channel. + + * generic/tcl.decls: New public API 'Tcl_ChannelBuffered'. S.a. + +2000-07-19 Jeff Hobbs + + * tests/socket.test: removed doTestsWithRemoteServer constraint + from socket-12.*. It requires 'exec', not a remote server. + Cleaned up some coding errors. + +2000-07-18 Brent Welch + + * win/Makefile.in: Added rules for static tcldde and tclreg libraries. + +2000-07-17 Jeff Hobbs + + * README: + * win/README: + * win/README.binary: + * win/configure.in: + * unix/configure.in: + * unix/tcl.spec: + * tools/tcl.wse.in: + * generic/tcl.h (TCL_RELEASE_SERIAL): updated to patchlevel 8.3.2 + + * unix/Makefile.in: + * win/Makefile.in: + * win/makefile.vc: added tclIOGT.c to objects list to compile. + + * generic/tclStubInit.c: + * generic/tclIntDecls.h: + * generic/tclInt.decls: commented out internal decls for + TclTestChannelCmd and TclTestChannelEventCmd as they were moved to + tclTest.c. Added new decls for TclChannelEventScriptInvoker and + TclChannelTransform. + + * generic/tclIO.h: new file that contains the main internal + structures of Tcl_Channel code to allow for multiple files to + access them. + * generic/tclTest.c: + * generic/tclIO.c: broke into 3 files - tclIO.c core code, tclIO.h + header code, and tclIOGT.c - the giot test code from Kupries. The + channel test code also moved to tclTest.c. + * generic/tclIO.c (CloseChannel): stopped masking out of the + TCL_READABLE|TCL_WRITABLE bits from the state flags in + CloseChannel, instead adding extra intelligence to + CheckChannelErrors with a new CHANNEL_RAW_MODE bit for special + behavior when called from Raw channel APIs. + +2000-07-13 Jeff Hobbs + + * generic/tclIO.c (StackSetBlockMode): moved set of chanPtr + outside of blockModeProc check to avoid infinite loop when + blockModeProc was NULL (Kupries). updated TransformSeekProc to + not call Tcl_Seek directly (Kupries). + + * win/tclWinChan.c: updated fileChannelType to v2 channel struct + * win/tclWinConsole.c: updated consoleChannelType to v2 channel struct + * win/tclWinPipe.c: updated pipeChannelType to v2 channel struct + * win/tclWinSerial.c: updated serialChannelType to v2 channel struct + * win/tclWinSock.c: updated tcpChannelType to v2 channel struct + +2000-07-11 Brent Welch + + * win/tclConfig.sh.in: Cleaned up unix-specific autoconf variables. + +2000-07-11 Jeff Hobbs + + * tests/iogt.test: made tests [345].0 not run by default as they + were failing in the new design, but I'm not convinced that the + returned result isn't correct. + + * generic/tclDecls.h: + * generic/tclStubInit.c: + * generic/tcl.decls: added Tcl_GetTopChannel C API that returns + the current top channel of a channel stack. Tcl_GetChannel was + changed earlier to return the bottommost channel of a stack + because that is the one that is guaranteed to stay around the + longest, and this was needed to compensate for certain + operations that want to look at the state of the main channel. + Most channel APIs already compensate for grabbing the top, so it + shouldn't be needed often. + + * generic/tclIO.c (Tcl_StackChannel, Tcl_UnstackChannel): Added + flushing of buffers (Kupries), removed use of DownChannel macro, + added Tcl_GetTopChannel public API to get to the top channel of + the channel stack (necessary for TLS). Rewrote Tcl_NotifyChannel + for new channel design (Kupries). Did some code cleanup in the + transform code. tclIO.c must still be broken into bits (separate + out test code and giot code, create tclIO.h). + +2000-07-10 Andreas Kupries + + * tests/iogt.test: Reverted some earlier changes as a fix by Jeff + revived the original and correct behaviour. IOW, the tests showed + a genuine error and I didn't see it :(. + + * generic/tclIO.c (Tcl_Read|Write_Raw): Changed to directly use + the drivers and not DoRead|DoWrite. The latter use the buffering + system, encoding and eol-translation and this wreaks havoc with + the data going through the transformations. Both procedures use + CheckForchannelErrors and let it believe that there is no + background copy in progress or else stacked channels could not + be used for that. + + * generic/tclIO.c (TclCopyChannel, CopyData): Moved access to the + topmost channel from the first to the second procedure to make + the decision about that at the last possible time (Callbacks can + change the stacking). + + test suite: failures of iogt-[345].0 + +2000-07-06 Jeff Hobbs + + * tests/iogt.test: new tests for stacked channel stuff based off + new 'testchannel transform|unstack' code (Kupries IOGT extension). + * generic/tcl.decls: + * generic/tcl.h: + * generic/tclDecls.h: + * generic/tclStubsInit.c: + * generic/tclIO.c: complete rewrite of Tcl Channel code for + stacked channels. Channels are now designed to work in a more + stacked fashion with a shared ChannelState data structure. + +2000-06-02 Jeff Hobbs + + * generic/tclIO.c (CloseChannel): removed the &ing out of + (TCL_READABLE|TCL_WRITABLE) from the flags, as CloseChannel does + this on the next pass through for the top channel, and it appeared + to be causing hangs by not allowing the final flush. + +2000-06-01 Jeff Hobbs + + * generic/tclIO.c (CloseChannel): Rewrote CloseChannel code to + unstack a channel during the close process. Fixed a refcount bug + in Tcl_UnstackChannel. [Bug: 5623] + (CloseChannel): further extended CloseChannel in the stacked case + to effect certain operations on the next channel that would have + been done in Tcl_Close. Also added CHANNEL_CLOSED and removed + (TCL_READABLE|TCL_WRITABLE) bits from chanPtr->flags. Changed + final reset of the WatchProc to check the chanDownPtr's (next) + interestMask. + +2000-05-29 Sandeep Tamhankar + + * tests/http.test + * doc/http.n + * library/http2.3/http.tcl: Fixed bug 5741, where unsuccessful + geturl calls sometimes leaked memory and resources (sockets). + Also, switched around some of the logic so that http::wait never + throws an exception. This is because in an asynchronous geturl, + the command callback will probably end up doing all the error + handling anyway, and in an asynchronous situation, the user + expects to check the state when the transaction completes, as + opposed to being thrown an exception. For the http package, this + menas the user can check http::status for "error" and http::error + for the error message after doing the http::wait. + +2000-04-26 Jeff Hobbs + + 8.3.1 RELEASE + + * README: + * mac/README: + * tools/tcl.wse.in: + * unix/README: + * unix/tcl.spec: + * win/README: + * win/README.binary: Updating URLs to reference dev.scriptics.com + +2000-04-25 Jeff Hobbs + + * unix/Makefile.in: + * win/Makefile.in: + * win/makefile.vc: updated for http change and some cleanup + * library/http2.[13]: moved dir http2.1 to http2.3 to match version + + * doc/Utf.3: clarified docs for Tcl_(UniChar|Utf)AtIndex + + * unix/tclUnixThrd.c: removed {}s around PTHREAD_MUTEX_INITIALIZER + [Bug: 5254] + + * unix/tclLoadDyld.c (TclpLoadFile): removed use of interp->result + +2000-04-25 Eric Melski + + * unix/mkLinks: + * doc/AddErrInfo.3: Added information about Tcl_LogCommandInfo + [Bug: 1818]. + +2000-04-24 Eric Melski + + * unix/mkLinks: + * doc/OpenFileChnl.3: Added man entry for Tcl_Ungets [Bug: 1834]. + + * unix/mkLinks: + * doc/SourceRCFile.3: Man page for Tcl_SourceRCFile [Bug: 1833]. + + * unix/mkLinks: + * doc/ParseCmd.3: Added documentation for Tcl_ParseVar [Bug: 1828]. + +2000-04-24 Jeff Hobbs + + * unix/tclUnixNotfy.c (Tcl_FinalizeNotifier, NotifierThreadProc): + added write of 'q' into triggerPipe for notifier in threaded case, + so that Tcl doesn't hang when children are still running [Bug: 4139] + + * unix/tclUnixThrd.c (Tcl_MutexLock): minor comment fixes. + +2000-04-23 Jim Ingham + + These changes make some error handling marginally better for Mac + sockets. It is still somewhat flakey, however. + + * mac/tclMacSock.c (TcpClose): Add timeouts to the close - these + don't seem to be honored, however. + Use a separate PB for the release, since an async connect socket + will still be using the original buffer. + Make sure TCPRelease returns noErr before freeing the recvBuff. + If the call returns an error, then the buffer is not right. + * mac/tclMacSock.c (CreateSocket): Add timeouts to the async + create. These don't seem to trigger, however. Sigh... + * mac/tclMacSock.c (WaitForSocketEvent): If an TCP_ASYNC_CONNECT + socket errors out, then return EWOULDBLOCK & error out. + * mac/tclMacSock.c (NotifyRoutine): Added a NotifyRoutine for + experimenting with MacTCP. + +2000-04-22 Jim Ingham + + * library/package.tcl (tclPkgUnknown): Fixed a typo in the Mac package + search part of tclPkgUnknown. + +2000-04-21 Sandeep Tamhankar + + * library/http2.1/http.tcl: Fixed a newly introduced bug where if + there's a -command callback and something goes wrong, geturl threw + an exception, called the callback, and unset the token. I changed + it so that it will not call the callback when throwing an + exception (so the caller only finds out about a given error from + one place). Also, fixed http::ncode so that it actually gives you + back the http return code (i.e. 200, 404, etc.) instead of the + first digit of the version of HTTP being used (i.e. 1). + +2000-04-21 Brent Welch + + * library/http2.1/http.tcl: More thrashing with the "server closes + without reading post data" scenario. Reverted to the previous + filevent configuratiuon, which seems to work better with small + amounts of post data. + +2000-04-20 Jeff Hobbs + + * generic/tclAlloc.c: wrapped caddr_t define to not be done on Unix + * unix/tclUnixPort.h: added Tclp*Alloc defines to allow the use of + USE_TCLALLOC on Unix. [Bug: 4731] + +2000-04-19 Jeff Hobbs + + * library/dde1.1/pkgIndex.tcl: + * library/reg1.0/pkgIndex.tcl: + * win/tclWinChan.c: + * win/tclWinThrd.c: converted CRLF to LF the */tcl.hpj.in files + were not converted, as it confuses hcw locally. [Bug: 5096] + + * win/Makefile.in: expanded cleanup target for help files + + * doc/Thread.3: minor macro cleanup + + * generic/tclFileName.c (SplitUnixPath): added support for QNX + node ids. + +2000-04-18 Jeff Hobbs + + * README: + * generic/tcl.h: + * tools/tcl.wse.in: + * unix/configure.in: + * unix/tcl.spec: + * win/configure.in: + * win/README.binary: bumped version to 8.3.1 + + * win/tcl.hpj.in: updated copyright date + + * generic/tclEnv.c: environment support for Mac OS/X + * unix/tclUnixPort.h: environment support for Mac OS/X + * unix/tclLoadDyld.c: new file for Mac OS/X dl functions + * unix/Makefile.in: added install-strip target; bindir, libdir, + mandir, includedir vars; tclLoadDyld.c target [Bug: 2527] + + * unix/tclUnixChan.c (CreateSocket): force a socket back into + blocking mode (default state) after a -async connect succeeds. + [Bug: 4388] + + * generic/tclEvent.c (TclInitSubsystems): Moved tclLibraryPath to + thread-local storage to prevent thread-related race condition. + [Bug: 5033] + * unix/tclAppInit.c (main): removed #ifdef TCL_TEST that sets the + library path as it was unnecessary and conflicts with move of + tclLibraryPath to thread-local storage. + +2000-04-18 Scott Redman + + * win/Makefile.in: + * win/tcl.rc: + * win/tclsh.rc: + * win/tclsh.ico: Modified copyright dates in Windows resource + files. Added an icon for tclsh.exe. + +2000-04-17 Brent Welch + + * generic/tcl.h, generic/tclThreadTest.c, unix/tclUnixThrd.c, + win/tclWinThread.c, mac/tclMacThread.c: + Added Tcl_CreateThreadType and TCL_RETURN_THREAD_TYPE + macros for declaring the NewThread callback proc. + +2000-04-14 Jeff Hobbs + + * unix/tclUnixChan.c (TtyParseMode): Only allow setting mark/space + parity on platforms that support it [Bug: 5089] + + * generic/tclBasic.c (Tcl_GetVersion): adjusted use of major/minor + to not conflict with global decl on some systems [Bug: 2882] + + * doc/AppInit.3: + * doc/Async.3: + * doc/BackgdErr.3: + * doc/CrtChannel.3: + * doc/CrtInterp.3: + * doc/CrtMathFnc.3: + * doc/DString.3: + * doc/Eval.3: + * doc/ExprLong.3: + * doc/GetInt.3: + * doc/GetOpnFl.3: + * doc/Interp.3: + * doc/LinkVar.3: + * doc/OpenFileChnl.3: + * doc/OpenTcp.3: + * doc/PkgRequire.3: + * doc/RecordEval.3: + * doc/SetResult.3: + * doc/SplitList.3: + * doc/StaticPkg.3: + * doc/TraceVar.3: + * doc/Translate.3: + * doc/UpVar.3: + * doc/load.n: removed or updated references to interp->result use. + +2000-04-13 Jeff Hobbs + + * doc/regexp.n: doc clarification [Bug: 5037] + * doc/update.n: typo fix [Bug: 4996] + + * unix/tcl.m4 (SC_ENABLE_THREADS): enhanced the detection of + pthread_mutex_init [Bug: 4359] and (SC_CONFIG_CFLAGS) added + --enable-64bit-vis switch for Sparc VIS compilation [Bug: 4995] + +2000-04-12 Jeff Hobbs + + * doc/dde.n: corrected dde poke docs. [Bug: 4991] + +2000-04-11 Eric Melski + + * win/tclWinPipe.c: Added "CONST" keyword to declaration of char + *native in TclpCreateTempFile, to supress compiler warnings. + +2000-04-10 Brent Welch + + * generic/tcl.h: Fixed Tcl_CreateThread declaration. + * library/tcltest1.0/tcltest.tcl: Fixed the "mainThread" + initialization to work with either testthread or the thread extension + * unix/tclUnixThrd.c: Fixed compiler warning when compiling + with -DTCL_THREADS + +2000-04-10 Eric Melski + + * win/tclWinPipe.c (TclpCreateTempFile): Added conversion of + contents string from UTF to native encoding [Bug: 4030]. + + * tests/regexp.test: Added tests for infinite looping in [regexp + -all]. + + * generic/tclCmdMZ.c: Fixed infinite loop bug with [regexp -all] + [Bug: 4981]. + + * tests/*.test: Changed all occurances of "namespace import + ::tcltest" to "namespace import -force ::tcltest" [Bug: 3948]. + +2000-04-09 Brent Welch + + * lib/httpd2.1/http.tcl: Worked on the "server closes before + reading post data" case, which unfortunately causes different + error cases on Solaris, which can read the reply, and Linux + and Windows, which cannot read anything. This is all in the + loop-back case - client and server on the same host. Also + unified the error handling so the "ioerror" status goes away + and errors are reflected in a more uniform way. Updated the + man page to document the behavior. + +2000-04-09 Jeff Hobbs + + * tests/reg.test (matchexpected): corrected tests to use tcltest + constraint types to skip certain tests. + + * generic/tclBasic.c (Tcl_SetCommandInfo): comment fix + + * unix/tclUnixThrd.c (Tcl_CreateThread): moved TCL_THREADS ifdef + inside of func as it is declared for non-threads builds as well. + In the non-threads case, it always returns TCL_ERROR (couldn't + create thread). + +2000-04-08 Andreas Kupries + + * Overall change: Definition of a public API for the creation of + new threads. + + * generic/tclInt.h (line 1802f): Removed the definition of + 'TclpThreadCreate'. (line 793f) Removed the definition of + 'Tcl_ThreadCreateProc'. + + * generic/tcl.h (line 388f): Readded the definition of + 'Tcl_ThreadCreateProc'. Added Win32 stuff send in by David + Graveraux to that too (__stdcall, + ...). Added macros for the default stacksize and allowed flags. + + * generic/tcl.decls (line 1356f): Added definition of + 'Tcl_CreateThread', slot 393 of the stub table. Two new + arguments in the public API, for stacksize and flags. + + * win/tclWinThrd.c: + * mac/tclMacThrd.c: Renamed TclpThreadCreate to Tcl_CreateThread, + added handling of the stacksize. Flags are currently ignored. + + * unix/tclUnixThrd.c: See above, but handles joinable + flag. Ignores the specified stacksize if the macro + HAVE_PTHREAD_ATTR_SETSTACKSIZE is not defined. + + * generic/tclThreadTest.c (line 363): See below. + + * unix/tclUnixNotfy.c (line 210): Adapted to the changes + above. Uses default stacksize and no flags now. + + * unic/tcl.m4 (line 382f): Added a check for + 'pthread_attr_setstacksize' to detect platforms not implementing + this feature of pthreads. If it is implemented, configure will + define the macro HAVE_PTHREAD_ATTR_SETSTACKSIZE (See + unix/tclUnixThrd.c too). + + * doc/Thread.3: Added Tcl_CreateThread and its arguments to the + list of described functions. Removed stuff about not providing a + public C-API for thread-creation. + +2000-04-07 Jeff Hobbs + + * doc/binary.n: clarified docs on sign extension in binary scan + [Bug: 3466] + + * library/tcltest1.0/tcltest.tcl (initConstraints): removed win32s + references (no longer supported) + + * tests/fCmd.test: marked test 8.1 knownBug because it is + dangerous on poorly configured systems [Bug: 3881] + and added 8.2 to keep essence of 8.1 tested. + +2000-04-05 Andreas Kupries + + * generic/tclIO.c (Tcl_UnstackChannel, line 1831): Forcing + interest mask to the correct value after an unstack and + re-initialization of the notifier via the watchProc. Without this + the first fileevent after an unstack will come through and be + processed, but no more. [Bug: ??]. + +2000-03-04 Brent Welch + + * {win,unix}/Makefile.in: added dependency of tclStubInit.c on + tcl.decls and tclInt.decls + * generic/tclThread.c: Tweak so this compiles w/out TCL_THREADS + * generic/{tcl.decls,tclStubInit.c}: Just touched the tcl.decls and + regenerated the tclStubInit.c file + +2000-03-29 Sandeep Tamhankar + + * library/http2.1/http.tcl: For the -querychannel option, + fconfigure the socket to be binary so that we don't translate + anything while reading the data. This is because we determine the + content length of the data on the channel by using seek (to the end + of the file) and tell on the file handle, and we need the + content-length to match the amount of data actually sent, and + translation can affect the number of bytes posted. + +2000-04-03 Andreas Kupries + + * Overall change: Definition of public API's for the finalization + of conditions and mutexes. [Bug: 4199]. + + * generic/tclInt.h: Removed definitions of TclFinalizeMutex and + TclFinalizeCondition. + + * generic/tcl.decls: Added declarations of Tcl_MutexFinalize and + Tcl_ConditionFinalize. + + * generic/tclThread.c: Renamed TclFinalizeMutex to + Tcl_MutexFinalize. Renamed TclFinalizeCondition to + Tcl_ConditionFinalize. + + * generic/tclNotify.c: Changed usage of TclFinalizeMutex to + Tcl_MutexFinalize. + + * unix/tclUnixNotfy.c: + * generic/tclThreadTest.c: Changed usages of TclFinalizeCondition to + Tcl_ConditionFinalize. + + * generic/tcl.h: Added empty macros for Tcl_MutexFinalize and + Tcl_ConditionFinalize, to be used when the core is compiled + without threads. + + * doc/Thread.3: Added description the new API's. + +2000-04-03 Jeff Hobbs + + * generic/tclCmdIL.c (InfoVarsCmd): checked for non-NULL procPtr + to prevent itcl info override crash [Bug: 4064] + + * tests/foreach.test: + * tests/namespace.test: + * tests/var.test: Added lsorts to avoid random sorted return + problems. [Bug: 2682] + + * tests/fileName.test: fixed 14.1 test fragility [Bug: 1482] + + * tools/man2help2.tcl: fixed winhelp cross-linking error [Bug: 4156] + improved translation to winhelp [Bug: 3679] + + * unix/Makefile.in (MAN_INSTALL_DIR): patch to accept --mandir + correctly [Bug: 4085] + + * unix/dltest/pkg[a-e].c: Cleaned up test packages [Bug: 2293] + +2000-04-03 Eric Melski + + * unix/tclUnixFCmd.c (SetGroupAttribute): + * unix/tclUnixFCmd.c (SetOwnerAttribute): Added (uid_t) and (gid_t) + casts to avoid compiler warnings. + +2000-03-31 Eric Melski + + * generic/tclGet.c (Tcl_GetDouble): Added additional conditions to + error test (previously only errno was checked, but the return + value of strtod() should be checked as well). [Bug: 4118]. + + * tests/exec.test: Added test for proper conversion of UTF data + when used with "<< $dataWithUTF" on exec's. + + * unix/tclUnixPipe.c (TclpCreateTempFile): Added + Tcl_UtfToExternalDString call, so that if there is UTF content in + the string it will be properly converted to the system encoding + before being written [Bug: 4030]. + (TclpCreateTempFile): Added a check on the return value of tmpnam; + some systems (Linux, for example) will start to return NULL after + tmpnam has been called TMP_MAX times; not checking for this can + have bad results (overwriting temp files, core dumps, etc.) + +2000-03-30 Jeff Hobbs + + * generic/tclBasic.c (Tcl_DeleteCommandFromToken): Added comments + noting the need to pair ckalloc with ckfree. [Bug: 4262] + + * generic/tclInt.decls: + * generic/tclIntPlatDecls.h: + * generic/tclStubInit.c: + * win/tclWin32Dll.c: removed TclWinSynchSpawn (vestige of Win32s + support). + + * win/tclWinReg.c: made use of TclWinGetPlatformId instead of + getting info again + + * win/tclWinPort.h: + * win/Makefile.in: + * win/configure.in: + * win/tcl.m4: Added support for gcc/mingw on Windows [Bug: 4234] + +2000-03-29 Jeff Hobbs + + * generic/tclCompile.c (TclCleanupByteCode): made ByteCode cleanup + more aware of TCL_BYTECODE_PRECOMPILED flagged structs (gen'd by + tbcload), to correctly clean them up. + + * generic/tclClock.c (FormatClock): moved check for empty format + earlier, commented 0 result return value + +2000-03-29 Sandeep Tamhankar + + * library/http2.1/http.tcl: Removed an unnecessary fileevent + statement from the error processing part of the Write method. + Also, fixed two potential memory leaks in wait and reset, in which + the state array wasn't being unset before throwing an exception. + Prior to this version, Brent checked in a fix to catch a + fileevent statement that was sometimes causing a stack trace when + geturl was called with -timeout. I believe Brent's fix is + necessary because TLS closes bad sockets for secure connections, + and the fileevent was trying to act on a socket that no longer + existed. + +2000-03-27 Jeff Hobbs + + * tests/httpd: removed unnecessary 'puts stderr "Post Dispatch"' + + * tests/namespace.test: + * generic/tclNamesp.c (Tcl_Export): added a uniq'ing test to the + export list so only one instance of each export pattern would + exist in the list. + + * generic/tclExecute.c (TclExecuteByteCode): optimized case for + the empty string in ==/!= comparisons + +2000-03-27 Eric Melski + + * unix/tclUnixChan.c: Added (off_t) type casts in lseek() call + [Bug: 4409]. + + * unix/tclLoadAout.c: + * unix/tclUnixPipe.c: Added (off_t) type casts in lseek() calls + [Bug: 4410]. + +2000-03-22 Sandeep Tamhankar + + * library/http2.1/http.tcl: Fixed a bug where string query data + that was bigger than queryblocksize would get duplicate characters + at block boundaries. + +2000-03-22 Sandeep Tamhankar + + * library/http2.1/http.tcl: Fixed bug 4463, where we were getting + a stack trace if we tried to publish a project to a good host but + a port where there was no server listening. It turned out the + problem was a stray fileevent that needed to be cleared. Also, + fixed a bug where http::code could stack trace if called on a bad + token (one which didn't represent a successful geturl) by adding + an http element to the state array in geturl. + +2000-03-21 Eric Melski + + * tests/clock.test: Modified some tests that were not robust with + respect to the time zone in which they were run and were thus + failing. + + * doc/clock.n: Clarified meaning of -gmt with respect to -base + when used with [clock scan] (-gmt does not affect the + interpretation of -base). + +2000-03-19 Sandeep Tamhankar + + * library/http2.1/http.tcl: geturl used to throw an exception when + the connection failed; I accidentally returned a token with the + error info, breaking backwards compatibility. I changed it back + to throwing an exception, but unsetting the state array first + (thus still eliminating the original memory leak problem). + +2000-03-19 Sandeep Tamhankar + + * library/http2.1/http.tcl: Added -querychannel option and altered + some of Brent's modifications to allow asynchronous posts (via + -command). Also modified -queryprogress so that it calls the + query callback as + to be consistent with -progress. Added -queryblocksize option + with default 8192 bytes for post blocksize. Fixed a bunch of + potential memory leaks for the case when geturl receives bad args + or can't open a socket, etc. Overall, the package really rocks + now. + + * doc/http.n: Added -queryblocksize, -querychannel, and + -queryprogress. Also, changed the description of -blocksize, + which states that the -progress callback will be called for each + block, to now qualify that with an "if -progress is specified". + + * tests/http.test: Added a querychannel test for synchronous and + asynchronous posts, altered the queryprogress test such that the + callback conforms to the -progress format. Also, had to use the + -queryblocksize option to do the post 16K at a time to match + Brent's expected results (and to test that -queryblocksize works). + +2000-03-15 Brent Welch + + * library/http2.1/http.tcl: Added -queryprogress callback to + http::geturl and also changed it so that writing the post data + is event driven if the queryprogress callback or a timeout is given. + This allows a timeout to occur when writing lots of post data. + The queryprogress callback is called after each block of query + data is posted. It has the same signature as the -progress callback. + +2000-03-06 Eric Melski + + * library/package.tcl: Applied patch from Bug: 2570; rather than + setting geometry of slave interp to 0x0 when Tk was loaded, it now + does "wm withdraw .". Both remove the main window from the + display, but the former caused some internal structures to get + initialized to zero, which caused crashes with some extensions. + +2000-03-02 Jeff Hobbs + + * library/package.tcl (tclPkgUnknown): extended to allow + recognizes changes in the auto_path while sourcing in other + pkgIndex.tcl files + + * doc/FindExec.3: fixed doc for declaration of Tcl_FindExecutable + [Bug: 4275] + + * generic/tclFileName.c (Tcl_TranslateFileName): Applied patch + from Newman to significantly speedup file split/join on Windows + (replaces regexp with custom parser). [Bug: 2867] + + * win/README.binary: change mailing lists from @consortium.org + to @scriptics.com [Bug: 4173] + +2000-02-28 Eric Melski + + * tests/clock.test: Added test for ISO bases < 100000 + + * generic/tclDate.c: (generated on Solaris) + * generic/tclGetDate.y: Changed condition for deciding if a number + is an ISO 8601 base from number >= 100000 to numberOfDigits >= 6. + Previously it would fail to recognize 000000 as an ISO base. + +2000-02-14 Eric Melski + + * unix/Makefile.in: Added rpm target to generate Tcl binary RPM. + + * unix/tcl.spec: RPM specification file for a Tcl binary RPM for + Linux. + +2000-02-10 Jeff Hobbs + + 8.3.0 RELEASE + + * changes: updated for 8.3.0 release + + * doc/load.n: added notes about dll load errors on Windows + + * unix/README: + * unix/Makefile.in (dist): removed porting.notes and porting.old + from distribution and CVS. The information was very outdated. Now + refer to http://dev.scriptics.com/services/support/platforms.html + + * tests/unixInit.test: fixed japanese LANG encoding test [Bug: 3549] + + * unix/configure.in: + * unix/tcl.m4: correct CFLAG_WARNING setting, + fixed gcc config for AIX, + added -export-dynamic to LDFLAGS for FreeBSD-3+ [Bug: 2998] + + * win/tclWinLoad.c (TclpLoadFile): improved error message for load + failures, could perhaps be even more intelligent. + +2000-02-09 Jim Ingham + + * mac/tclMacSock.c: Don't panic when you get an error closing an async + socket. This doesn't seem to hurt anything, and we return the error so + the caller can do the right thing. + + New Files: + * mac/MW_TclHeader.h: + * mac/MW_TclTestHeader.h: + * mac/MW_TclTestHeader.pch: + * mac/MW_TclAppleScriptHeader.h: More convenient to use .h prefix files + in the preference panels... + + The above are curtesy of Daniel Steffen (steffen@math.mq.edu.au) + +2000-02-08 Eric Melski + + * tests/clock.test: Added tests for "next monthname" constructs. + * generic/tclDate.c: + * generic/tclGetDate.y (Message): Added a grammar rule for "next + monthname" so that we can handle "next january" and similar + constructs (bug #4146). + +2000-02-08 Jeff Hobbs + + * README: + * tools/tcl.wse.in: + * unix/configure.in: + * win/configure.in: + * win/README: + * win/README.binary: + * generic/tcl.h (TCL_RELEASE_SERIAL): Moved to 8.3.0 patchlevel + + * doc/library.n: + * library/auto.tcl: fixed crufty puts code and docs [Bug: 4122] + + * library/tcltest1.0/tcltest.tcl: correctly protected searchDirectory + list to allow dirnames with spaces + + * unix/tcl.m4: changed all -fpic to -fPIC + + * generic/tclDecls.h: + * generic/tcl.decls: change Tcl_GetOpenFile to use decl of 'int + forWriting' instead of 'int write' to avoid shadowing [Bug: 4121] + + * tests/httpold.test: changed test script to source in the httpd + server procs from httpd instead of having its own set. + + * tests/httpd: improved query support in test httpd to handle fix + in http.tcl. [Bug: 4089 change 2000-02-01] + + * unix/README: fixed notes about --enable-shared and add note + about --disable-shared. + +2000-02-07 Eric Melski + + * tests/package.test: + * library/tclIndex: + * library/package.tcl: Renamed ::package namespace to ::pkg. + +2000-02-03 Eric Melski + + * doc/Package.n: + * doc/packagens.n: Renamed Package.n -> packagens.n because Windows + can't deal with case-sensitive names. + +2000-02-02 Jeff Hobbs + + * tests/regexp.test: added tests for -all and -inline switches + * doc/regexp.n: added docs for -all and -inline switches + * generic/tclCmdMZ.c (Tcl_RegexpObjCmd): added extra comments for + new -all and -inline switches to regexp command + +2000-02-01 Eric Melski + + * library/init.tcl: Applied patch from rfe 1734 regarding + auto_load errors not setting error message and errorInfo properly. + +2000-02-01 Jeff Hobbs + + * win/Makefile.in (install-*): reduced verbosity of install + + * generic/tclFileName.c (Tcl_JoinPath): improved support for special + QNX node id prefixes in pathnames [Bug: 4053] + + * library/http1.0/http.tcl: + * library/http2.1/http.tcl: The query data POSTed was newline + terminated when it shouldn't be altered [Bug: 4089] + +2000-01-31 Eric Melski + + * tests/package.test: + * library/tclIndex: + * library/package.tcl: Added ::package namespace and + ::package::create function. + + * library/init.tcl: Fixed problem with auto_load and determining + if commands were loaded. + + * library/auto.tcl: "Fixed" issues with $ in files to be auto indexed. + + * doc/Package.n: New man page for package::create function. + + * doc/pkgMkIndex.n: Added additional information. + + * doc/library.n: Added additional qualification regarding auto_mkindex. + +2000-01-28 Eric Melski + + * tests/pkg/magicchar2.tcl: + * tests/autoMkindex.test: Test for auto loader fix (bug #2480). + + * library/init.tcl: auto_load was using [info commands $name] to + determine if a given command was available; if the command name + had * or [] it, this would fail because info commands uses + glob-style matching. This is fixed. (Bug #2480). + + * tests/pkg/spacename.tcl: + * tests/pkgMkIndex.test: Tests for fix for bug #2360. + + * library/package.tcl: Fixed to extract only the first element of + the list returned by auto_qualify (bug #2360). + + * tests/pkg/magicchar.tcl: + * tests/autoMkindex.test: Test for fix for bug #2611. + + * library/auto.tcl: Fixed the regular expression that performs $ + escaping before sourcing a file to index. It was erroneously + adding \ escapes even to $'s that were already escaped, + effectively "un-escaping" those $'s. (bug #2611). + +2000-01-27 Eric Melski + + * tests/autoMkindex.test: + * library/auto.tcl: Applied patch (with slight modification) from + bug #2701: auto_mkIndex uses platform dependent file paths. + Added test for fix. + +2000-01-27 Jennifer Hom + + * library/tcltest1.0/tcltest.tcl: Changed NormalizePath to + normalizePath and exported it as a public proc. This proc + creates an absolute path given the name of the variable containing + the path to modify. The path is modified in place. + * library/tcltest1.0/pkgIndex.tcl: Added normalizePath. + * tests/all.tcl: Changed code to use normalizePath. + +2000-01-27 Eric Melski + + * tests/pkg/samename.tcl: test file for bug #1983 + + * tests/pkgMkIndex.test: + * doc/pkgMkIndex.n: + * library/package.tcl: Per rfe #4097, optimized creation of direct + load packages to bypass computing the list of commands added by + the new package. Also made direct loading the default, and added + a -lazy option. + Fixed bug #1983, dealing with pkg_mkIndex incorrectly handling + situations with two procs by the same name but in different + namespaces (ie, foo::baz and bar::baz). + +2000-01-26 Eric Melski + + * generic/tclNamesp.c: Undid fix for #956, which broke backwards + compatibility. + + * doc/variable.n: + * doc/trace.n: + * doc/namespace.n: + * doc/info.n: Added further information about differences between + "namespace which" and "info exists". + + * doc/SetErrno.3: Added descriptions of ErrnoId() and ErrnoMsg() + functions. + +2000-01-25 Jeff Hobbs + + * unix/tcl.m4: modified EXTRA_CFLAGS to add -DHAVE_TZSET for + OSF1-V* and ULTRIX-4.* when not using gcc. Also added higher min + stack size for OSF1-V* when building with threads. [Bug: 4063] + + * generic/tclClock.c (FormatClock): inlined resultPtr, as it + conflicted with var creation for HAVE_TZSET #def [Bug: 4063] + + * generic/tclCmdIL.c (Tcl_LsortObjCmd): fixed potential leak + when calling lsort -command with bad command [Bug: 4067] + + * generic/tclFileName.c (Tcl_JoinPath): added support for special + QNX node id prefixes in pathnames [Bug: 4053] + + * doc/ListObj.3: clarified Tcl_ListObjGetElements docs [Bug: 4080] + + * doc/glob.n: clarified Mac path separator determination docs. + + * win/makefile.vc: added some support for building helpfile on Windows + +2000-01-23 Jeff Hobbs + + * library/init.tcl (auto_execok): added 'start' to list of + recognized built-in commands for COMSPEC on NT. [Bug: 2858] + + * unix/tclUnixPort.h: moved include of lower since some + systems (UTS) require sys/types.h to be included first [Bug: 4031] + + * unix/tclUnixChan.c (CreateSocketAddress): changed comparison + with -1 to 0xFFFFFFFF, to ensure 32 bit comparison even on 64 bit + systems. [Bug: 3878] + + * generic/tclFileName.c: improved guessing of path separator + for the Mac. (Darley) + + * generic/tclInt.h: + * generic/tcl.decls: moved Tcl_ProcObjCmd to stubs table [Bug: 3827] + and removed 'register' from stub definition of + Tcl_AppendUnicodeToObj [Bug: 4038] + +2000-01-21 Eric Melski + + * unix/mkLinks: + * doc/GetHostName.3: Man page for Tcl_GetHostName (bug #1817). + + * doc/lreplace.n: Corrected man page with respect to treatment of + empty lists, and "prettied up" the page. (bug #1705). + +2000-01-20 Eric Melski + + * tests/namespace.test: Added test for undefined variables with + namespace which (bug #956). + + * generic/tclNamesp.c: Added check for undefined variables in + NamespaceWhichCmd (bug #956). + + * tests/var.test: Added tests for corrected variable behavior + (bug #981). + + * doc/upvar.n: Expanded explanation of upvar behavior with respect to + variable traces. (bugs 3917 1433 2110). + + * generic/tclVar.c: Changed behavior of variable command when name + refers to an element in an array (ie, "variable foo(x)") to always + return an error, regardless of existance of that element in the + array (now behavior is consistant with docs too) (bug #981). + +2000-01-20 Jeff Hobbs + + * generic/tclCmdIL.c (InfoBodyCmd): made [info body] return a + string if the body has been bytecompiled. + * generic/tclBasic.c (Tcl_EvalObjEx): added pedantic check for + originating proc body of bytecompiled code, #def'd out as the + change for [info body] should make it unnecessary + + * unix/tclUnixNotfy.c (Tcl_InitNotifier): added cast for tsdPtr + + * tests/set.test: added test for complex array elem name compiling + * generic/tclCompCmds.c (TclCompileSetCmd): Fixed parsing of array + elements during compiling, and slightly optimised same [Bug: 3889] + + * doc/tclvars.n: added definitions for tcl_(non)wordchars + + * doc/vwait.n: added notes about requirement for vwait var being + globally scoped [Bug: 3329] + + * library/word.tcl: changed tcl_(non)wordchars settings to use + new unicode regexp char class escapes instead of char sequences + +2000-01-14 Eric Melski + + * tests/var.test: Added a test for the array multiple delete + protection in Tcl_UnsetVar2. + + * generic/tclVar.c: Added protection in Tcl_UnsetVar2 against + attempts to multiply delete arrays when unsetting them (bug + #3453). This could happen if there was an unset trace on an array + element and the trace proc made a global or upvar link to the + array, and then the array was unset at the global level. See the + bug reference for more information. + + * unix/tclUnixTime.c: New clock format format. + + * compat/strftime.c: New clock format format. + + * generic/tclGetDate.y: New clock scan format. + +2000-01-13 Jeff Hobbs + + * changes: updated changes file to reflect 8.3b2 mods + + * README: + * generic/tcl.h: + * tools/tcl.wse.in: + * unix/configure.in: + * unix/tcl.m4: + * win/README.binary: + * win/configure.in: updated to patchlevel 8.3b2 + + * generic/regexec.c: added var initialization to prevent compiler + warning + +2000-01-13 Eric Melski + + * tests/cmdIL.test: Added tests for lsort -dictionary with + characters that occur between Z and a in ASCII. + + * generic/tclCmdIL.c: Modified DictionaryCompare function (used by + lsort -dictionary) to do upper/lower case equivalency before doing + character comparisons, instead of after. This fixes bug #1357, in + which lsort -dictionary [list ` AA c CC] and lsort -dictionary + [list AA c ` CC] gave different (and both wrong) results. + +2000-01-12 Eric Melski + + * tests/clock.test: Added tests for "next " and + "" + Added tests for "monday 1 week ago", etc, from RFE #3671. + + * doc/tests/clock.test: Added numerous tests for clock scan. + + * doc/generic/tclGetDate.y: Fixed some shift/reduce conflicts in + clock grammar. + + * doc/doc/clock.n: Added documentation for new supported clock + scan formats and additional explanation of daylight savings time + correction algorithm. + +2000-01-12 Jeff Hobbs + + * doc/file.n: + * tests/unixFCmd.test: + * unix/tclUnixFCmd.c: added support for symbolic permissions + setting in SetPermissionsAttribute (file attr $file -perm ...) + [Bug: 3970] + + * generic/tclClock.c: fixed support for 64bit handling of clock + values [Bug: 1806] + + * generic/tclThreadTest.c: upped a buffer size to hold double + + * tests/info.test: + * generic/tclCmdIL.c: fixed 'info procs ::namesp::*' behavior (Dejong) + + * generic/tclNamesp.c: made imported commands also import their + compile proc [Bug: 2100] + + * tests/expr.test: + * unix/Makefile.in: + * unix/configure.in: + * unix/tcl.m4: recognize strtod bug on Tru64 v5.0 [Bug: 3378] + and added tests to prevent unnecessary chmod +x in sources while + installing, as well as more intelligent setsockopt/gethostbyname + checks [Bug: 3366, 3389] + + * unix/tclUnixThrd.c: added compile time support (through use of + the TCL_THREAD_STACK_MIN define) for increasing the default stack + size for a thread. [Bug: 3797, 1966] + +2000-01-11 Eric Melski + + * generic/tclGetDate.y: Added comments for the Convert function. + Added a fix for daylight savings time handling for relative time + spans of days, weeks or fortnights. (bug 3441, 3868). + + * generic/tclDate.c: Fixed compiler warning issues. + +2000-01-10 Jeff Hobbs + + * compat/waitpid.c: use pid_t type instead of int [Bug: 3999] + + * tests/utf.test: fixed test that allowed \8 as octal value + * generic/tclUtf.c: changed Tcl_UtfBackslash to not allow + non-octal digits (8,9) in \ooo substs. [Bug: 3975] + + * generic/tcl.h: noted need to change win/tcl.m4 and + tools/tclSplash.bmp for minor version changes + + * library/http2.1/http.tcl: trim value for $state(meta) key + + * unix/tclUnixFile.c: fixed signature style on functions + + * unix/Makefile.in: made sure tcl.m4 would be installed with dist + + * unix/tcl.m4: added ELF support for NetBSD [Bug: 3959] + +2000-01-10 Eric Melski + + * generic/tclGetDate.y: Added rules for ISO 8601 formats (BUG #847): + CCYY-MM-DD + CCYYMMDD + YY-MM-DD + YYMMDD + CCYYMMDDTHHMMSS + CCYYMMDD HHMMSS + CCYYMMDDTHH:MM:SS + Fixed "clock scan " to scan the number as an hour for the + current day, rather than a minute after 00:00 for the current day + (bug #2732). + + +2000-01-07 Eric Melski + + * generic/tclClock.c: Changed switch in Tcl_ClockObjCmd to use + enumerated values instead of constants. (ie, COMMAND_SCAN instead + of 3). + +1999-12-22 Jeff Hobbs + + * changes: updated changes file + * tools/tclSplash.bmp: updated to show 8.3 + +1999-12-21 Jeff Hobbs + + * README: + * generic/tcl.h: + * mac/README: + * unix/configure.in: + * tools/tcl.wse.in: + * win/README.binary: + * win/configure.in: updated to patch level 8.3b1 + + * unix/Makefile.in: added -srcdir=... for 'make html' + + * doc/Hash.3: fixed reference to ckfree [Bug: 3912] + * doc/RegExp.3: fixed calling params for Tcl_RegExecFromObj + * doc/open.n: fixed minor formatting errors + * doc/string.n: fixed minor formatting errors + + * doc/lsort.n: added -unique docs + * tests/cmdIL.test: + * generic/tclCmdIL.c: added -unique option to lsort + + * generic/tclThreadTest.c: changed thread ids to longs [Bug: 3902] + + * mac/tclMacOSA.c: fixed applescript for I18N [Bug: 3644] + + * win/mkd.bat: + * win/rmd.bat: removed necessity of tag.txt [Bug: 3874] + + * win/tclWinThrd.c: changed CreateThread to _beginthreadex and + ExitThread to _endthreadex + +1999-12-12 Jeff Hobbs + + * doc/glob.n: + * tests/fileName.test: + * generic/tclInt.decls: + * generic/tclInt.h: + * generic/tclIntDecls.h: + * generic/tclStubInit.c: + * generic/tclEncoding.c: + * generic/tclFileName.c: + * mac/tclMacFile.c: + * unix/tclUnixFile.c: + * win/tclWinFile.c: enhanced the glob command with the new options + -types -path -directory and -join. Deprecated TclpMatchFiles with + TclpMatchFilesTypes, extended TclGlob and TclDoGlob and added + GlobTypeData structure. [Bug: 2363] + +1999-12-10 Jeff Hobbs + + * tests/var.test: + * generic/tclCompile.c: fixed problem where setting to {} array + would intermittently not work. (Fontaine) [Bug: 3339] + + * generic/tclCmdMZ.c: + * generic/tclExecute.c: optimized INST_TRY_CVT_TO_NUMERIC to + recognize boolean objects. (Spjuth) [Bug: 2815] + + * tests/info.test: + * tests/parseOld.test: + * generic/tclCmdAH.c: + * generic/tclProc.c: changed Tcl_UplevelObjCmd (uplevel) and + Tcl_EvalObjCmd (eval) to use TCL_EVAL_DIRECT in the single arg + case as well, to take advantage of potential pure list input + optimization. This means that it won't get byte compiled though, + which should be acceptable. + * generic/tclBasic.c: made Tcl_EvalObjEx pure list object aware in + the TCL_EVAL_DIRECT case for efficiency. + * generic/tclUtil.c: made Tcl_ConcatObj pure list object aware, + and return a list object in that case [Bug: 2098 2257] + + * generic/tclMain.c: changed Tcl_Main to not constantly reuse the + commandPtr object (interactive case) as it could be shared. (Fellows) + + * unix/configure.in: + * unix/tcl.m4: + * unix/tclUnixPipe.c: removed checking for compatible vfork + function and use of the vfork function. Modern VM systems rarely + suffer any performance degradation when fork is used, and it + solves multiple problems with vfork. Users that still want vfork + can add -Dfork=vfork to the compile flags. [Bug: 942 2228 1312] + +1999-12-09 Jeff Hobbs + + * win/aclocal.m4: made it just include tcl.m4 + + * doc/exec.n: + * doc/open.n: + * win/tclWin32Dll.c: + * win/tclWinChan.c: + * win/tclWinFCmd.c: + * win/tclWinInit.c: + * win/tclWinPipe.c: + * win/tclWinSock.c: removed all code that supported Win32s. It + was no longer officially supported, and likely didn't work anyway. + * win/makefile.vc: removed 16 bit stuff, cleaned up. + + * win/tcl16.rc: + * win/tclWin16.c: + * win/winDumpExts.c: these files have been removed from the + source tree (no longer necessary to build) + +1999-12-07 Jeff Hobbs + + * tests/io.test: removed 'knownBug' tests that were for + unsupported0, which is now fcopy (that already has tests) + + * mac/tclMacPort.h: added utime.h include + + * generic/tclDate.c: + * unix/Makefile.in: fixed make gendate to swap const with CONST + so it uses the Tcl defined CONST type [Bug: 3521] + + * generic/tclIO.c: removed panic that could occur in FlushChannel + when a "blocking" channel would receive EAGAIN, instead treating + it the same as non-blocking. [Bug: 3773] + + * generic/tclUtil.c: fixed Tcl_ScanCountedElement to not step + beyond the end of the counted string [Bug: 3336] + +1999-12-03 Jeff Hobbs + + * doc/load.n: added note about NT's buggy handling of './' with + LoadLibrary + + * library/http2.1/http.tcl: fixed error handling in http::Event + [Bug: 3752] + + * tests/env.test: removed knownBug limitation from working test + * tests/all.tcl: ensured that ::tcltest::testsDirectory would be + set to an absolute path + + * tests/expr-old.test: + * tests/parseExpr.test: + * tests/string.test: + * generic/tclGet.c: + * generic/tclInt.h: + * generic/tclObj.c: + * generic/tclParseExpr.c: + * generic/tclUtil.c: + * generic/tclExecute.c: added TclCheckBadOctal routine to enhance + error message checking for when users use invalid octal numbers + (like 08), as well as replumbed the Expr*Funcs with a new + VerifyExprObjType to simplify type handling. [Bug: 2467] + + * tests/expr.test: + * generic/tclCompile.c: fixed 'bad code length' error for + 'expr + {[incr]}' case, with new test case [Bug: 3736] + and seg fault on 'expr + {[error]}' (different cause) that + was caused by a correct optimization that didn't correctly + track how it was modifying the source string in the opt. + The optimization was removed, which means that: + expr 1 + {[string length abc]} + will be not be compiled inline as before, but this should be + written: + expr {1 + [string length abc]} + which will be compiled inline for speed. This prevents + expr 1 + {[mindless error]} + from seg faulting, and only affects optimizations for + degenerate cases [Bug: 3737] + +1999-12-01 Scott Redman + + * generic/tcl.decls : + * generic/tclMain.c : + * unix/tclAppInit.c: + * win/tclAppInit.c: Added two new internal functions, + TclSetStartupScriptFileName() and TclGetStartupScriptFileName() + and added hooks into the main() code for supporting TclPro and + other "big" shells more easily without requiring a copy of the + main() code. + + * generic/tclEncoding.c: + * generic/tclEvent.c: Moved encoding-related startup code from + tclEvent.c into the more appropriate tclEncoding.c. + +1999-11-30 Jeff Hobbs + + * generic/tclIO.c: fix from Kupries for Tcl_UnstackChannel that + correctly handles resetting translation and encoding. + + * generic/tclLoad.c: #def'd out the unloading of DLLs at finalize + time for Unix in TclFinalizeLoad. [Bug: 2560 3373] Should be + parametrized to allow for user to specify unload or not. + + * win/tclWinTime.c: fixed handling of %Z on NT for time zones + that don't have DST. + +1999-11-29 Jeff Hobbs + + * library/dde1.1/pkgIndex.tcl: + * library/reg1.0/pkgIndex.tcl: added supported for debugged + versions of the libraries + + * unix/tclUnixPipe.c: fixed PipeBlockModeProc to properly set + isNonBlocking flag on pipe. [Bug: 1356 710] + removed spurious fcntl call from PipeBlockModeProc + + * tests/scan.test: + * generic/tclScan.c: fixed scan where %[..] didn't match anything + and added test case [Bug: 3700] + +1999-11-24 Jeff Hobbs + + * doc/open.n: + * win/tclWinSerial.c: adopted patch from Schroedter to handle + fconfigure $sock -lasterror on Windows. [RFE: 3368] + + * generic/tclCmdIL.c: made SORTMODE_INTEGER work with Longs + [Bug: 3652] + +1999-11-23 Scott Stanton + + * library/tcltest1.0/tcltest.tcl: Fixed bug where tcltest output + went to stdout instead of the specified output file in some + cases. + +1999-11-19 Jeff Hobbs + + * generic/tclProc.c: backed out change from 1999-11-18 as it + could affect return string from upvar as well. + + * tools/tcl.wse.in: added tcltest1.0 library to distribution list + + * doc/http.n: + * library/http2.1/http.tcl: + * library/http2.1/pkgIndex.tcl: updated http package to 2.2 + +1999-11-18 Jeff Hobbs + + * unix/tcl.m4: added defined for _THREAD_SAFE in --enable-threads + case; added check for pthread_mutex_init in libc; in AIX case, + with --enable-threads ${CC}_r is used; fixed flags when using gcc + on SCO + + * generic/tclProc.c: corrected error reporting for default case + at the global level for uplevel command. + + * generic/tclIOSock.c: changed int to size_t type for len + in TclSockMinimumBuffers. + + * generic/tclCkalloc.c: fixed Tcl_DbCkfree to return a value + on NULL input. [Bug: 3400] + + * generic/tclStringObj.c: fixed support for passing in negative + length to Tcl_SetUnicodeObj, et al handling routines. [Bug: 3380] + + * doc/scan.n: + * tests/scan.test: + * generic/tclScan.c: finished support for inline scan by + supporting XPG identifiers. + + * doc/http.n: + * library/http2.1/http.tcl: added register and unregister + commands to http:: package (better support for tls/SSL), + as well as -type argument to http::geturl. [RFE: 2617] + + * generic/tclBasic.c: removed extra decr of numLevels in + Tcl_EvalObjEx that could cause seg fault. (mjansen@wendt.de) + + * generic/tclEvent.c: fixed possible lack of MutexUnlock in + Tcl_DeleteExitHandler [Bug: 3545] + + * unix/tcl.m4: Added better pthreads library check and inclusion + of _THREAD_SAFE in --enable-threads case + Added support for gcc config on SCO + + * doc/glob.n: added note about ..../ glob behavior on Win9* + * doc/tcltest.n: fixed minor example errors [Bug: 3551] + +1999-11-17 Brent Welch + * library/http2.1/http.tcl: Correctly fixed the -timeout + problem mentioned in the 10-29 change. Also added error + handling for failed writes on the socket during the protocol. + +1999-11-09 Jeff Hobbs + + * doc/open.n: corrected docs for 'a' open mode. + + * generic/tclIOUtil.c: changed Tcl_Alloc to ckalloc + + * generic/tclInt.h: + * generic/tclObj.c: rolled back changes from 1999-10-29 + Purify noted new leaks with that code + + * generic/tclParse.c: added code in Tcl_ParseBraces to test for + possible unbalanced open brace in a comment + + * library/init.tcl: removed the installed binary directory from + the auto_path variable + + * tools/tcl.wse.in: updated to 8.3a1, fixed install of twind.tcl + and koi8-r.enc files + + * unix/tcl.m4: added recognition of pthreads library for AIX + +1999-10-29 Brent Welch + * generic/tclInt.h: Modified the TclNewObj and TclDecrRefCount + in two ways. First, in the case of TCL_THREADS, we do not use + the special Tcl_Obj allocator because that is a source of + lock contention. Second, general code cleanup to eliminate + duplicated code. In particular, TclDecrRefCount now uses + TclFreeObj instead of duplicating that code, so it is now + identical to Tcl_DecrRefCount. + + * generic/tclObj.c: Changed Tcl_NewObj so it uses the + TclNewObj macro instead of duplicating the code. Adjusted + TclFreeObj so it understands the TCL_THREADS case described + above. + + * library/http2.1/http.tcl: Fixed a bug in the handling of + the state(status) variable when the -timeout flag is specified. + Previously it was possible to leave the status undefined + instead of empty, which caused errors in http::status + +1999-10-28 Jeff Hobbs + + * unix/aclocal.m4: made it just include tcl.m4 + + * library/tcltest1.0/tcltest.tcl: updated makeFile to return + full pathname of file created + + * generic/tclStringObj.c: fixed Tcl_AppendStringsToObjVA so it only + iterates once over the va_list (avoiding a memcpy of it, + which is not portable). + + * generic/tclEnv.c: fixed possible ABR error in environ array + + * tests/scan.test: + * generic/tclScan.c: added support for use of inline scan, + XPG3 currently not included + + * tests/incr.test: + * tests/set.test: + * generic/tclCompCmds.c: fixed improper bytecode handling of + 'eval {set array($unknownvar) 5}' (also for incr) [Bug: 3184] + + * win/tclWinTest.c: added testvolumetype command, as atime is + completely ignored for Windows FAT file systems + * win/tclWinPort.h: added sys/utime.h to includes + * unix/tclUnixPort.h: added utime.h to includes + * doc/file.n: + * tests/cmdAH.test: + * generic/tclCmdAH.c: added time arguments to atime and mtime + file command methods (support 'touch' functionality) + +1999-10-20 Jeff Hobbs + + * unix/tclUnixNotfy.c: fixed event/io threading problems by + making triggerPipe non-blocking [Bug: 2792] + + * library/tcltest1.0/tcltest.tcl: + * generic/tclThreadTest.c: fixed mem leaks in threads + + * generic/tclResult.c: fixed Tcl_AppendResultVA so it only + iterates once over the va_list (avoiding a memcpy of it, + which is not portable). + + * generic/regc_color.c: fixed mem leak and assertion, from HS + + * generic/tclCompile.c: removed savedChar trick that appeared to + be causing a segv when the literal table was released + + * tests/string.test: + * generic/tclCmdMZ.c: fixed [string index] to return ByteArrayObj + when indexing into one (test case string-5.16) [Bug: 2871] + + * library/http2.1/http.tcl: protected gets with catch [Bug: 2665] + +1999-10-19 Jennifer Hom + + * tests/tcltest.test: + * doc/tcltest.n: + * library/tcltest1.0/tcltest.tcl: Removed the extra return at the + end of the tcltest.tcl file, added version information about tcl. + + Applied patches sent in by Andreas Kupries to add helper procs for + debug output, add 3 new flags (-testsdir, -load, -loadfile), and + internally refactors common code for dealing with paths into + separate procedures. [Bug: 2838, 2842] + + Merged code from core-8-2-1 branch that changes the checks for the + value of tcl_interactive to also incorporate a check for the + existence of the variable. + + * tests/autoMkindex.test: + * tests/pkgMkIndex.test: Explicitly cd to + ::tcltest::testsDirectory at the beginning of the test run + + * tests/basic.test: Use version information defined in tcltest + instead of hardcoded version number + + * tests/socket.test: package require tcltest before attempting to + use variable defined in tcltest namespace + + * tests/unixInit.test: + * tests/unixNotfy.test: Added explicit exits needed to avoid + problems when the tests area run in wish. + +1999-10-12 Jim Ingham + + * mac/tclMacLoad.c: Stupid bug - we converted the filename to + external, but used the unconverted version. + * mac/tclMacFCmd.c: Fix a merge error in the bug fix for [Bug: 2869] + +1999-10-12 Jeff Hobbs + + * generic/regc_color.c: + * generic/regc_cvec.c: + * generic/regc_lex.c: + * generic/regc_locale.c: + * generic/regcomp.c: + * generic/regcustom.h: + * generic/regerrs.h: + * generic/regex.h: + * generic/regexec.c: + * generic/regguts.h: + * generic/tclRegexp.c: + * generic/tclTest.c: + * tests/reg.test: updated to Henry Spencer's new regexp engine + (mid-Sept 99). Should greatly reduce stack space reqs. + + * library/tcltest1.0/pkgIndex.tcl: fixed procs in pkgIndex.tcl file + + * generic/tclEnv.c: fixed mem leak with putenv and DStrings + * doc/Encoding.3: corrected docs + * tests/basic.test: updated test cases for 8.3 + * tests/encoding.test: fixed test case that change system + encoding to a double-byte one (this causes a bogus mem read + error for purify) + * unix/Makefile.in: purify has to use -best-effort to instrument + * unix/tclAppInit.c: identified potential mem leak when compiling + tcltest (not critical) + * unix/tclUnixPipe.c: fixed mem leak in TclpCreateProcess when + doing alloc between vfork and execvp. + * unix/tclUnixTest.c: fixed mem leak in findexecutable test command + +1999-10-05 Jeff Hobbs + + * {win,mac,unix,tools,}/README: + * win/README.binary: + * win/makefile.vc: + * {win,unix}/configure.in: + * generic/tcl.h: + * library/init.tcl: updated to 8.3a1 from 8.2.0. + + * library/http2.1/http.tcl: fixed possible use of global c var. + + * win/tclWinReg.c: fixed registry command to properly 'get' + HKEY_PERFORMANCE_DATA root key data. Needs more work. + + * generic/tclNamesp.c: + * generic/tclVar.c: + * generic/tclCmdIL.c: fixed comment typos + + * mac/tclMacFCmd.c: fixed filename stuff to support UTF-8 [Bug: 2869] + + * win/tclWinSerial.c: changed SerialSetOptionProc to return + TCL_OK by default. (patch from Rolf Schroedter) + +1999-09-21 Jennifer Hom + + * library/tcltest1.0/tcltest.tcl: Applied patches sent in by + Andreas Kupries to fix typos in comments and ::tcltest::grep, + fix hook redefinition problems, and change "string compare" to + "string equal." [Bug: 2836, 2837, 2839, 2840] + +1999-09-20 Jeff Hobbs + + * tests/env.test: + * unix/Makefile.in: added support for AIX LIBPATH env var [Bug: 2793] + removed second definition of INCLUDE_INSTALL_DIR (the one that + referenced @includedir@) [Bug: 2805] + * unix/dltest/Makefile.in: added -lc to LIBS [Bug: 2794] + +1999-09-16 Jeff Hobbs + + * tests/timer.test: changed after delay in timer test 6.29 from + 1 to 10. [Bug: 2796] + + * tests/pkg.test: + * generic/tclPkg.c: fixed package version check to disallow 1.2..3 + [Bug: 2539] + + * unix/Makefile.in: fixed gendate target - this never worked + since RCS was intro'd. + * generic/tclGetDate.y: updated to reflect previous changes + to tclDate.c (leap year calc) and added CEST and UCT time zone + recognition. Fixed 4 missing UCHAR() casts. [Bug: 2717, 954, + 1245, 1249] + + * generic/tclCkalloc.c: changed Tcl_DumpActiveMemory to really + dump to stderr and close it [Bug: 725] and changed Tcl_Ckrealloc + and Tcl_Ckfree to not bomb when NULL was passed in [Bug: 1719] + and changed Tcl_Alloc, et al to not panic when a alloc request + for zero came through and NULL was returned (valid on AIX, Tru64) + [Bug: 2795, etc] + + * tests/clock.test: + * doc/clock.n: + * generic/tclClock.c: added -milliseconds switch to clock clicks + to guarantee that the return value of clicks is in the millisecs + granularity [Bug: 2682, 1332] + +1999-09-15 Jeff Hobbs + + * generic/tclIOCmd.c: fixed potential core dump in conjunction + with stacked channels with result obj manipulation in + Tcl_ReadChars [Bug: 2623] + + * tests/format.test: + * generic/tclCmdAH.c: fixed translation of %0#s in format [Bug: 2605] + + * doc/msgcat.n: fixed \\ bug in example [Bug: 2548] + + * unix/tcl.m4: + * unix/aclocal.m4: added fix for FreeBSD-[1-2] recognition + [Bug: 2070] and fix for IRIX SHLIB_LB_LIBS. [Bug: 2610] + + * doc/array.n: + * tests/var.test: + * tests/set.test: + * generic/tclVar.c: added an array unset operation, with docs + and tests. Variation of [Bug: 1775]. Added fix in TclArraySet + to check when trying to set in a non-existent namespace. [Bug: 2613] + +1999-09-14 Jeff Hobbs + + * tests/linsert.test: + * doc/linsert.n: + * generic/tclCmdIL.c: fixed end-int interpretation of linsert + to correctly calculate value for end, added test and docs [Bug: 2693] + + * doc/regexp.n: + * doc/regsub.n: + * tests/regexp.test: + * generic/tclCmdMZ.c: add -start switch to regexp and regsub + with docs and tests + + * doc/switch.n: added proper use of comments to example. + * generic/tclCmdMZ.c: changed switch to complain when an error + occurs that seems to be due to a misplaced comment. + + * generic/tclCmdMZ.c: fixed illegal ref for \[0-9] substitutions + in regsub [Bug: 2723] + + * generic/tclCmdMZ.c: changed [string equal] to return an Int + type object (was a Boolean) + +1999-09-01 Jennifer Hom + + * library/tcltest1.0/tcltest.tcl: Process command-line arguments + only ::tcltest doesn't have a child namespace (requires that + command-line args are processed in that namespace) + +1999-09-01 Jeff Hobbs + + * generic/tclParseExpr.c: changed '"' to '\"' to make FreeBSD + happy [Bug: 2625] + * generic/tclProc.c: moved static buf to better location and + changed static msg that would overflow in ProcessProcResultCode + [Bug: 2483] and added Tcl_DStringFree to Tcl_ProcObjCmd. + Also reworked size of static buffers. + * tests/stringObj.test: added test 9.11 + * generic/tclStringObj.c: changed Tcl_AppendObjToObj to + properly handle the 1-byte dest and mixed src case where + both had had Unicode string len checks made on them. [Bug: 2678] + * unix/aclocal.m4: + * unix/tcl.m4: adjusted fix from 8-21 to add -bnoentry to the + AIX-* case and readjusted the range + +1999-08-31 Jennifer Hom + + * library/tcltest1.0/tcltest.tcl: + * doc/tcltest.n: + * tests/README: Modified testConstraints variable so that it isn't + unset every time ::tcltest::initConstraints is called and cleaned up + documentation in the README file and the man page. + +1999-08-27 Jennifer Hom + + * tests/env.test: + * tests/exec.test: + * tests/io.test: + * tests/event.test: + * tests/tcltest.test: Added 'exit' calls to scripts that the tests + themselves write, and removed accidental checkin of knownBugThreaded + constraints for Solaris and Linux. + + * library/tcltest1.0/tcltest.tcl: Modified tcltest so that + variables are only initialized to their default values if they did + not previously exist. + +1999-08-26 Jennifer Hom + + * tests/tcltest.test: + * library/tcltest1.0/tcltest.tcl: Added a -args flag that sets a + variable named ::tcltest::parameters based on whatever's being + sent in as the argument to the -args flag. + +1999-08-23 Jennifer Hom + + * tests/tcltest.test: Added additional tests for -tmpdir, marked + all tests that use exec as unixOrPc. + + * tests/encoding.test: + * tests/interp.test: + * tests/macFCmd.test: + * tests/parseOld.test: + * tests/regexp.test: Applied patches from Jim Ingham to add + encoding to a Mac only interp test, change an error message in + macFCmd.tet, put a comment in parseOld.test, fix tests using the + testencoding path command, and put unixOrPc constraints on tests + that use exec. + +1999-08-21 Jeff Hobbs + + * unix/aclocal.m4: Changed AIX-4.[2-9] check to AIX-4.[1-9] + [Bug: 1909] + +1999-08-20 Jeff Hobbs + + * generic/tclPosixStr.c: fixed typo [Bug: 2592] + + * doc/*: fixed various nroff bugs in man pages [Bug: 2503 2588] + +1999-08-19 Jeff Hobbs + + * win/README.binary: fixed version info and some typos [Bug: 2561] + + * doc/interp.n: updated list of commands available in a safe + interpreter [Bug: 2526] + + * generic/tclIO.c: changed Tcl_GetChannelNames* to use style guide + headers (pleases HP cc) + +1999-08-18 Jeff Hobbs + + * doc/Eval.3: fixed doc on input args [Bug: 2114] + + * doc/OpenFileChnl.3: + * doc/file.n: + * tests/cmdAH.test: + * tclIO.c: + * tclCmdAH.c: added "file channels ?pattern?" tcl command, with + associated Tcl_GetChannelNames and Tcl_GetChannelNamesEx public + C APIs (added to tcl.decls as well), with docs and tests. + + * tests/expr.test: + * generic/tclCompile.c: add TCL_TOKEN_VARIABLE to the part types + that cause differed compilation for exprs, to correct the expr + double-evaluation problem for vars. Added test cases. + Related to [Bug: 732] + + * unix/Makefile.in: changed the dependency structure so that + install-* is dependent on * (ie - install-binaries is dependent + on binaries). + + * library/auto.tcl: + * library/init.tcl: + * library/ldAout.tcl: + * library/package.tcl: + * library/safe.tcl: + * library/word.tcl: + * library/http2.1/http.tcl: + * library/msgcat1.0/msgcat.tcl: updated libraries to better + Tcl style guide (no more string comparisons with == or !=, spacing + changes). + +1999-08-05 Jim Ingham + + * mac/tclMacProjects.sea.hqx: Rearrange the projects so that the build + directory is separate from the sources. Much more convenient! + +1999-08-13 Scott Redman + + * /: 8.2.0 tagged for final release + +1999-08-12 Scott Stanton + + * win/Makefile.in: Added COMPILE_DEBUG_FLAGS macro to make it + easier to turn on compiler tracing. + + * tests/parse.test: + * generic/tclParse.c: Fixed bug in Tcl_EvalEx where the termOffset + was not being updated in cases where the evaluation returned a non + TCL_OK error code. [Bug: 2535] + +1999-08-12 Scott Redman + + * win/tclWinSerial.c: Applied patch from Petteri Kettunen to + remove compiler warning. + +1999-08-10 Scott Redman + + * generic/tclAlloc.c: + * generic/tclCmdIL.c: + * generic/tclIO.c: + * generic/tclThread.c: + * win/tclWinThrd.c: + * unix/tclUnixThrd.c: Fixed Brent's changes so that they work on + Windows (and he fixed the bug in the Unix thread implementation). + +1999-08-09 Brent Welch + + * generic/tcl.decls: + * generic/tclAlloc.c: + * generic/tclCkalloc.c: + * generic/tclCmdIL.c: + * generic/tclDecls.h: + * generic/tclIO.c: + * generic/tclInt.decls: + * generic/tclIntDecls.h: + * generic/tclStubInit.c: + * generic/tclVar.c: + * mac/tclMacThrd.c: + * unix/tclUnixThrd.c: + * win/tclWinThrd.c: Added use of Tcl_GetAllocMutex to tclAlloc.c + and tclCkalloc.c so they can be linked against alternate thread + packages. Added Tcl_GetChannelNames to tclIO.c. Added + TclVarTraceExists hook so "info exists" triggers read traces + exactly like it did in Tcl 7.6. Stubs table changes to reflect new + internal and external APIs. + +1999-08-09 Jeff Hobbs + + * tests/string.test: added largest_int proc to adapt for >32 bit + machines and int overflow testing. + * tests/tcltest.test: fixed minor error in 8.2 result (from dgp) + + * doc/Object.3: clarified Tcl_DecrRefCount docs [Bug: 1952] + * doc/array.n: clarified array pattern docs [Bug: 1330] + * doc/clock.n: fixed clock docs [Bug: 693] + * doc/lindex.n: clarified to account for new end-int behavior. + * doc/string.n: fixed formatting errors [Bug: 2188 2189] + * doc/tclvars.n: fixed doc error [Bug: 2042] + * library/init.tcl: fixed path handling in auto_execok (it could + miss including the normal path on some Windows machines) [Bug: 1276] + +1999-08-05 Jeff Hobbs + + * doc/tclvars.n: Made it clear that tcl_pkgPath was not set + for Windows (already mentioned in init.tcl) [Bug: 2455] + * generic/tclLiteral.c: fixed reference to bytes that might + not be null terminated (using objPtr->bytes, which is) [Bug: 2496] + * library/http2.1/http.tcl: Made use of "i" in init section use + local var and start at 0 (was 1). [Bug: 2502] + +1999-08-04 Scott Stanton + + * tests/reg.test: Added test for REG_EXPECT bug fixed by Henry's + patch. + + * generic/regc_nfa.c: + * generic/regcomp.c: + * generic/rege_dfa.c: + * generic/regexec.c: + * generic/regguts.h: Applied patches supplied by Henry Spencer to + greatly enhance the performance of certain classes of regular + expressions. [Bug: 2440, 2447] + +1999-08-03 Scott Redman + + * win/tclWinInt.h: Remove function declarations in header that was + moved to tclInt.decls file in previous changes. + +1999-08-02 Scott Redman + + * unix/configure.in: + * win/configure.in: Change beta level to b2. + + * generic/tcl.h: + * generic/tcl.decls: + * generic/tclDecls.h: + * generic/tclInt.h: + * generic/tclInt.decls: + * generic/tclIntDecls.h: + * generic/tclRegexp.h: + * generic/tclStubInit.c: Move some exported public and internal + functions to the stub tables. Removed functions that are in the + stub tables (from this and previous changes) from the original + header files. + +1999-08-01 Scott Redman + + * win/tclWinSock.c: Added comment block to SocketThread() + function. Added code to avoid calling TerminateThread(), but + instead to send a message to the socket event window to tell it to + terminate its thread. + +1999-07-30 Jennifer Hom + + * tests/tcltest.test: + * library/tcltest1.0/tcltest.tcl: Exit with non-zero status if + there were problems with the way the test suite was started + (e.g. wrong # arguments). + +1999-07-30 Jeff Hobbs + + * generic/tclInt.decls: added declaractions necessary for the + Tcl test code to work wth stubs [Bug: 2445] + +1999-07-30 + + * win/tclWinPipe.c: + * win/Makefile.in: Fixing launching of 16-bit apps on Win9x from + wish. The command line was primed with tclpip82.dll, but it was + ignored. Fixed that, then fixed the gmake makefile to build + tclpip82.dll as an executable. + + * win/tclWinSock.c: Applied small patch to get thread-specific + data after initializing the socket driver. + + * unix/tclUnixThrd.c: Applied patch to fix threads on Irix 6.5. + Patch from James Dennett. [Bug: 2450] + + * tests/info.test: Enable test for tclParse.c change (info + complete). + +1999-07-30 + + * tclIO.c: added fix for Kupries' trf patch [Bug: 2386] + + * tclParse.c: fixed bug in info complete regarding nested square + brackets [Bug: 2382, 2466] + +1999-07-29 + + * win/tclWinChan.c: Allow tcl to open CON and NUL, even for std + channels. Checking for bad/unusable std channels was moved to Tk + since its only purpose was to check whether to use the Tk Console + Window for the std channels. [Bug: 2393 2392 2209 2458] + + * unix/mkLinks.tcl: Applied patch to avoid linking pack.n to + pack-old.n. Patch from Don Porter. [Bug: 2469] + + * doc/Encoding.n: Applied patch to fix typo in .SH NAME line. + Patch from Don Porter. [Bug: 2451] + + * win/tclWinSock.c: Free Win32 Event handles when destroying + the socket helper thread. + +1999-07-28 + + * tests/tcltest.test: + * library/tcltest1.0/tcltest.tcl: Fixed the condition under which + ::tcltest::PrintError had an infinite loop problem and added a + test case for it. Added an optional argument to + ::tcltest::getMatchingFiles telling it where to search for test + files. + +1999-07-27 + + * tools/tclSplash.bmp: Updated Windows installer bitmap + to ready Tcl/Tk Version 8.2. + +1999-07-26 + + * tests/tcltest.test: Need to close the new core file, there + seems to be a hang in threaded WinNT if the file isn't closed. + Open issue, need to fix that hang. + + * tests/httpold.test: Add time delay in response from Http server + so that test cases can properly detect timeout conditions with + threads enabled on multi-CPU WinNT. + + * tests/winFCmd.test: Test case winFcmd-1.33 was looking for + c:\windows, which may not exist. Instead, create a new directory + on c:\ and use it for the test. + + * win/tclWinConsole.c: + * win/tclWinPipe.c: + * win/tclWinSock.c: Fix terminating helper threads by holding any + mutexes from the primary thread while waiting for the helper + thread to terminate. Without these changes, the test suite hangs + on WinNT with 2 CPUs and threads enabled. Open issue, seems to be + a sporadic hang on dual CPU systems still (very rare). + +1999-07-26 Jennifer Hom + + * tests/tcltest.test: + * library/tcltest1.0/tcltest.tcl: + * doc/tcltest.n: Cleaned up code in ::tcltest::PrintError, revised + documentation, and added tests for the tcltest package. + +1999-07-23 + + * tests/info.test: + * generic/tclParse.c: Removed patch for info command, breaks test + cases on Unix. Patch was bad and needs to be redone + properly. [Bug: 2382] + +1999-07-22 + + * Changed version to 8.2b2. + + * win/tclWinSock.c: Fixed hang with threads enabled, fixed + semaphores with threads disabled. + + * win/safe.test: Fixed safe-6.3 with threads enabled. + + * win/Makefile.in: Fixed calling of tcltest to fix safe.test + failures due to path TCL_LIBRARY path. + + * win/tclWinPort.h: Block out include of sys/*.h in order to + build extensions with MetroWerks compiler for Win32. [Bug: 2385] + + * generic/tclCmdMZ.c: + * generic/tclIO.c: Fix ANSI-style prototypes based on patch from + Ulrich Ring. [Bug: 2391] + + * unix/Makefile.in: Need to make install-sh executable before + calling (with chmod +x). [Bug: 2413] + + * tests/var.test: + * generic/tclVar.c: Fixed bug that caused a seg. fault when using + "array set a(b) {}", which is a bad array name anyway. Now the + "array set" command will return an error in this case. Added test + case and fixed existing test. [Bug: 2427] + +1999-07-21 + + * tests/info.test: + * generic/tclParse.c: Applied patch to fix "info complete" + for the string {[a [b]}. Patch from Peter Spjuth. [Bug: 2382] + + * doc/Utf.3: + * generic/tcl.decls: + * generic/tclDecls.h: + * generic/tclUtf.c: Changed function declarations in + non-platform-specific public APIs to use "unsigned long" instead of + "size_t", which may not be defined on certain compilers (rather + than include sys/types.h, which may not exist). + + * unix/Makefile.in: Added the Windows configure script to the + distribution file list, already shipping configure.in and the .m4 + files, but needed the configure script itself. + + * win/makefile.vc: Changed version number of DDE package in VC++ + makefile to use 1.1 instead of 1.0. + + * doc/open.n: Added documentation of \\.\comX notation for opening + serial ports on Windows (alternative to comX:). + + * tests/ioCmd.test: + * doc/open.n: + * win/tclWinSerial.c: Applied patch from Rolf Schroedter to add + -pollinterval option to fconfigure to modify the maxblocktime used + in the fileevent polling. Added documentation and fixed the test + case as well. + + * win/tclWinSock.c: Modified 8.1.0 version of the Win32 socket + driver to move the handling of the socket event window in a + separate thread. It also turned out that Win95 & Win98 were, in + some cases, getting multiple FD_ACCEPTs but only handling one. + Added a count for the FD_ACCEPT to take care of this. Tested on + NT4 SP3, NT4 SP4, Win95, and Win98. + [Bug: 2178 2256 2259 2329 2323 2355] + +1999-07-21 + + * README: Small tweaks to clean up typos and wording. + +1999-07-20 Melissa Hirschl + + * generic/tclInitScript.h: + * unix/tclUnixInit.c: merged code with 8.0.5. We now use an + intermediate global tcl var "tclDefaultLibrary" to keep the + "tcl_library" var from being set by the default value in the + Makefile. Also fixed a bug in which caused the value of + TCL_LIBRARY env var to be ignored. + * unix/tclWinInit.c: just updated some comments. + +1999-07-19 Melissa Hirschl + + * library/http2.1/http.tcl: updated -useragent text to say version + 2.1. + +1999-07-16 + + * generic/tcl.decls: + * generic/tclDecls.h: + * generic/tclStubInit.c: Add Tcl_SetNotifier to stub table. + [Bug: 2364] + + * unix/aclocal.m4: + * unix/tcl.m4: Add check for Alpha/Linux to correct the IEEE + floating flag to the compiler, should be -mieee. Patch from Don + Porter. + + * tools/tcl.hpj.in: Change version number of .cnt file referenced + in .HPJ file. + +1999-07-15 + + * tools/tcl.wse.in: Fixed naming of target files for Windows. + +1999-07-14 + + * doc/re_syntax.n: Deleted sentence as suggested by Scott S. + +1999-07-12 + + * doc/re_syntax.n: Removed two notes to myself (oops), cleaned + up wording, fixed changebars, made two examples easier to read. + +1999-07-11 + + * win/makefile.vc: Since the makefile.vc should continue to work + while we're working out bugs/issues in the new TEA-style + autoconf/configure/gmake build mechanism for Windows, the version + numbers of the Tcl libraries need to remain in sync. Modified the + version numbers in the makefile to reflect the change to 8.2b1. + +1999-07-09 + + * win/configure.in: Eval DLLSUFFIX, LIBSUFFIX, and EXESUFFIX in + the configure script so that substitutions get expanded before + being placed in the Makefile. The "d" portion for debug libraries + and DLLs was not being set properly. + +1999-07-08 + + * tests/string.test: + * generic/tclCmdMZ.c: Fixed bug in string range bounds checking + code. + +1999-07-08 Jennifer Hom + + * doc/tcltest.n: + * library/tcltest1.0/tcltest.tcl: Removed -asidefromdir and + -relateddir flags, removed unused ::tcltest::dotests proc, cleaned + up implementation of core file checking, and fixed the code that + checks for 1-letter flag abbreviations. + +1999-07-08 + + * win/Makefile.in: Added tcltest target so runtest works + properly. Added missing names to the clean/distclean targets. + + * tests/reg.test: + * generic/rege_dfa.c: Applied fix supplied by Henry Spencer for + bug in DFA state caching under lookahead conditions. [Bug: 2318] + +1999-07-07 + + * doc/fconfigure.n: Clarified default buffering behavior for the + standard channels. [Bug: 2335] + +1999-07-06 + + * win/tclWinSerial.c: New implementation of serial port driver + from Rolf Shroedter (Rolf.Schroedter@dlr.de) that allows more than + one byte to be read from the port. Implemented using polling + instead of threads, there is a max. 10ms latency between checking the + port for file events. [Bug: 1980 2217] + +1999-07-06 + + * library/http2.0/http.tcl: Fixed the -timeout option so it + handles timeouts that occur during connection attempts to + hosts that are down (the only case that really matters!) + +1999-07-03 + + * doc/ChnlStack.3: + * generic/tcl.decls: + * generic/tclIO.c: Added a new variant of the "Trf patch" + from Andreas Kupres that adds new C APIs Tcl_StackChannel, + Tcl_UnstackChannel, and Tcl_GetStackedChannel. + +1999-07-03 + + * generic/tclNotify.c: + * unix/tclUnixNotfy.c: + * unix/tclXtTest.c: + * unix/tclXtNotify.c: + * win/tclWinNotify.c: + * mac/tclMacNotify.c: Added Tcl_SetNotifier and the associated + hook points in the notifiers to be able to replace the notifier + calls at runtime The Xt notifier and test program use this hook. + +1999-07-03 + + * generic/tclParse.c: Changed parsing of variable names to + allow empty array names. Now "$(foo)" is a variable reference! + Previous you had to use something like $::(foo), which is slower. + This change is requested by Jean-Luc Fontaine for his STOOOP + package. + +1999-07-01 + + * generic/tclCmdAH.c: + * generic/tclFCmd.c: Call TclStat instead of TclpStat in order to + allow Tcl_Stat hooks to work properly. + +1999-06-29 Jennifer Hom + + * library/tcltest1.0/pkgIndex.tcl: + * library/tcltest1.0/tcltest.tcl: + * doc/tcltest.n: + * tests/all.tcl: Added -preservecore, -limitconstraints, -help, + -file, -notfile, -relateddir and -asidefromdir flags to the + tcltest package along with exported proc + ::tcltest::getMatchingFiles. The documentation was modified to + match and all.tcl was modified to use the new functionality + instead of implementing -file itself. + +1999-06-28 + + * generic/tclIndexObj.c: + * doc/GetIndex.3: + * tests/binary.test: + * tests/winDde.test: Applied patch from Peter Hardie (with + changes) to fix problem with Tcl_GetIndexFromObj() when the key + being passed is the empty string. It used to match "" and return + TCL_OK, but it should have returned TCL_ERROR instead. Added test + case to "binary" and "dde" commands to check the behavior. Added + documentation note as well. + +1999-06-26 + + * win/tclWinDde.c: Applied patch from Peter Hardie to add poke + command to dde. Also rev'd version of dde package to 1.1. + [Bug: 1738] + +1999-06-25 Jennifer Hom + + * unix/Makefile.in: + * win/Makefile.in: + * library/tcltest1.0/pkgIndex.tcl: + * library/tcltest1.0/tcltest.tcl: + * library/tcltest1.0: Added initial implementation of the Tcl test + harness package. This package was based on the defs.tcl file that + was part of the tests directory. Reversed the way that tests were + evaluated to fix a problem with false passes. + + * doc/tcltest.n: Added documentation for the tcltest package. + + * tests/README: + * tests/defs.tcl: + * tests/all.tcl: Modified all test files (tests/*.test) and + all.tcl to use the new tcltest package and removed references to + the defs.tcl file. Modified the README file to point to the man + page for tcltest. + +1999-06-25 + + * tests/reg.test: + * generic/regexec.c: Fixed bugs in non-greedy quantifiers. + +1999-06-23 + + * doc/re_syntax.n: + * doc/switch.n: + * doc/lsearch.n: + * doc/RegExp.3: + * doc/regexp.n: + * doc/regsub.n: Moved information about syntax of 8.1 regular + expressions from regexp(n) manpage into new re_syntax(n) page. + Added pointers from other manpages to new re_syntax(n) page. + +1999-06-23 + + * unix/Makefile.in: Changed install-doc to install-man. + + * tools/uniParse.tcl: + * tools/uniClass.tcl: + * tools/README: + * tests/string.test: + * generic/regc_locale.c: + * generic/tclUniData.c: + * generic/tclUtf.c: + * doc/string.n: Updated Unicode character tables to reflect latest + Unicode 2.1 data. Also rationalized "regexp" and "string is" + definitions of character classes. + +1999-06-21 + + * unix/tclUnixThrd.c (TclpThreadCreate): Fixed memory leak where + thread attributes were not being released. [Bug: 2254] + +1999-06-17 + + * tests/regexp.test: + * generic/tclCmdMZ.c: + * generic/tclCmdIL.c: Changed to use new regexp interfaces. Added + -expanded, -line, -linestop, and -lineanchor switches to regsub. + + * doc/RegExp.3: Documented the new regexp interfaces and + the compile/execute flags. + + * generic/tclTest.c: + * generic/tclRegexp.h: + * generic/tclRegexp.c: + * generic/tcl.h: + * generic/tcl.decls: Renamed Tcl_RegExpMatchObj to + Tcl_RegExpExecObj and added a new Tcl_RegExpMatchObj that is + equivalent to Tcl_RegExpMatch. Added public macros for the regexp + compile/execute flags. Changed to store either an object pointer + or a string pointer in the TclRegexp structure. Changed to avoid + adding a reference to the object or copying the string. + + * generic/regcomp.c: lint + + * tests/reg.test: + * generic/regex.h: + * generic/regc_lex.c: Added REG_BOSONLY flag to allow Expect to + iterate through a string an only find matches that start at the + current position within the string. + +1999-06-16 + + * unix/configure.in: + * unix/Makefile.in: + * unix/tcl.m4: + * unix/aclocal.m4: Numerous build changes to make Tcl conform to the + proposed TEA spec + +1999-06-16 Melissa Hirschl + + * generic/tclVar.c (Tcl_VariableObjCmd): fixed premature increment + in loop that was causing out-of-bounds reads on array "varName". + +1999-06-16 + + * tests/execute.test: + * generic/tclExecute.c (TclExecuteByteCode): Fixed crash caused by + a bug in INST_LOAD_SCALAR1 where the scalar index was read as + a signed 1 byte value instead of unsigned. [Bug: 2243] + +1999-06-14 Melissa Hirschl + + * doc/StringObj.3 + * test/stringObj.test + * unix/Makefile.in + * win/Makefile.in + * win/makefile.vc + * generic/tclStringObj.c: + Merged String and Unicode object types. Added new functions to + the puplic API: Tcl_NewUnicodeObj, Tcl_SetUnicodeObj, + Tcl_GetUnicode, Tcl_GetUniChar, Tcl_GetCharLength, Tcl_GetRange, + Tcl_AppendUnicodeToObj. + +1999-06-09 + + * generic/tclUnicodeObj.c: Lots of cleanup and simplification. + Fixed several memory bugs. Added TclAppendUnicodeToObj. + + * generic/tclInt.h: Added declarations for various Unicode string + functions. + + * generic/tclRegexp.c: + * generic/tclCmdMZ.c: Changed to use new Unicode string interfaces + for better performance. + + * generic/tclRegexp.h: + * generic/tclRegexp.c: + * generic/tcl.h: + * generic/tcl.decls: Added Tcl_RegExpMatchObj and + Tcl_RegExpGetInfo calls to access lower level regexp API. These + features are needed by Expect. This is a preliminary + implementation pending final review and cleanup. + + * generic/tclCmdMZ.c: + * tests/string.test: Fixed bug where string map failed on null + strings. + + * generic/regexec.c: + * unix/tclUnixNotfy.c: lint + + * tools/genStubs.tcl: Changed to always write output in LF mode. + +1999-06-08 + + * win/tclWinSock.c: Rolled back to the 8.1.0 implementation + because of serious problems with the new driver. Basically no + incoming socket connections would be reported to a server port. + The 8.1.1 code needs to be redesigned and fixed correctly. + +1999-06-07 Melissa Hirschl + + * tests/string.test: + * generic/tclVar.c (Tcl_SetVar2Ex): + * generic/tclStringObj.c (Tcl_AppendObjToObj): + * generic/tclCmdMZ.c (Tcl_StringObjCmd): optimized the string + index, string length, string range, and append command in cases + where the object's internal rep is a bytearray. Objects with + other internal reps are converted to have the new unicode internal + rep. + + * unix/Makefile.in: + * win/Makefile.in: + * win/Makefile.vc: + * tests/unicode.test: + * generic/tclInt.h: + * generic/tclObj.c: + * generic/tclUnicodeObj.c: added a new object type to store the + unicode representation of a string. + + * generic/tclTestObj.c: added the objtype option to the testobj + command. This option returns the name of the type of internal rep + an object has. + +1999-06-04 + + * win/configure.in: + * win/Makefile.in: Windows build now handles static/dynamic + debug/nodebug builds and supports the standard targets using + Cygwin user tools plus GNU make and autoconf. + +1999-06-03 + + * generic/tclCmdMZ.c (Tcl_StringObjCmd): + * tests/string.test: Fixed bug where string equal/compare -nocase + reported wrong result on null strings. [Bug: 2138] + +1999-06-02 + + * generic/tclUtf.c (Tcl_UtfNcasecmp): Fixed incorrect computation + of relative ordering. [Bug: 2135] + +1999-06-01 + + * unix/configure.in: Fixed various small configure.in patches + submitted by Jan Nijtmans. [Bug: 2121] + + * tests/reg.test: + * generic/regc_color.c: + * generic/regc_cvec.c: + * generic/regc_lex.c: + * generic/regc_locale.c: + * generic/regc_nfa.c: + * generic/regcomp.c: + * generic/regcustom.h: + * generic/rege_dfa.c: + * generic/regerror.c: + * generic/regerrs.h: + * generic/regex.h: + * generic/regexec.c: + * generic/regfree.c: + * generic/regfronts.c: + * generic/regguts.h: + * generic/tclCmdMZ.c: + * generic/tclRegexp.c: + * generic/tclRegexp.h: + * generic/tclTest.c: Applied Henry Spencer's latest regexp patches + that fix an infinite loop bug and add support for testing whether + a string could match with additional input. [Bug: 2117] + +1999-05-28 + + * generic/tclObj.c: Changed to eliminate use of isupper/tolower in + favor of the Unicode versions. + + * win/Makefile.in: + * win/configure.in: Added preliminary TEA implementation. + + * win/tclWinDde.c: Fixed bug where dde calls were being passed an + invalid dde handle because Initialize had not been called. + [Bug: 2124] + +1999-05-26 + + * generic/tclThreadTest.c: Fixed race condition in testthread + code that showed up in the WinNT test suite intermittently. + + * win/tclWinSock.c: Fixed a hang in the WinNT socket driver, wake + up the socket thread every 100ms to check for events on the + sockets that did not wake up the thread (race condition). + +1999-05-24 + + * tools/genStubs.tcl: Changed to allow a list of platforms instead + of just one at a time. + + * generic/tcl.decls: + * generic/tclCmdMZ.c: + * generic/tclDecls.h: + * generic/tclInt.decls: + * generic/tclIntDecls.h: + * generic/tclPort.h: + * generic/tclStubInit.c: + * generic/tclStubLib.c: Various header file related changes and other + lint to try to get the Mac builds working. + +1999-05-21 + + * win/tclWinPipe.c: Fix bug when launching command.com on + Win95/98. Need to wait for the procInfo.hProcess of the process that + was created, not the hProcess of the current process. [Bug: 2105] + +1999-05-20 + + * library/init.tcl: Add the directory where the executable is, and + the ../lib directory relative to that, to the auto_path variable. + +1999-05-19 + + Merged in various changes submitted by Jeff Hobbs: + + * generic/tcl.decls: + * generic/tclUtf.c: Added Tcl_UniCharIs* functions for control, + graph, print, and punct classes. + + * generic/tclUtil.c: + * doc/StrMatch.3: Added Tcl_StringCaseMatch() implementation to + support case-insensitive globbing. + + * doc/string.n: + * unix/mkLinks: + * tests/string.test: + * generic/tclCmdMZ.c: Added additional character class tests, + added -nocase switch to "string match", changed string first/last + to use offsets. + +1999-05-19 + + * generic/tcl.h: Add extern "C" block around entire header file for + C++ compilers to fix linkage issues. Submitted by Don Porter and + Paul Duffin. + + * generic/tclRegexp.c: Fix bug when the regexp cache is empty + and an empty pattern is used in regexp ( such as {} or "" ). + +1999-05-18 + + * win/tclWinChan.c: Modified initialization code to avoid + inherenting closed or invalid channels. If the standard input is + anything other than a console, file, serial port, or pipe, then we + fall back to the standard Tk window console. + +1999-05-14 + + * generic/tclCmdAH.c (Tcl_ForObjCmd): Fixed crash caused by + failure to reset the result before evaluating the test + expression. + +1999-05-14 + + * generic/tclBasic.c (Tcl_CreateInterp): Added introspection + variable for threaded interps. If the interp was compiled with + threads enabled, the tcl_platform(threaded) variable will exist. + +1999-05-14 + + * generic/tclDate.c: Applied patch to fix 100-year and 400-year + boundaries in leap year code, from Isaac Hollander. [Bug: 2066] + +1999-05-13 + + * unix/Makefile.in: + * unix/tclAppInit.c: Minor cleanup related to Xt notifier. + + * unix/tclUnixInit.c (TclpSetInitialEncodings): Tcl now looks for + an encoding subfield in the LANG/LC_ALL variables in cases where + the locale is not found in the locale table. Ensure that + setlocale() is called at least once so X11 will initialize + properly. Also, forces the LC_NUMERIC locale to be "C" so numeric + processing in scripts is not affected by the current locale + setting. [Bug: 1989] + + * generic/tclRegexp.c: Increased per-thread regexp cache to 30 + slots. This seems to be about the right number for larger + applications like exmh. [Bug: 1063] + +1999-05-12 + + * doc/tclsh.1: Updated references to rc script names to accurately + reflect the platform differences on Windows. + + * tests/regexp.test: + * generic/tclInt.h: + * generic/tclBasic.c: + * generic/tclRegexp.h: + * generic/tclRegexp.c: Replaced the per-interpreter regexp cache + with a per-thread cache. Changed the Regexp object to take + advantage of this extra cache. Added a reference count to the + TclRegexp type so regexps can be shared by multiple objects. + Removed the per-interp regexp cache from the interpreter. Now + regexps can be used with no need for an interpreter. [Bug: 1063] + + * win/tclWinInit.c (TclpSetVariables): Avoid calling GetUserName + if the value can be determined from the USERNAME environment + variable. GetUserName is very slow. + +1999-05-07 + + * win/winDumpExts.c: + * win/makefile.vc: Removed incorrect patch. [Bug: 1998] + + * generic/tcl.decls: Replaced const with CONST. + + * generic/tclResult.c (Tcl_AppendResultVA): + * generic/tclStringObj.c (Tcl_AppendStringsToObjVA): Fixed to copy + arglist using memcpy instead of assignment so it works properly on + OS/390. [Bug: 1997] + + * generic/tclLoadNone.c: Updated to use current interfaces, added + TclpUnloadFile. [Bug: 2003] + + * win/winDumpExts.c: + * win/makefile.vc: Changed to emit library name in defs + file. [Bug: 1998] + + * unix/configure.in: Added fix for OS/390. [Bug: 1976] + +1999-05-06 + + * tests/string.test: + * generic/tclCmdMZ.c: + * doc/string.n: Fixed bug in string equal/compare code when using + -length option. Cleaned up docs a bit more. + + * tests/http.test: Unset "data" array before running tests to + avoid failures due to previous tests. + + * doc/string.n: + * tests/cmdIL.test: + * tests/cmdMZ.test: + * tests/error.test: + * tests/ioCmd.test: + * tests/lindex.test: + * tests/linsert.test: + * tests/lrange.test: + * tests/lreplace.test: + * tests/string.test: + * tests/cmdIL.test: + * generic/tclUtil.c: + * generic/tclCmdMZ.c: Replaced "string icompare/iequal" with + -nocase and -length switches to "string compare/equal". Added a + -nocase option to "string map". Changed index syntax to allow + integer or end?-integer? instead of a full expression. This is + much simpler with safeTcl scripts since it avoids double + substitution issues. + + * doc/Utf.3: + * generic/tclStubInit.c: + * generic/tclDecls.h: + * generic/tclUtf.c: + * generic/tcl.decls: Added Tcl_UtfNcmp and Tcl_UtfNcasecmp. + +1999-05-05 + + * win/makefile.vc: Added encoding directory to install-libraries + target. + +1999-05-03 + + * doc/string.n: + * tests/cmdMZ.test: + * tests/string.test: + * generic/tclCmdMZ.c (Tcl_StringObjCmd): Changed "string length" + to avoid regenerating the string rep of a ByteArray object. + + * tests/cmdIL.test: + * tests/cmdMZ.test: + * tests/error.test: + * tests/lindex.test: + * tests/linsert.test: + * tests/lrange.test: + * tests/lreplace.test: + * tests/string.test: + * generic/tclCmdMZ.c (Tcl_StringObjCmd): + * generic/tclUtil.c (TclGetIntForIndex): Applied Jeff Hobbs's + string patch which includes the following changes [Bug: 1845]: + + - string compare now takes optional length arg (for strncmp + behavior) + + - added string equal (just a few lines of code blended + in with string compare) + + - added string icompare/iequal for case-insensitive comparisons + + - string index's index can now be ?end[+-]?expression + I made this change in the private TclGetIntForIndex, + which means that the list commands also benefit, as + well as string range, et al. + + - added [string repeat string count] + Repeats given string number of times + + - added string replace, string equiv to lreplace + (quasi opposite of string range): + string replace first last ?string? + Example of use, replacing end of string with ... + should the string be more than 16 chars long: + string replace $string 16 end "..." + This just returns the string len < 16, so it + will only affect the long strings. + + - added optional first and last args to string to* + This allows you to just affect certain regions of + a string with the command (like just capping the + first letter). I found the original totitle to + be too draconian to be useful. + + - added [string map charMap string] + where charMap is a {from to from to} list that equates to + what one might get from [array get]. Each and + can be multiple chars (or none at all). For Tcl/CGI users, + this is a MAJOR speed booster. + + * generic/tclParse.c (Tcl_ParseCommand): Changed to avoid + modifying eval'ed strings that are already null terminated. + [Bug: 1793] + + * tests/binary.test: + * generic/tclBinary.c (DupByteArrayInternalRep): Fixed bug where + type was not being set in duplicated object. [Bug: 1975, 2047] + +1999-04-30 + + * Changed version to 8.1.1. + +1999-04-30 + + * Merged changes from 8.1.0 branch: + + * generic/tclParse.c: Fixed memory leak in CommandComplete. + + * generic/tclPlatDecls.h: + * generic/tclIntPlatDecls.h: + * generic/tclIntDecls.h: + * generic/tclDecls.h: + * tools/genStubs.tcl: Added 'extern "C" {}' block around the stub + table pointer declaration so the stub library can be used from + C++. [Bug: 1934] + + * Lots of documentation and other release engineering fixes. + +1999-04-28 + + * mac/tclMacResource.c: + * generic/tclListObj.c: + * generic/tclObj.c: + * generic/tclStringObj.c: Changed to avoid freeing the string + representation before freeing the internal rep. This helps with + debugging since the string rep will still be valid when the free + proc is invoked. + +1999-04-27 + + * generic/tclLiteral.c (TclHideLiteral): Fixed so hidden literals + get duplicated to avoid accidental sharing in the global object + table. + +1999-04-23 + + * generic/tclStubInit.c: + * tools/genStubs.tcl: Changed to avoid the need for forward + declarations in stub initializers. + +1999-04-23 + + * library/encoding/koi8-r.enc: + * tools/encoding/koi8-r.txt: Added support for the koi8-r Cyrillic + encoding. [Bug: 1771] + +1999-04-22 + + * win/tclWinFCmd.c: + * win/tclWin32Dll.c: Changed uses of "try" to "__try", since that + is the actual keyword. This eliminates the need for some -D flags + from the makefile. + + * generic/tclPort.h: Added include of tcl.h since it defines + various Windows macros that are needed before deciding which + platform porting file to use. + + * generic/tclEvent.c: lint + + * win/tclWinInit.c (TclpInitPlatform): Added call to TclWinInit + when building a static library since DllMain will not be invoked. + This could break old code that explicitly called TclWinInit, but + should be simpler in the long run. + +1999-04-22 Scott Stanton + + * generic/tclInt.h: + * generic/tclInt.decls: + * generic/tclCompile.c: Added TclSetByteCodeFromAny that takes a + hook procedure to invoke after compilation but before the byte + codes are emitted. This makes it possible to do postprocessing on + the compiled byte codes before the ByteCode is generated. + + * generic/tclLiteral.c: Added TclHideLiteral and TclAddLiteralObj + to make it possible to create local unshared literal objects. + + * win/tclWinInit.c: + * unix/tclUnixInit.c: Changed initial search path to match that + found used by tcl_findLibrary. + +1999-04-22 + + * win/tclWinPort.h: + * win/tclWinSock.c: Added code to use WinSock 2.0 API on NT to + avoid creating a window to handle sockets. API not available on + Win95 and needs to be fixed on Win98, until then continue to use + the older (window-based) scheme on those two OSes. + +1999-04-15 + + * Merged 8.1 back into the main trunk + +1999-04-13 + + * library/encoding/gb2312.enc: + * library/encoding/euc-cn.enc: + * tools/encoding/gb2312.txt: + * tools/encoding/cp950.txt: + * tools/encoding/Makefile: Restored the double byte definition of + GB2312 and added the EUC-CN encoding. EUC-CN is a variant of + GB2312 that shifts the characters into bytes with the high bit set + and includes ASCII as a subset. [Bug: 632] + +1999-04-13 + + * win/tclWinSock.c: Apply patch to allow write access to a socket + if FD_WRITE is sent but FD_CONNECT is not. Some strange problem + with either Win32 or a socket driver. [Bug: 1664 1776] + +1999-04-09 + + * unix/tclUnixNotfy.c: Fixed notifier deadlock situation when the + pipe used to talk back notifier thread is filled with data. When + calling the write() function to feed data down that pipe, unlock + the notifierMutex to allow the notifier to wake up again. Found + as a result of the focus.test for Tk hanging. [Bug: 1700] + +1999-04-06 + + * tests/unixNotfy.test: Fixed hang in tests when built with thread + support. + + * tests/httpold.test: Fixed broken test that didn't wait long + enough for events to arrive. + + * tests/unixInit.test: Fixed race condition in test. + + * tests/unixInit.test: + * tests/fileName.test: Minor test nits. + + * unix/tclUnixInit.c (TclpSetInitialEncodings): Fixed bad initial + encoding string. + +1999-04-06 + + * generic/tclVar.c: + * generic/tclEnv.c: Moved the "array set" C level code into a + common routine (TclArraySet). The TclSetupEnv routine now uses + this API to create an env array w/ no elements. + + * generic/tclEnv.c: + * generic/tclWinInit.h: + * generic/tclUnixInit.h: + * generic/tclInt.h: Made the Env module I18N compliant. Changed the + FindVariable routine to TclpFindVariable, that now does a case + insensitive string comparison on Windows, and not on UNIX. [Bug: + 1299, 1500] + +1999-04-05 + + * tests/io.test: Minor test cleanup. + + * generic/tclEncoding.c (Tcl_CreateEncoding): Minor lint to make + it easier to compile on Digital-unix. [Bug: 1659] + + * unix/configure.in: + * unix/tclUnixPort.h: Applied patch for OS/390 to handle lack of + sys/param.h. [Bug: 1725] + + * unix/configure.in: Fixed BSD/OS 4.* configuration to support + shared libraries properly. [Bug: 1730] + +1999-04-05 + + * win/tclWinDde.c: decrease timeout value for DDE calls to 30k + [Bug: 1639] + + * generic/tcl.decls: + * generic/tcl.h: + * generic/tclDecls.h: + * generic/tclInt.decls: + * generic/tclInt.h: + * generic/tclIntDecls.h: + * generic/tclStubInit.c: + * generic/tclUtil.c: Added more functions to the Tcl stubs table, + including all Tcl_ functions not already in it (except Cmd + functions) and Tcl_GetCwd() and Tcl_Chdir() (new functions). + + * tests/safe.test: + * doc/safe.n: + * generic/tclBasic.c: + * library/safe.tcl: The encoding command is not safe as-is, so + create a safe alias to mask out the "encoding system " but + allow all other uses including "encoding system". Added test cases + and updated the man page for Safe Tcl. + +1999-04-05 + + * tests/winTime.test: + * win/tclWinTime.c: Fixed crash in clock command that occurred + when manipulating negative time values in timezones east of + GMT. [Bug: 1142, 1458] + + * tests/platform.test: + * tests/fileName.test: Fixed broken tests. + + * generic/tclFileName.c: Moved global regexps into thread local + storage. + + * tests/socket.test: Changed so tests don't reuse sockets, + since Windows is slow to release sockets. + + * win/tclWinConsole.c: + * win/tclWinPipe.c: + * win/tclWinSerial.c: Fixed race condition where background + threads were terminated while they still held a lock in the + notifier. + +1999-04-02 + + * tests/http.test: Fixed bad test initialization code. + + * generic/tclThreadTest.c (ThreadExitProc): Fixed bug where static + memory was being returned instead of a dynamically allocated + result in error cases. + +1999-04-02 + + * doc/dde.n: + * tools/tcl.wse.in: + * win/makefile.vc: + * win/pkgIndex.tcl: + * win/tclWinDde.c: Add new DDE package, code removed from Tk now + separated into its own package. Changed DDE-based send code into + "dde eval" command. Can be loaded into tclsh (not just wish). + Windows only. + +1999-04-02 + + * tests/expr.test: + * tests/for-old.test: + * tests/for.test: + * tests/foreach.test: + * tests/format.test: + * tests/httpold.test: + * tests/if.test: + * tests/init.test: + * tests/interp.test: + * tests/while.test: Added some tests for known bugs (marked with + knownBug constraint), and cleaned up a few bad tests. + + * generic/regc_locale.c: + * generic/regcustom.h: + * generic/tcl.decls: + * generic/tclCmdIL.c: + * generic/tclCmdMZ.c: + * generic/tclInt.h: + * generic/tclRegexp.c: + * generic/tclScan.c: + * generic/tclTest.c: + * generic/tclUtf.c: + * win/tclWinFCmd.c: + * win/tclWinFile.c: Made various Unicode utility functions + public. The following functions were made public and added to the + stubs table: + Tcl_UtfToUniCharDString, Tcl_UniCharToUtfDString, + Tcl_UniCharLen, Tcl_UniCharNcmp, Tcl_UniCharIsAlnum, + Tcl_UniCharIsAlpha, Tcl_UniCharIsDigit, Tcl_UniCharIsLower, + Tcl_UniCharIsSpace, Tcl_UniCharIsUpper, Tcl_UniCharIsWordChar + +1999-04-01 + + * tests/registry.test: + * win/tclWinReg.c: Internationalized the registry code. It now + uses Unicode interfaces on NT. [Bug: 1197] + + * tests/parse.test: + * generic/tclParse.c: Fixed crash due to multiple frees in parser + during error cleanup when parsing commands with more tokens than + will fit in the static area of the parse structure. [Bug: 1681] + + * generic/tclInt.h: Removed duplicate declarations. + + * generic/tclInt.decls: + * generic/tcl.decls: Added Tcl_WinUtfToTChar and Tcl_WinTCharToUtf + to the tclPlat table. + +1999-04-01 + + * generic/tcl.decls: + * generic/tcl.h: + * generic/tclBasic.c: + * generic/tclDecls.h: + * generic/StubInit.c: + * tools/genStubs.tcl: + * unix/Makefile.in: + * win/makefile.vc: Applied patch from Jan Nijtmans to fix Ultrix + multiple symbol definition problem. Now, even Tcl includes a copy + of the Tcl stub library. Also fixed TCL_MEM_DEBUG mode (for Tk). + +1999-03-31 + + * win/tclWinConsole.c: WinNT has a bug when reading a single + character from the console. Rewrote the code for the console to + read an entire line at a time using the reader thread. + +1999-03-30 + + * unix/Makefile.in: Removed trailing backslash that broke the + "depend" target. + + * unix/tclUnixInit.c (TclpSetInitialEncodings): Changed to avoid + calling setlocale(). We now look directly at env(LANG) and + env(LC_CTYPE) instead. [Bug: 1636] + + * generic/tclFileName.c: + * generic/tclDecls.h: + * generic/tcl.decls: Removed CONST from Tcl_JoinPath and + Tcl_TranslateFileName because it changes the signature of + Tcl_JoinPath in an incompatible manner. + + * generic/tclInt.h: + * generic/tclLoad.c (TclFinalizeLoad): + * generic/tclEvent.c (Tcl_Finalize): Defer unloading of loadable + modules until all exit handlers have been invoked. + [Bug: 998, 1273, 1573, 1593] + +1999-03-29 + + * generic/tclFileName.c: + * generic/tclDecls.h: + * generic/tcl.decls: Added CONST to Tcl_JoinPath and + Tcl_TranslateFileName. + +1999-03-29 + + * tools/genStubs.tcl: + * unix/configure.in: + * unix/Makefile.in: + * win/makefile.vc: + * generic/tcl.h: + * generic/tclBasic.c: + * generic/tclDecls.h: + * generic/tclIntDecls.h: + * generic/tclPlatDecls.h: + * generic/tclIntPlatDecls.h: Removed the stub functions and + changed the stub macros to just use the name without params. Pass + &tclStubs into the interp (don't use tclStubsPtr because of + collisions with the stubs on Solaris). + +1999-03-27 + + * win/makefile.bc: Removed makefile for Borland compiler, no + longer supported. + +1999-03-26 + + * win/tclWinSerial.c: + * win/tclWinConsole.c: + * win/tclWinPipe.c: Don't close the Win32 handle for a channel if + it's a stdio handle (GetStdHandle()) during shutdown of a thread + to prevent it from destroying the stdio of other threads. + +1999-03-26 + + * unix/configure.in + --nameble-shared is now the default and build Tcl as a shared + library; specify --disable-shared to build a static Tcl library + and shell. + +1999-03-25 + + * tests/interp.test: + * generic/tclInterp.c (AliasObjCmd): Changed so aliases are + invoked at current scope in the target interpreter instead of at + the global scope. This was an incompatibility introduced in 8.1 + that is being removed. [Bug: 1153, 1556] + + * library/encoding/big5.enc: + * library/encoding/gb2312.enc: + * tools/encoding/big5.enc: + * tools/encoding/gb2312.enc: Added ASCII to big5 and gb2312 + encodings. [Bug: 632] + + * generic/tclPkg.c (Tcl_PkgRequireEx): Fixed broken clientData + initialization in package code. + + * unix/Makefile.in (dist): Added tcl.decls and tclInt.decls to + source distribution. [Bug: 1571] + + * doc/Thread.3: Updated documentation of Tcl_MutexLock to indicate + that the recursive locking behavior is undefined. On Windows, it + does not block, on Unix it deadlocks. [Bug: 1275] + +1999-03-24 + + * tests/execute.test: + * generic/tclExecute.c (TclExecuteByteCode): Fixed expression code + that incorrectly returned floating point values for integers if + the internal rep happened to be a double. Now we check to see if + the object has a string rep that looks like an integer before + using the double internal rep. [Bug: 1516] + +1999-03-24 + + * generic/tclAlloc.c: + * generic/tclEncoding.c: + * generic/tclProc.c: + * unix/tclUnixTime.c: + * win/tclWinSerial.c: Fixed compilation warnings/errors for VC++ + 5.0 and 6.0 and HP-UX native compiler without -Aa or -Ae. + [Bug: 1323 1518 1324 1583 1585 1586] + + * win/tclWinSock.c: Make sockets thread-safe on Windows. The + current implementation uses windows to handle events on the + socket, one for each thread (thread local storage). Previously, + there was only one window shared between threads, which didn't + work. [Bug: 1326] + +1999-03-23 + + * tools/tcl.wse: Fixed file association to look in the right place + for the wish icon. [Bug: 1544] + + * tests/winNotify.test: + * tests/ioCmd.test: + * tests/event.test: Changed to use new style conditionals. + + * tests/encoding.test: Fixed nonportable test. + + * unix/dltest/configure.in: + * unix/dltest/Makefile.in: Added missing DBGX macros. [Bug: 1564] + + * tests/winNotify.test: + * mac/tclMacNotify.c: + * win/tclWinNotify.c: + * unix/tclUnixNotfy.c: + * generic/tclNotify.c: Added a new Tcl_ServiceModeHook interface + that is invoked whenever the service mode changes. This is needed + to allow the Windows notifier to create a communication window the + first time Tcl is about to enter an external modal event loop + instead of at startup time. This will avoid the various problems + that people have been seeing where the system hangs when tclsh + is running outside of the event loop. [Bug: 783] + + * generic/tclInt.h: + * generic/tcl.decls: Renamed TclpAlertNotifier back to + Tcl_AlertNotifier since it is part of the public notifier driver + API. + +1999-03-23 + + * win/tclWinSerial.c: Fixed problem with fileevent on the serial + port and nonblocking mode. Gets no longer hangs, fileevents fire + whenever there is any character data on the port. + + * tests/winConsole.test: + * win/tclWinConsole.c: Fixed problem with fileevents and gets from + a console stdin. Previously, fileevents were firing before an + entire line was available for reading, which meant that when you + did a gets or read, it blocked (even in nonblocking mode). Now, it + should work the same as Unix: fileevents fire when an entire line + is ready, and gets and read do not block in non-blocking mode. + Added an interactive test case to check for this. + +1999-03-22 + + * tests/reg.test: + * generic/regc_color.c: Applied regexp bug fix from Henry Spencer. + +1999-03-19 + + * generic/tclCmdIL.c: Fixed the initialization of an array so that + the Sun 5.0 C compiler wouldn't complain. + + * unix/configure.in: Added support for --enable-64bit. For now, + this is only supported on Solaris 7 64bit (SunOS 5.7) using the Sun + compiler (not gcc). + +1999-03-18 + + * win/tclWinChan.c (TclpOpenFileChannel, Tcl_MakeFileChannel): + Changed to only test for console or comm handles when the type is + FILE_TYPE_CHAR to avoid useless tests on simple files. Also + reordered tests so consoles are tested first as this is more + common. + + * win/makefile.vc: Regularized usage of mkd and rmd and rm. + + * library/encoding/shiftjis.enc: + * tools/encoding/shiftjis.txt: Missing/incorrect characters in + shift-jis table. [Bug: 1008, 1526] + + * generic/tclInt.decls: + * generic/tcl.decls: Eliminated use of "string" and "list" from + argument lists to avoid conflicts with C++ STL. [Bug: 1181] + + * win/tclWinFile.c (TclpMatchFiles): Changed to ignore the + FS_CASE_IS_PRESERVED bit and always return exactly what we get + from the system. + +1999-03-17 + + * win/README.binary: + * win/README: + * unix/configure.in: + * generic/tcl.h: + * README: Updated version to 8.1b3. + +1999-03-14 + + * win/tclWinConsole.c: + * win/tclWinPipe.c: + * win/tclWinSerial.c: Changed so channel drivers wait for the + reader/writer threads to exit before returning during a close + operation. This ensures that the main thread is the last thread + to exit, so the process return value is set properly. + + * generic/tclIntDecls.h: + * generic/tclIntPlatDecls.h: + * generic/tclIntPlatStubs.c: + * generic/tclIntStubs.c: + * generic/tclPlatDecls.h: + * generic/tclPlatStubs.c: + * generic/tclStubInit.c: + * generic/tclStubs.c: Fixed bad eol characters. + + * generic/tclInt.decls: Changed "const" to "CONST" in + declarations for better portability. + + * generic/tcl.decls: Renamed panic and panicVA to Tcl_Panic and + Tcl_PanicVA in the stub files. + + * generic/tclInterp.c (Tcl_MakeSafe): Remove tcl_platform(user) + from safe interps. + +1999-03-11 + + * unix/Makefile.in: + * unix/configure.in: Include compat files in the stub library in + addition to the main library. Compat files are now built for + dynamic use in all cases. + + * generic/tcl.h: Changed magic number so it doesn't match the plus + patch, at Jan's request. + + * unix/tclConfig.sh.in: + * unix/dltest/Makefile.in: + * unix/dltest/configure.in: + * unix/dltest/pkga.c: + * unix/dltest/pkgb.c: + * unix/dltest/pkgc.c: + * unix/dltest/pkgd.c: + * unix/dltest/pkge.c: + * unix/dltest/pkgf.c: Changed package tests to build against the + stubs library. + +1999-03-10 + + * generic/tcl.h: + * generic/tcl.decls: Changed Tcl_ReleaseType from an enum to + macros so it can be used in .rc files. + Added Tcl_GetString. + + * mac/tclMacNotify.c: + * generic/tclNotify.c: + * generic/tclInt.h: + * win/tclWinNotify.c: + * generic/tcl.h: Renamed Tcl_AlertNotifier to TclpAlertNotifier. + + * generic/tclInt.decls: Added TclWinAddProcess to make it possible + for expect to use Tcl_WaitForPid(). This patch is from Gordon + Chaffee. + + * mac/tclMacPort.h: + * win/tclWinInit.c: + * unix/tclUnixPort.h: + * generic/tclAsync.c: Added TclpAsyncMark to fix bug in async + handling on Windows where async events don't wake up the event + loop. This patch comes from Gordon Chaffee. + + * generic/tcl.decls: Fixed declarations of reserved slots. + +1999-03-10 + + * generic/tclCompile.h: Ensure that the ByteCode struct is binary + compatible with the version in 8.0.6. + + * generic/tcl.h: + * generic/tclBasic.c: Add Tcl_GetVersion() function to the public + C API to allow programs to check the version number of the Tcl + library at runtime. Also added an enum to clarify the release + level (alpha, beta, final). + +1999-03-09 + + * Integrated changes from Tcl 8.0 including: + stubs mechanism + configure patches from Jan Nijtmans + rename of panic to Tcl_Panic + +1999-03-08 + + * win/tclWin32Dll.c: Removed Dll instance from thread-local + storage. + +1999-03-08 + + * generic/tcl.h: Moved Tcl_Mutex, etc. macros above the inclusion + of tclDecls.h to avoid macro conflicts. + + * generic/tclInt.h: + * generic/regc_color.c: + * generic/regcomp.c: + * generic/tclCmdIL.c: + * generic/tclCmdAH.c: + * generic/tclIOCmd.c: + * generic/tclParse.c: + * generic/tclStringObj.c: + * unix/tclUnixNotfy.c: Cleaned up various compiler warnings, + eliminated UCHAR bugs. + + * unix/tclUnixNotfy.c: + * unix/tclUnixThrd.c: + * generic/tclThreadTest.c: + * mac/tclMacThrd.c: Changed TclpCondition*() to Tcl_Condition*(). + + * INTEGRATED PATCHES FROM 8.0.6: + + * generic/tcl.decls: + * generic/tcl.h: + * generic/tclBasic.c: + * generic/tclDecls.h: + * generic/tclInt.decls: + * generic/tclInt.h: + * generic/tclIntDecls.h: + * generic/tclIntPlatDecls.h: + * generic/tclIntPlatStubs.c: + * generic/tclIntStubs.c: + * generic/tclPlatDecls.h: + * generic/tclPlatStubs.c: + * generic/tclStubInit.c: + * generic/tclStubLib.c: + * generic/tclStubs.c: + * tools/genStubs.tcl: + * unix/configure.in: + * unix/Makefile.in: + * unix/tclConfig.sh.in: + * win/makefile.vc: + * win/tclWinPort.h: Added Tcl stubs implementation. There are + now two new macros USE_TCL_STUBS and USE_TCL_STUB_PROCS that + enable use of stubs and disable stub macros respectively. All of + the public and private function declarations from tcl.h and + tclInt.h have moved into the *.decls files and the *Stubs.c and + *Decls.h files are generated using the genStubs.tcl script. + + * unix/Makefile.in: + * unix/configure.in: + * unix/ldAix: Enhanced AIX shared library support. + + * win/tclWinSock.c: Removed a bunch of extraneous PASCAL FAR + attributes from internal functions. + + * win/tclWinReg.c: Changed registry package to use stubs mechanism + so it no longer depends on the specific version of Tcl. + + * doc/AddErrInfo.3: + * doc/Eval.3: + * doc/PkgRequire.3: + * doc/SetResult.3: + * doc/StringObj.3: + * generic/tcl.h: + * generic/tclBasic.c: + * generic/tclPanic.c: + * generic/tclStringObj.c: + * generic/tclUtil.c: + * unix/mkLinks: Added va_list versions of all VARARGS + functions so they can be invoked from the stub functions. + + * doc/package.n: + * doc/PkgRequire.3: + * generic/tclPkg.c: Added Tcl_PkgProvideEx, Tcl_RequireEx, + Tcl_PresentEx, and Tcl_PkgPresent. Added "package present" + command. + + * generic/tclFileName.c: + * mac/tclMacFile.c: + * mac/tclMacShLib.exp: + * unix/tclUnixFile.c: + * win/tclWinFile.c: Changed so TclGetUserHome is defined on + all platforms, even though it is currently a noop on mac and + windows, and renamed it to TclpGetUserHome. + + * generic/tclPanic.c: + * generic/panic.c: Renamed panic to Tcl_Panic. + +1999-02-25 + + * win/makefile.vc: Added tclWinConsole.c and tclWinSerial.c + + * win/tclWinConsole.c: New code to properly deal with fileevents + and nonblocking mode on consoles. + + * win/tclWinSerial.c: New code to properly deal with fileevents + and nonblocking mode on serial ports. + + * win/tclWinPipe.c: + * win/tclWinPort.h: Exported functions to allow creation of pipe + channels from tclWinChan.c + + * win/tclWinChan.c: Check the type of a channel, including for the + standard (stdin/stdout/stderr), and use the correct channel type + to create the channel (file, serial, console, or pipe). + +1999-02-11 + + * README: + * generic/tcl.h: + * win/README.binary: + * win/README: + * unix/configure.in: + * mac/README: Updated version numbers to 8.1b2. + +1999-02-10 + + * library/auto.tcl: Fixed auto_mkindex so it handles .tbc files. + Did some general cleanup to handle bad eval statements that didn't + use "list". + + * unix/mkLinks: + * doc/SetVar.3: + * generic/tcl.h: + * generic/tclVar.c: Restored Tcl_ObjGetVar2 and Tcl_ObjSetVar2 + from 8.0. Renamed Tcl_Get/SetObjVar2 to Tcl_GetVar2Ex and + Tcl_SetVar2Ex. + +1999-02-10 + + INTEGRATED PATCHES FROM 8.0.5b2: + + * test/winPipe.test: Changed to remove echoArgs.tcl temporary file + when done. + + * tests/cmdAH.test: + * generic/tclFileName.c (TclGetExtension): Changed behavior so the + split happens at the last period in the name instead of the first + period of the last run of periods. So, "foo..o" is split into + "foo." and ".o" now. [Bug: 1126] + + * win/makefile.vc: Added better support for paths with spaces in + the name. Added .lib and support .dlls to the install-binaries + target. Added generate of a pkgIndex.tcl script to the + install-libraries target. + + * win/tclAppInit.c: + * unix/tclAppInit.c: + * mac/tclMacAppInit.c: + * generic/tclTest.c: Changed some EXTERN declarations to extern + since they are not defining exported interfaces. This avoids + generating useless declspec() attributes and makes the windows + makefile simpler. + + * generic/tcl.h: Moved Tcl_AppInit declaration to end and cleared + out TCL_STORAGE_CLASS so it is not declared with a declspec(). + + * tests/interp.test: + * generic/tclInterp.c (DeleteAlias): Changed to use + Tcl_DeleteCommandFromToken so we handle renames properly. This + avoids senseless panic. [Bug: 736] + + * unix/tclUnixChan.c: + * win/tclWinSock.c: + * doc/socket.n: Applied Gordon Chaffee's patch to handle failures + during asynchronous socket connection operations. This adds a new + "-error" fconfgure option to socket channels. [Bug: 893] + + * generic/tclProc.c: + * generic/tclNamesp.c: + * generic/tclInt.h: + * generic/tclCmdIL.c: + * generic/tclBasic.c: + * generic/tclVar.c: Applied patch from Viktor Dukhovni to + rationalize TCL_LEAVE_ERR_MSG behavior when creating variables. + + * generic/tclVar.c: Fixed bug in namespace tail computation. + Fixed bug where upvar could resurrect a namespace variable whose + namespace had been deleted. + + * generic/tclCompile.c (TclCompileExprCmd): Eliminated yet another + bogus optimization in expression compilation. + + * unix/configure.in: Added branch for BSD/OS-4* to shared library + case statement. [Bug: 975] + Fixed to correctly handle IRIX 6.5 n32 library support. [Bug: 1117] + + * win/winDumpExts.c: Patched to be pickier about stripping + @'s. [Bug: 920] + + * library/http2.0/http.tcl: Added catch around eof test in + CopyDone since the user may have already called http::reset. + [Bug: 1108] + + * unix/configure.in: Changed Linux and IRIX to set SHLIB_LIBS to + LIBS so shared libraries are linked with the system + libraries. [Bug: 1018] + + * generic/tclCompile.c (CompileExprWord): Fixed exception stack + overflow bug caused by missing statement. [Bug: 928] + + * generic/tclIOCmd.c: + * generic/tclBasic.c: Objectified the "open" command. [Bug: 1113] + + * generic/tclPosixStr.c (Tcl_ErrnoId, Tcl_ErrnoMsg): When using + egcs, ENOTSUP and EOPNOTSUPP are the same, so now we handle that + case. [Bug: 1137] + + * library/init.tcl: Various small changes requested by Jan Nijtmans. + - If the variable $tcl_library contains the empty string, this + empty string will be put in $auto_path. This is not useful at all, + it only slows down later package processing. + - If the variable tcl_pkgPath is not set, the "unset __dir" + fails. Thich makes init.tcl totally unusable. Better put a "catch" + around it. + - In the function tcl_findLibraries, the "string match" function + only works correctly if $tcl_patchLevel is in one of the forms + "?.?a?", "?.?b?" or "?.?.?". Could a "regexp" be used instead, + then it allows anything to be appended to the patchLevel + string. And it is more efficient. + - The tclPkgSetup function assumes that if $type != "load" then + the type must be "source". This needn't be true. Some users want + to add their own setup types. + [RFE: 1138] [Bug: 978] + + * win/tclWinReg.c: + * doc/registry.n: Added support for HKEY_PERFORMANCE_DATA and + HKEY_DYN_DATA keys. [Bug: 1109] + + * win/tclWinInit.c (TclPlatformInit): Added code to ensure + tcl_pkgPath is set to "" when no registry entry is found. [Bug: 978] + +1999-02-01 + + * generic/tclBasic.c: + * generic/tclCmdAH.c: + * generic/tclCmdIL.c: + * generic/tclCmdMZ.c: + * generic/tclExecute.c: + * generic/tclHistory.c: + * generic/tclIO.c: + * generic/tclIOUtil.c: + * generic/tclInterp.c: + * generic/tclMain.c: + * generic/tclNamesp.c: + * generic/tclParse.c: + * generic/tclProc.c: + * generic/tclTest.c: + * generic/tclTimer.c: + * generic/tcl.h: Made eval interfaces compatible with 8.0 by + renaming Tcl_EvalObj to Tcl_EvalObjEx, renaming Tcl_Eval2 to + Tcl_EvalEx and restoring Tcl_EvalObj and Tcl_GlobalEvalObj + interfaces so they match Tcl 8.0. + +1999-01-28 + + * Merged Tcl 8.0.5b1 changes. + + * generic/tclUtil.c (Tcl_DStringSetLength): Changed so the buffer + overallocates in a manner similar to Tcl_DStringAppend. This + should improve performance for TclUniCharToUtfDString. + +1998-12-11 === Tcl 8.1b1 Release === + +1998-12-10 + + * Fixed lots of files that used TCL_THREAD instead of TCL_THREADS. + + * generic/tclEncoding.c (Tcl_FreeEncoding): Moved most of the code + into a static FreeEncoding routine that does not grab the + encodingMutex to avoid deadlocks/races when called from other + routines that already have the mutex. + +1998-12-09 + + * library/msgcat1.0/msgcat.tcl: Fixed bad export list, fixed so + all locale strings are converted to lower case, including file + names. + + * generic/regcomp.c (makescan): Fixed bug in longest match case + that caused anchored patterns to fail. [Bug: 897] + +1998-12-08 + + * library/msgcat1.0/msgcat.tcl: changed mc to invoke mcunknown in + the calling context, changed locale lookups to be case insensitive + +1998-12-07 + + * generic/tclAlloc.c (TclpRealloc): Fixed a memory allocation bug + where big blocks that were reallocated into a different heap + location were not being placed into the bigBlocks list. [Bug: 933] + + * tests/msgcat.test: Added message catalog test suite. + + * library/msgcat1.0/msgcat.tcl: minor bug fixes, integrated latest + changes from Mark Harrison. + +1998-12-04 + + * library/msgcat1.0/msgcat.tcl: Changed code to conform to Tcl + coding standards. Changed to use file join for portability. + + * library/msgcat1.0: Added initial implementaion of Tcl message + catalog package contributed by Mark Harrison. + +1998-12-03 + + * win/tclWinPipe.c (BuildCommandLine): Fixed bug that kept + arguments containing spaces from being properly quoted. + + * tests/defs: Changed so auto_path is set to only contain the Tcl + library directory. This keeps the tests from accidentally picking + up stuff in installed packages. + + * generic/tclUtil.c (Tcl_StringMatch): Changed to match 8.0 + behavior in corner case where there is no closing bracket. + +1998-12-02 + + * win/tclWinPipe.c (TclpCreateCommandChannel): Changed + reader/writer threads to have THREAD_PRIORITY_HIGHEST so they will + have a chance to run whenever there is something to do. + + * generic/tclIO.c (WriteBytes, WriteChars): Fixed so extraneous + flushes do not happen in line mode. + (TranslateOutputEOL): Made translation more efficient in line mode + and fixed a buffer overflow bug in CRLF translation. [Bug: 887] + +1998-12-02 + + * Updated patchlevel to 8.1b1 + +1998-12-02 + + * generic/regc_color.c (subcolor): Added check for error case to + avoid an out of bounds array reference. + + * generic/tclCmdAH.c (Tcl_EncodingObjCmd): Changed to avoid using + Tcl_DStringResult because it is not binary clean. + + * generic/tclParse.c (Tcl_ParseCommand): Fixed bug in comment + parsing where a trailing comment looked like an incomplete + command. + +1998-12-02 + + * Merged changes from 8.0.4, especially the new pkg_mkIndex + +1998-12-01 + + * generic/tclIO.c (Tcl_ReadChars): Added a call to UpdateInterest + so we don't block when there is data sitting in the buffers. + + * generic/tclTest.c (TestevalobjvObjCmd): Updated for EvalObjv + change. + + * tests/parse.test: Updated tests for EvalObjv change. + + * generic/tclParse.c (EvalObjv, Tcl_EvalObjv): Changed + Tcl_EvalObjv interface to remove string and length arguments, + preserved original interface as EvalObjv for internal use. + + * generic/tcl.h: Changed Tcl_EvalObjv interface to remove string + and length arguments. + + * doc/Eval.3: Updated documentation for Tcl_EvalObjv to remove + string and length arguments. + + * generic/tclCompCmds.c (TclCompileForeachCmd): Fixed code that + corrupted the exceptDepth value in the compile environment when + foreach failed to compile inline. [Bug: 884] + + * library/encoding/euc-kr.enc: + * library/encoding/ksc5601.enc: + * tools/encoding/ksc5601.txt: + * unix/tclUnixInit.c: Added support for Korean EUC. + + * win/tclWinChan.c (TclpGetDefaultStdChannel): added check for a + failure during Tcl_MakeFileChannel. + +1998-11-30 + + * unix/tclUnixNotfy.c (Tcl_WaitForEvent): Fixed hang that occurs + when trying to close a pipe that is currently being waited on by + the notifier thread. [Bug: 607] + + * unix/tclUnixFCmd.c (GetPermissionsAttribute): Increase size of + returnString buffer to avoid overflow. [Bug: 584] + + * generic/tclThreadTest.c (TclThreadSend): Fixed memory leak due + to use of TCL_VOLATILE instead of TCL_DYNAMIC. + + * generic/tclThread.c (TclRememberSyncObject): Fixed memory leak + caused by failure to reuse condition variables. + + * unix/tclUnixNotfy.c: (Tcl_AlertNotifier, Tcl_WaitForEvent, + NotifierThreadProc, Tcl_InitNotifier): Fixed race condition caused + by incorrect use of condition variables when sending messages + between threads.. [Bug: 607] + + * generic/tclTestObj.c (TeststringobjCmd): MAX_STRINGS was off by one + so the strings array was too small. + + * generic/tclCkalloc.c (Tcl_DbCkfree): Moved mutex lock so + ValidateMemory is done inside the mutex to avoid a race condition + when validate_memory is enabled. [Bug: 880] + +1998-11-23 + + * regexec.c: more performance tuning from Henry Spencer. + +1998-11-17 + + * tclScan.c: moved "scan" implementation out of tclCmdMZ.c and + added Unicode support. This required a complete reimplementation + of the command to avoid using scanf(), which isn't Unicode aware. + Two new features were added in the process: %n to return the + current number of characters consumed, and XPG3-style %n$ argument + order specifiers similar to those provided by the "format" + command. [Bug: 833] + + * tclAlloc.c: changed so allocated memory is always 8-byte aligned + to improve memory performance and to ensure that it will work on + systems that don't like accessing 4-byte aligned values + (e.g. Solaris and HP-UX). [Bug: 834] + +1998-11-06 + + * tclVar.c (TclGetIndexedScalar): Fixed bug 796, var name was + getting lost before being passed to CallTraces. + +1998-10-21 + + * added "encoding" command + + * Moved internal regexp declarations from tclInt.h to tclRegexp.h + + * integrated regexp updates from Henry Spencer + +1998-10-15 + + * tclUtf.c: added Unicode character table support + + * tclInt.h: added TclUniCharIsWordChar + + * tclCmdMZ.c (Tcl_StringObjCmd): added "totitle" subcommand, + changed "wordend" and "wordstart" to properly handle Unicode word + characters and connector punctuation + +1998-10-05 + + * auto.tcl, package.tcl: fixed SCCS strings + + * tclIndex: updated index to reflect 8.1 files + + * tclCompile.c (TclCompileScript): changed to avoid modifying the + input string in place because name lookup operations could have + arbitrary side effects + + * tclInterp.c: added guard against deleting current interpreter + + * tclMacFile.c, tclUnixFile.c, tclWinFile.c, tclFileName.c: added + warnings around code that modifies strings in place + + * tclExecute.c: fixed off-by-one copying error, fixed merge bugs + + * tclEvent.c: changed so USE_TCLALLOC is tested for value instead + of definition + + * tclCompCmds.c: replaced SCCS strings, added warnings around code + that modifies strings in place + + * interp.test: added test for interp deleting itself + +1998-09-30 + + * makefile.vc: fixed so TCL_LIBRARY is set before running tcltest + + * tclWin32Dll.c: removed TclpFinalize, cleanup of merges + diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/README b/lc-continuity/mk4/modtcl/tcl8.3.4/README new file mode 100644 index 0000000000000000000000000000000000000000..8283c9cbed2be037be2e5fbdbd479c68481cfbd2 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/README @@ -0,0 +1,185 @@ +README: Tcl + This is the Tcl 8.3.4 source distribution. + You can get any release of Tcl from: + http://sourceforge.net/project/showfiles.php?group_id=10894 + Tcl/Tk is also available through NetCVS: + http://tcl.sourceforge.net/ + +RCS: @(#) $Id: README,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ + +Contents +-------- + 1. Introduction + 2. Documentation + 3. Compiling and installing Tcl + 4. Development tools + 5. Tcl newsgroup + 6. Tcl contributed archive + 7. Tcl Resource Center + 8. Mailing lists + 9. Support and Training + 10. Thank You + +1. Introduction +--------------- +Tcl provides a powerful platform for creating integration applications that +tie together diverse applications, protocols, devices, and frameworks. +When paired with the Tk toolkit, Tcl provides the fastest and most powerful +way to create GUI applications that run on PCs, Unix, and the Macintosh. +Tcl can also be used for a variety of web-related tasks and for creating +powerful command languages for applications. + +Tcl is maintained, enhanced, and distributed freely by the Tcl community. +The home for Tcl/Tk sources and bug/patch database is on SourceForge: + + http://tcl.sourceforge.net/ + +with the Tcl Developer Xchange hosted at: + + http://www.tcl-tk.net/ + +Tcl is a freely available open source package. You can do virtually +anything you like with it, such as modifying it, redistributing it, +and selling it either in whole or in part. See the file +"license.terms" for complete information. + +2. Documentation +---------------- + +Extensive documentation is available at our website. +The home page for this release, including new features, is + http://www.tcl-tk.net/software/tcltk/8.3.html + +Detailed release notes can be found at + http://sourceforge.net/project/showfiles.php?group_id=10894 + +Information about Tcl itself can be found at + http://www.tcl-tk.net/scripting/ + +There are many Tcl books on the market. Most are listed at + http://www.tcl-tk.net/resource/doc/books/ + +2a. Unix Documentation +---------------------- + +The "doc" subdirectory in this release contains a complete set of +reference manual entries for Tcl. Files with extension ".1" are for +programs (for example, tclsh.1); files with extension ".3" are for C +library procedures; and files with extension ".n" describe Tcl +commands. The file "doc/Tcl.n" gives a quick summary of the Tcl +language syntax. To print any of the man pages on Unix, cd to the +"doc" directory and invoke your favorite variant of troff using the +normal -man macros, for example + + ditroff -man Tcl.n + +to print Tcl.n. If Tcl has been installed correctly and your "man" program +supports it, you should be able to access the Tcl manual entries using the +normal "man" mechanisms, such as + + man Tcl + +2b. Windows Documentation +------------------------- + +The "doc" subdirectory in this release contains a complete set of Windows +help files for Tcl. Once you install this Tcl release, a shortcut to the +Windows help Tcl documentation will appear in the "Start" menu: + + Start | Programs | Tcl | Tcl Help + +3. Compiling and installing Tcl +------------------------------- + +There are brief notes in the unix/README, win/README, and mac/README about +compiling on these different platforms. There is additional information +about building Tcl from sources at + + http://www.tcl-tk.net/doc/howto/compile.html + +4. TclPro Development tools +--------------------------- + +A high quality set of commercial quality development tools is available to +accelerate your Tcl application development. The TclPro product provides a +debugger, static code checker, packaging utility, and bytecode compiler. +TclPro was open-sourced when Scriptics/Ajuba was acquired by Interwoven. +Visit its home at SourceForge for more information and source/binaries: + + http://tclpro.sourceforge.net/ + +5. Tcl newsgroup +---------------- + +There is a network news group "comp.lang.tcl" intended for the exchange of +information about Tcl, Tk, and related applications. The newsgroup is a +great place to ask general information questions. For bug reports, please +see the "Support and bug fixes" section below. + +6. Tcl contributed archive +-------------------------- + +Many people have created exciting packages and applications based on Tcl +and/or Tk and made them freely available to the Tcl community. An archive +of these contributions is kept on the machine ftp.neosoft.com. You +can access the archive using anonymous FTP; the Tcl contributed archive is +in the directory "/pub/tcl". The archive also contains several FAQ +("frequently asked questions") documents that provide solutions to problems +that are commonly encountered by TCL newcomers. + +7. Tcl Resource Center +---------------------- + +Visit http://www.tcl-tk.net/resource/ to see an annotated index of +many Tcl resources available on the World Wide Web. This includes +papers, books, and FAQs, as well as development tools, extensions, +applications, binary releases, and patches. You can also recommend +additional URLs for the resource center using the forms labeled "Add a +Resource". + +8. Mailing lists +---------------- + +Several mailing lists are hosted at SourceForge to discuss development or +use issues (like Macintosh and Windows topics). For more information and +to subscribe, visit: + + http://sourceforge.net/projects/tcl/ + +and go to the Mailing Lists page. + +9. Support and Training +------------------------ + +We are very interested in receiving bug reports, patches, and suggestions +for improvements. We prefer that you send this information to us via the +bug form at SourceForge, rather than emailing us directly. The bug +database is at: + + http://tcl.sourceforge.net/ + +The bug form was designed to give uniform structure to bug reports as +well as to solicit enough information to minimize followup questions. + +We will log and follow-up on each bug, although we cannot promise a +specific turn-around time. Enhancements may take longer and may not happen +at all unless there is widespread support for them (we're trying to slow +the rate at which Tcl/Tk turns into a kitchen sink). It's very difficult +to make incompatible changes to Tcl/Tk at this point, due to the size of +the installed base. + +The Tcl community is too large for us to provide much individual support +for users. If you need help we suggest that you post questions to +comp.lang.tcl. We read the newsgroup and will attempt to answer esoteric +questions for which no-one else is likely to know the answer. In addition, +see the following Web site for links to other organizations that offer +Tcl/Tk training: + + http://www.tcl-tk.net/resource/community/commercial/training + +10. Thank You +------------- + +We'd like to express our thanks to the Tcl community for all the +helpful suggestions, bug reports, and patches we have received. +Tcl/Tk has improved vastly and will continue to do so with your help. diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/changes b/lc-continuity/mk4/modtcl/tcl8.3.4/changes new file mode 100644 index 0000000000000000000000000000000000000000..d3b5e564eb571334ae32333484e2037e1671a6e4 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/changes @@ -0,0 +1,5075 @@ +Recent user-visible changes to Tcl: + +RCS: @(#) $Id: changes,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ + +1. No more [command1] [command2] construct for grouping multiple +commands on a single command line. + +2. Semi-colon now available for grouping commands on a line. + +3. For a command to span multiple lines, must now use backslash-return +at the end of each line but the last. + +4. "Var" command has been changed to "set". + +5. Double-quotes now available as an argument grouping character. + +6. "Return" may be used at top-level. + +7. More backslash sequences available now. In particular, backslash-newline +may be used to join lines in command files. + +8. New or modified built-in commands: case, return, for, glob, info, +print, return, set, source, string, uplevel. + +9. After an error, the variable "errorInfo" is filled with a stack +trace showing what was being executed when the error occurred. + +10. Command abbreviations are accepted when parsing commands, but +are not recommended except for purely-interactive commands. + +11. $, set, and expr all complain now if a non-existent variable is +referenced. + +12. History facilities exist now. See Tcl.man and Tcl_RecordAndEval.man. + +13. Changed to distinguish between empty variables and those that don't +exist at all. Interfaces to Tcl_GetVar and Tcl_ParseVar have changed +(NULL return value is now possible). *** POTENTIAL INCOMPATIBILITY *** + +14. Changed meaning of "level" argument to "uplevel" command (1 now means +"go up one level", not "go to level 1"; "#1" means "go to level 1"). +*** POTENTIAL INCOMPATIBILITY *** + +15. 3/19/90 Added "info exists" option to see if variable exists. + +16. 3/19/90 Added "noAbbrev" variable to prohibit command abbreviations. + +17. 3/19/90 Added extra errorInfo option to "error" command. + +18. 3/21/90 Double-quotes now only affect space: command, variable, +and backslash substitutions still occur inside double-quotes. +*** POTENTIAL INCOMPATIBILITY *** + +19. 3/21/90 Added support for \r. + +20. 3/21/90 List, concat, eval, and glob commands all expect at least +one argument now. *** POTENTIAL INCOMPATIBILITY *** + +21. 3/22/90 Added "?:" operators to expressions. + +22. 3/25/90 Fixed bug in Tcl_Result that caused memory to get trashed. + +------------------- Released version 3.1 --------------------- + +23. 3/29/90 Fixed bug that caused "file a.b/c ext" to return ".b/c". + +24. 3/29/90 Semi-colon is not treated specially when enclosed in +double-quotes. + +------------------- Released version 3.2 --------------------- + +25. 4/16/90 Rewrote "exec" not to use select or signals anymore. +Should be more Sys-V compatible, and no slower in the normal case. + +26. 4/18/90 Rewrote "glob" to eliminate GNU code (there's no GNU code +left in Tcl, now), and added Tcl_TildeSubst procedure. Added automatic +tilde-substitution in many commands, including "glob". + +------------------- Released version 3.3 --------------------- + +27. 7/11/90 Added "Tcl_AppendResult" procedure. + +28. 7/20/90 "History" with no options now defaults to "history info" +rather than to "history redo". Although this is a backward incompatibility, +it should only be used interactively and thus shouldn't present any +compatibility problems with scripts. + +29. 7/20/90 Added "Tcl_GetInteger", "Tcl_GetDouble", and "Tcl_GetBoolean" +procedures. + +30. 7/22/90 Removed "Tcl_WatchInterp" procedure: doesn't seem to be +necessary, since the same effect can be achieved with the deletion +callbacks on individual commands. *** POTENTIAL INCOMPATIBILITY *** + +31. 7/23/90 Added variable tracing: Tcl_TraceVar, Tcl_UnTraceVar, +and Tcl_VarTraceInfo procedures, "trace" command. + +32. 8/9/90 Mailed out list of all bug fixes since 3.3 release. + +33. 8/29/90 Fixed bugs in Tcl_Merge relating to backslashes and +semi-colons. Mailed out patch. + +34. 9/3/90 Fixed bug in tclBasic.c: quotes weren't quoting ]'s. +Mailed out patch. + +35. 9/19/90 Rewrote exec to always use files both for input and +output to the process. The old pipe-based version didn't work if +the exec'ed process forked a child and then exited: Tcl waited +around for stdout to get closed, which didn't happen until the +grandchild exited. + +36. 11/5/90 ERR_IN_PROGRESS flag wasn't being cleared soon enough +in Tcl_Eval, allowing error messages from different commands to +pile up in $errorInfo. Fixed by re-arranging code in Tcl_Eval that +re-initializes result and ERR_IN_PROGRESS flag. Didn't mail out +patch: changes too complicated to describe. + +37. 12/19/90 Added Tcl_VarEval procedure as a convenience for +assembling and executing Tcl commands. + +38. 1/29/91 Fixed core leak in Tcl_AddErrorInfo. Also changed procedure +and Tcl_Eval so that first call to Tcl_AddErrorInfo need not come from +Tcl_Eval. + +----------------- Released version 5.0 with Tk ------------------ + +39. 4/3/91 Removed change bars from manual entries, leaving only those +that came after version 3.3 was released. + +40. 5/17/91 Changed tests to conform to Mary Ann May-Pumphrey's approach. + +41. 5/23/91 Massive revision to Tcl parser to simplify the implementation +of string and floating-point support in expressions. Newlines inside +[] are now treated as command separators rather than word separators +(this makes newline treatment consistent throughout Tcl). +*** POTENTIAL INCOMPATIBILITY *** + +42. 5/23/91 Massive rewrite of expression code to support floating-point +values and simple string comparisons. The C interfaces to expression +routines have changed (Tcl_Expr is replaced by Tcl_ExprLong, Tcl_ExprDouble, +etc.), but all old Tcl expression strings should be accepted by the new +expression code. +*** POTENTIAL INCOMPATIBILITY *** + +43. 5/23/91 Modified tclHistory.c to check for negative "keep" value. + +44. 5/23/91 Modified Tcl_Backslash to handle backslash-newline. It now +returns 0 to indicate that a backslash sequence should be replaced by +no character at all. +*** POTENTIAL INCOMPATIBILITY *** + +45. 5/29/91 Modified to use ANSI C function prototypes. Must set +"USE_ANSI" switch when compiling to get prototypes. + +46. 5/29/91 Completed test suite by providing tests for all of the +built-in Tcl commands. + +47. 5/29/91 Changed Tcl_Concat to eliminate leading and trailing +white-space in each of the things it concatenates and to ignore +elements that are empty or have only white space in them. This +produces cleaner output from the "concat" command. +*** POTENTIAL INCOMPATIBILITY *** + +48. 5/31/91 Changed "set" command and Tcl_SetVar procedure to return +new value of variable. + +49. 6/1/91 Added "while" and "cd" commands. + +50. 6/1/91 Changed "exec" to delete the last character of program +output if it is a newline. In most cases this makes it easier to +process program-generated output. +*** POTENTIAL INCOMPATIBILITY *** + +51. 6/1/91 Made sure that pointers are never used after freeing them. + +52. 6/1/91 Fixed bug in TclWordEnd where it wasn't dealing with +[] inside quotes correctly. + +53. 6/8/91 Fixed exec.test to accept return values of either 1 or +255 from "false" command. + +54. 7/6/91 Massive overhaul of variable management. Associative +arrays now available, along with "unset" command (and Tcl_UnsetVar +procedure). Variable traces have been completely reworked: +interfaces different both from Tcl and C, and multiple traces may +exist on same variable. Can no longer redefine existing local +variable to be global. Calling sequences have changed slightly +for Tcl_GetVar and Tcl_SetVar ("global" is now "flags"). Tcl_SetVar +can fail and return a NULL result. New forms of variable-manipulation +procedures: Tcl_GetVar2, Tcl_SetVar2, etc. Syntax of variable +$-notation changed to support array indexing. +*** POTENTIAL INCOMPATIBILITY *** + +55. 7/6/91 Added new list-manipulation procedures: Tcl_ScanElement, +Tcl_ConvertElement, Tcl_AppendElement. + +56. 7/12/91 Created new procedure Tcl_EvalFile, which does most of the +work of the "source" command. + +57. 7/20/91 Major reworking of "exec" command to allow pipelines, +more redirection, background. Added new procedures Tcl_Fork, +Tcl_WaitPids, Tcl_DetachPids, and Tcl_CreatePipeline. The old +"< input" notation has been replaced by "<< input" ("<" is for +redirection from a file). Also handles error returns and abnormal +terminations (e.g. signals) differently. +*** POTENTIAL INCOMPATIBILITY *** + +58. 7/21/91 Added "append" and "lappend" commands. + +59. 7/22/91 Reworked error messages and manual entries to use +?x? as the notation for an optional argument x, instead of [x]. The +bracket notation was often confused with the use of brackets for +command substitution. Also modified error messages to be more +consistent. + +60. 7/23/91 Tcl_DeleteCommand now returns an indication of whether +or not the command actually existed, and the "rename" command uses +this information to return an error if an attempt is made to delete +a non-existent command. +*** POTENTIAL INCOMPATIBILITY *** + +61. 7/25/91 Added new "errorCode" mechanism, along with procedures +Tcl_SetErrorCode, Tcl_UnixError, and Tcl_ResetResult. Renamed +Tcl_Return to Tcl_SetResult, but left a #define for Tcl_Return to +avoid compatibility problems. + +62. 7/26/91 Extended "case" command with alternate syntax where all +patterns and commands are together in a single list argument: makes +it easier to write multi-line case statements. + +63. 7/27/91 Changed "print" command to perform tilde-substitution on +the file name. + +64. 7/27/91 Added "tolower", "toupper", "trim", "trimleft", and "trimright" +options to "string" command. + +65. 7/29/91 Added "atime", "mtime", "size", and "stat" options to "file" +command. + +66. 8/1/91 Added "split" and "join" commands. + +67. 8/11/91 Added commands for file I/O, including "open", "close", +"read", "gets", "puts", "flush", "eof", "seek", and "tell". + +68. 8/14/91 Switched to use a hash table for command lookups. Command +abbreviations no longer have direct support in the Tcl interpreter, but +it should be possible to simulate them with the auto-load features +described below. The "noAbbrev" variable is no longer used by Tcl. +*** POTENTIAL INCOMPATIBILITY *** + +68.5 8/15/91 Added support for "unknown" command, which can be used to +complete abbreviations, auto-load library files, auto-exec shell +commands, etc. + +69. 8/15/91 Added -nocomplain switch to "glob" command. + +70. 8/20/91 Added "info library" option and TCL_LIBRARY #define. Also +added "info script" option. + +71. 8/20/91 Changed "file" command to take "option" argument as first +argument (before file name), for consistency with other Tcl commands. +*** POTENTIAL INCOMPATIBILITY *** + +72. 8/20/91 Changed format of information in $errorInfo variable: +comments such as + ("while" body line 1) +are now on separate lines from commands being executed. +*** POTENTIAL INCOMPATIBILITY *** + +73. 8/20/91 Changed Tcl_AppendResult so that it (eventually) frees +large buffers that it allocates. + +74. 8/21/91 Added "linsert", "lreplace", "lsearch", and "lsort" +commands. + +75. 8/28/91 Added "incr" and "exit" commands. + +76. 8/30/91 Added "regexp" and "regsub" commands. + +77. 9/4/91 Changed "dynamic" field in interpreters to "freeProc" (procedure +address). This allows for alternative storage managers. +*** POTENTIAL INCOMPATIBILITY *** + +78. 9/6/91 Added "index", "length", and "range" options to "string" +command. Added "lindex", "llength", and "lrange" commands. + +79. 9/8/91 Removed "index", "length", "print" and "range" commands. +"Print" is redundant with "puts", but less general, and the other +commands are replaced with the new commands described in change 78 +above. +*** POTENTIAL INCOMPATIBILITY *** + +80. 9/8/91 Changed history revision to occur even when history command +is nested; needed in order to allow "history" to be invoked from +"unknown" procedure. + +81. 9/13/91 Changed "panic" not to use vfprintf (it's uglier and less +general now, but makes it easier to run Tcl on systems that don't +have vfprintf). Also changed "strerror" not to redeclare sys_errlist. + +82. 9/19/91 Lots of changes to improve portability to different UNIX +systems, including addition of "config" script to adapt Tcl to the +configuration of the system it's being compiled on. + +83. 9/22/91 Added "pwd" command. + +84. 9/22/91 Renamed manual pages so that their filenames are no more +than 14 characters in length, moved to "doc" subdirectory. + +85. 9/24/91 Redid manual entries so they contain the supplemental +macros that they need; can just print with "troff -man" or "man" +now. + +86. 9/26/91 Created initial version of script library, including +a version of "unknown" that does auto-loading, auto-execution, and +abbreviation expansion. This library is used by tclTest +automatically. See the "library" manual entry for details. + +----------------- Released version 6.0, 9/26/91 ------------------ + +87. 9/30/91 Made "string tolower" and "string toupper" check case +before converting: on some systems, "tolower" and "toupper" assume +that character already has particular case. + +88. 9/30/91 Fixed bug in Tcl_SetResult: wasn't always setting freeProc +correctly when called with NULL value. This tended to cause memory +allocation errors later. + +89. 10/3/91 Added "upvar" command. + +90. 10/4/91 Changed "format" so that internally it converts %D to %ld, +%U to %lu, %O to %lo, and %F to %f. This eliminates some compatibility +problems on some machines without affecting behavior. + +91. 10/10/91 Fixed bug in "regsub" that caused core dumps with the -all +option when the last match wasn't at the end of the string. + +92. 10/17/91 Fixed problems with backslash sequences: \r support was +incomplete and \f and \v weren't supported at all. + +93. 10/24/91 Added Tcl_InitHistory procedure. + +94. 10/24/91 Changed "regexp" to store "-1 -1" in subMatchVars that +don't match, rather than returning an error. + +95. 10/27/91 Modified "regexp" to return actual strings in matchVar +and subMatchVars instead of indices. Added "-indices" switch to cause +indices to be returned. +*** POTENTIAL INCOMPATIBILITY *** + +96. 10/27/91 Fixed bug in "scan" where it used hardwired constants for +sizes of floats and doubles instead of using "sizeof". + +97. 10/31/91 Fixed bug in tclParse.c where parse-related error messages +weren't being storage-managed correctly, causing spurious free's. + +98. 10/31/91 Form feed and vertical tab characters are now considered +to be space characters by the parser. + +99. 10/31/91 Added TCL_LEAVE_ERR_MSG flag to procedures like Tcl_SetVar. + +100. 11/7/91 Fixed bug in "case" where "in" argument couldn't be omitted +if all case branches were embedded in a single list. + +101. 11/7/91 Switched to use "pid_t" and "uid_t" and other official +POSIC types and function prototypes. + +----------------- Released version 6.1, 11/7/91 ------------------ + +102. 12/2/91 Modified Tcl_ScanElement and Tcl_ConvertElement in several +ways. First, allowed caller to request that only backslashes be used +(no braces). Second, made Tcl_ConvertElement more aggressive in using +backslashes for braces and quotes. + +103. 12/5/91 Added "type", "lstat", and "readlink" options to "file" +command, plus added new "type" element to output of "stat" and "lstat" +options. + +104. 12/10/91 Manual entries had first lines that caused "man" program +to try weird preprocessor. Added blank comment lines to fix problem. + +105. 12/16/91 Fixed a few bugs in auto_mkindex proc: wasn't handling +errors properly, and hadn't been upgraded for new "regexp" syntax. + +106. 1/2/92 Fixed bug in "file" command where it didn't properly handle +a file names containing tildes where the indicated user doesn't exist. + +107. 1/2/92 Fixed lots of cases in tclUnixStr.c where two different +errno symbols (e.g. EWOULDBLOCK and EAGAIN) have the same number; Tcl +will only use one of them. + +108. 1/2/92 Lots of changes to configuration script to handle many more +systems more gracefully. E.g. should now detect the bogus strtoul that +comes with AIX and substitute Tcl's own version instead. + +----------------- Released version 6.2, 1/10/92 ------------------ + +109. 1/20/92 Config didn't have code to actually use "uid_t" variable +to set TCL_UIT_T #define. + +110. 2/10/92 Tcl_Eval didn't properly reset "numLevels" variable when +too-deep recursion occurred. + +111. 2/29/92 Added "on" and "off" to keywords accepted by Tcl_GetBoolean. + +112. 3/19/92 Config wasn't installing default version of strtod.c for +systems that don't have one in libc.a. + +113. 3/23/92 Fixed bug in tclExpr.c where numbers with leading "."s, +like 0.75, couldn't be properly substituted into expressions with +variable or command substitution. + +114. 3/25/92 Fixed bug in tclUnixAZ.c where "gets" command wasn't +checking to make sure that it was able to write the variable OK. + +115. 4/16/92 Fixed bug in tclUnixAZ.c where "read" command didn't +compute file size right for device files. + +116. 4/23/92 Fixed but in tclCmdMZ.c where "trace vinfo" was overwriting +the trace command. + +----------------- Released version 6.3, 5/1/92 ------------------ + +117. 5/1/92 Added Tcl_GlobalEval. + +118. 6/1/92 Changed auto-load facility to source files at global level. + +119. 6/8/92 Tcl_ParseVar wasn't always setting termPtr after errors, which +sometimes caused core dumps. + +120. 6/21/92 Fixed bug in initialization of regexp pattern cache. This +bug caused segmentation violations in regexp commands under some conditions. + +121. 6/22/92 Changed implementation of "glob" command to eliminate +trailing slashes on directory names: they confuse some systems. There +shouldn't be any user-visible changes in functionality except for names +in error messages not having trailing slashes. + +122. 7/2/92 Fixed bug that caused 'string match ** ""' to return 0. + +123. 7/2/92 Fixed bug in Tcl_CreateCmdBuf where it wasn't initializing +the buffer to an empty string. + +124. 7/6/92 Fixed bug in "case" command where it used NULL pattern string +after errors in the "default" clause. + +125. 7/25/92 Speeded up auto_load procedure: don't reread all the index +files unless the path has changed. + +126. 8/3/92 Changed tclUnix.h to define MAXPATHLEN from PATH_MAX, not +_POSIX_PATH_MAX. + +----------------- Released version 6.4, 8/7/92 ------------------ + +127. 8/10/92 Changed tclBasic.c so that comment lines can be continued by +putting a backslash before the newline. + +128. 8/21/92 Modified "unknown" to allow the source-ing of a file for +an auto-load to trigger other nested auto-loads, as long as there isn't +any recursion on the same command name. + +129. 8/25/92 Modified "format" command to allow " " and "+" flags, and +allow flags in any order. + +130. 9/14/92 Modified Tcl_ParseVar so that it doesn't actually attempt +to look up the variable if "noEval" mode is in effect in the interpreter +(it just parses the name). This avoids the errors that used to occur +in statements like "expr {[info exists foo] && $foo}". + +131. 9/14/92 Fixed bug in "uplevel" command where it didn't output the +correct error message if a level was specified but no command. + +132. 9/14/92 Renamed manual entries to have extensions like .3 and .n, +and added "install" target to Makefile. + +133. 9/18/92 Modified "unknown" command to emulate !!, !, and +^^ csh history substitutions. + +134. 9/21/92 Made the config script cleverer about figuring out which +switches to pass to "nm". + +135. 9/23/92 Fixed tclVar.c to be sure to copy flags when growing variables. +Used to forget about traces in progress and make extra recursive calls +on trace procs. + +136. 9/28/92 Fixed bug in auto_reset where it was unsetting variables +that might not exist. + +137. 10/7/92 Changed "parray" library procedure to print any array +accessible to caller, local or global. + +138. 10/15/92 Fixed bug where propagation of new environment variable +values among interpreters took N! time if there exist N interpreters. + +139. 10/16/92 Changed auto_reset procedure so that it also deletes any +existing procedures that are in the auto_load index (the assumption is +that they should be re-loaded to get the latest versions). + +140. 10/21/92 Fixed bug that caused lists to be incorrectly generated +for elements that contained backslash-newline sequences. + +141. 12/9/92 Added support for TCL_LIBRARY environment variable: use +it as library location if it's present. + +142. 12/9/92 Added "info complete" command, Tcl_CommandComplete procedure. + +143. 12/16/92 Changed the Makefile to check to make sure "config" has been +run (can't run config directly from the Makefile because it modifies the +Makefile; thus make has to be run again after running config). + +----------------- Released version 6.5, 12/17/92 ------------------ + +144. 12/21/92 Changed config to look in several places for libc file. + +145. 12/23/92 Added "elseif" support to if. Also, "then", "else", and +"elseif" may no longer be abbreviated. +*** POTENTIAL INCOMPATIBILITY *** + +146. 12/28/92 Changed "puts" and "read" to support initial "-nonewline" +switch instead of additional "nonewline" argument. The old form is +still supported, but it is discouraged and is no longer documented. +Also changed "puts" to make the file argument default to stdout: e.g. +"puts foo" will print foo on standard output. + +147. 1/6/93 Fixed bug whereby backslash-newline wasn't working when +typed interactively, or in "info complete". + +148. 1/22/93 Fixed bugs in "lreplace" and "linsert" where close +quotes were being lost from last element before replacement or +insertion. + +149. 1/29/93 Fixed bug in Tcl_AssembleCmd where it wasn't requiring +a newline at the end of a line before considering a command to be +complete. The bug caused some very long lines in script files to +be processed as multiple separate commands. + +150. 1/29/93 Various changes in Makefile to add more configuration +options, simplify installation, fix bugs (e.g. don't use -f switch +for cp), etc. + +151. 1/29/93 Changed "name1" and "name2" identifiers to "part1" and +"part2" to avoid name conflicts with stupid C++ implementations that +use "name1" and "name2" in a reserved way. + +152. 2/1/93 Added "putenv" procedure to replace the standard system +version so that it will work correctly with Tcl's environment handling. + +----------------- Released version 6.6, 2/5/93 ------------------ + +153. 2/10/93 Fixed bugs in config script: missing "endif" in libc loop, +and tried to use strncasecmp.c instead of strcasecmp.c. + +154. 2/10/93 Makefile improvements: added RANLIB variable for easier +Sys-V configuration, added SHELL variable for SGI systems. + +----------------- Released version 6.7, 2/11/93 ------------------ + +153. 2/6/93 Changes in backslash processing: + - \Cx, \Mx, \CMx, \e sequences no longer special + - \ also eats up any space after the newline, replacing + the whole sequence with a single space character + - Hex sequences like \x24 are now supported, along with ANSI C's \a. + - "format" no longer does backslash processing on its format string + - there is no longer any special meaning to a 0 return value from + Tcl_Backslash + - unknown backslash sequences, like (e.g. \*), are replaced with + the following character (e.g. *), instead of just treating the + backslash as an ordinary character. +*** POTENTIAL INCOMPATIBILITY *** + +154. 2/6/93 Updated all copyright notices. The meaning hasn't changed +at all but the wording does a better job of protecting U.C. from +liability (according to U.C. lawyers, anyway). + +155. 2/6/93 Changed "regsub" so that it overwrites the result variable +in all cases, even if there is no match. +*** POTENTIAL INCOMPATIBILITY *** + +156. 2/8/93 Added support for XPG3 %n$ conversion specifiers to "format" +command. + +157. 2/17/93 Fixed bug in Tcl_Eval where errors due to infinite +recursion could result in core dumps. + +158. 2/17/93 Improved the auto-load mechanism to deal gracefully (i.e. +return an error) with a situation where a library file that supposedly +defines a procedure doesn't actually define it. + +159. 2/17/93 Renamed Tcl_UnixError procedure to Tcl_PosixError, and +changed errorCode variable usage to use POSIX as keyword instead of +UNIX. +*** POTENTIAL INCOMPATIBILITY *** + +160. 2/19/93 Changes to exec and process control: + - Added support for >>, >&, >>&, |&, <@, >@, and >&@ forms of redirection. + - When exec puts processes into background, it returns a list of + their pids as result. + - Added support for file, etc. (i.e. no space between + ">" and file name. + - Added -keepnewline option. + - Deleted Tcl_Fork and Tcl_WaitPids procedures (just use fork and + waitpid instead). + - Added waitpid compatibility procedure for systems that don't have + it. + - Added Tcl_ReapDetachedProcs procedure. + - Changed "exec" to return an error if there is stderr output, even + if the command returns a 0 exit status (it's always been documented + this way, but the implementation wasn't correct). + - If a process returns a non-zero exit status but doesn't generate + any diagnostic output, then Tcl generates an error message for it. +*** POTENTIAL INCOMPATIBILITY *** + +161. 2/25/93 Fixed two memory-management problems having to do with +managing the old result during variable trace callbacks. + +162. 3/1/93 Added dynamic string library: Tcl_DStringInit, Tcl_DStringAppend, +Tcl_DStringFree, Tcl_DStringResult, etc. + +163. 3/1/93 Modified glob command to only return the names of files that +exist, and to only return names ending in "/" if the file is a directory. +*** POTENTIAL INCOMPATIBILITY *** + +164. 3/19/93 Modified not to use system calls like "read" directly, +but instead to use special Tcl procedures that retry automatically +if interrupted by signals. + +165. 4/3/93 Eliminated "noSep" argument to Tcl_AppendElement, plus +TCL_NO_SPACE flag for Tcl_SetVar and Tcl_SetVar2. +*** POTENTIAL INCOMPATIBILITY *** + +166. 4/3/93 Eliminated "flags" and "termPtr" arguments to Tcl_Eval. +*** POTENTIAL INCOMPATIBILITY *** + +167. 4/3/93 Changes to expressions: + - The "expr" command now accepts multiple arguments, which are + concatenated together with space separators. + - Integers aren't automatically promoted to floating-point if they + overflow the word size: errors are generated instead. + - Tcl can now handle "NaN" and other special values if the underlying + library procedures handle them. + - When printing floating-point numbers, Tcl ensures that there is a "." + or "e" in the number, so it can't be treated as an integer accidentally. + The procedure Tcl_PrintDouble is available to provide this function + in other contexts. Also, the variable "tcl_precision" can be used + to set the precision for printing (must be a decimal number giving + digits of precision). + - Expressions now support transcendental and other functions, e.g. sin, + acos, hypot, ceil, and round. Can add new math functions with + Tcl_CreateMathFunc(). + - Boolean expressions can now have any of the string values accepted + by Tcl_GetBoolean, such as "yes" or "no". +*** POTENTIAL INCOMPATIBILITY *** + +168. 4/5/93 Changed Tcl_UnsetVar and Tcl_UnsetVar2 to return TCL_OK +or TCL_ERROR instead of 0 or -1. +*** POTENTIAL INCOMPATIBILITY *** + +169. 4/5/93 Eliminated Tcl_CmdBuf structure and associated procedures; +can use Tcl_DStrings instead. +*** POTENTIAL INCOMPATIBILITY *** + +170. 4/8/93 Changed interface to Tcl_TildeSubst to use a dynamic +string for buffer space. This makes the procedure re-entrant and +thread-safe, whereas it wasn't before. +*** POTENTIAL INCOMPATIBILITY *** + +171. 4/14/93 Eliminated tclHash.h, and moved everything from it to +tcl.h +*** POTENTIAL INCOMPATIBILITY *** + +172. 4/15/93 Eliminated Tcl_InitHistory, made "history" command always +be part of interpreter. +*** POTENTIAL INCOMPATIBILITY *** + +173. 4/16/93 Modified "file" command so that "readable" option always +exists, even on machines that don't support symbolic links (always returns +same error as if the file wasn't a symbolic link). + +174. 4/26/93 Fixed bugs in "regsub" where ^ patterns didn't get handled +right (pretended not to match when it really did, and looped infinitely +if -all was specified). + +175. 4/29/93 Various improvements in the handling of variables: + - Can create variables and array elements during a read trace. + - Can delete variables during traces (note: unset traces will be + invoked when this happens). + - Can upvar to array elements. + - Can retarget an upvar to another variable by re-issuing the + upvar command with a different "other" variable. + +176. 5/3/93 Added Tcl_GetCommandInfo, which returns info about a Tcl +command such as whether it exists and its ClientData. Also added +Tcl_SetCommandInfo, which allows any of this information to be modified +and also allows a command's delete procedure to have a different +ClientData value than its command procedure. + +177. 5/5/93 Added Tcl_RegExpMatch procedure. + +178. 5/6/93 Fixed bug in "scan" where it didn't properly handle +%% conversion specifiers. Also changed "scan" to use Tcl_PrintDouble +for printing real values. + +179. 5/7/93 Added "-exact", "-glob", and "-regexp" options to "lsearch" +command to allow different kinds of pattern matching. + +180. 5/7/93 Added many new switches to "lsort" to control the sorting +process: "-ascii", "-integer", "-real", "-command", "-increasing", +and "-decreasing". + +181. 5/10/93 Changes to file I/O: + - Modified "open" command to support a list of POSIX access flags + like {WRONLY CREAT TRUNC} in addition to current fopen-style + access modes. Also added "permissions" argument to set permissions + of newly-created files. + - Fixed Scott Bolte's bug (can close stdin etc. in application and + then re-open them with Tcl commands). + - Exported access to Tcl's file table with new procedures Tcl_EnterFile + and Tcl_GetOpenFile. + +182. 5/15/93 Added new "pid" command, which can be used to retrieve +either the current process id or a list of the process ids in a +pipeline opened with "open |..." + +183. 6/3/93 Changed to use GNU autoconfig for configuration instead of +the home-brew "config" script. Also made many other configuration-related +changes, such as using instead of explicitly declaring system +calls in tclUnix.h. + +184. 6/4/93 Fixed bug where core-dumps could occur if a procedure +redefined itself (the memory for the procedure's body could get +reallocated in the middle of evaluating the body); implemented +simple reference count mechanism. + +185. 6/5/93 Changed tclIndex file format in two ways: (a) it's now +eval-ed instead of parsed, which makes it 3-4x faster; (b) the entries +in auto_index are now commands to evaluate, which allows commands to +be loaded in different ways such as dynamic-loading of C code. The +old tclIndex file format is still supported. + +186. 6/7/93 Eliminated tclTest program, added new "tclsh" program +that is more like wish (allows script files to be invoked automatically +using "#!/usr/local/bin/tclsh", makes arguments available to script, +etc.). Added support for Tcl_AppInit plus default version; this +allows new Tcl applications to be created without modifying the +main program for tclsh. + +187. 6/7/93 Fixed bug in TclWordEnd that kept backslash-newline from +working correctly in some cases during interactive input. + +188. 6/9/93 Added Tcl_LinkVar and related procedures, which automatically +keep a Tcl variable in sync with a C variable. + +189. 6/16/93 Increased maximum nesting depth from 100 to 1000. + +190. 6/16/93 Modified "trace var" command so that error messages from +within traces are returned properly as the result of the variable +access, instead of the generic "access disallowed by trace command" +message. + +191. 6/16/93 Added Tcl_CallWhenDeleted to provide callbacks when an +interpreter is deleted (same functionality as Tcl_WatchInterp, which +used to exist in versions before 6.0). + +193. 6/16/93 Added "-code" argument to "return" command; it's there +primarily for completeness, so that procedures implementing control +constructs can reflect exceptional conditions back to their callers. + +194. 6/16/93 Split up Tcl.n to make separate manual entries for each +Tcl command. Tcl.n now contains a summary of the language syntax. + +195. 6/17/93 Added new "switch" command to replace "case": allows +alternate forms of pattern matching (exact, glob, regexp), replaces +pattern lists with single patterns (but you can use "-" bodies to +share one body among several patterns), eliminates "in" noise word. +"Case" command is now obsolete. + +196. 6/17/93 Changed the "exec", "glob", "regexp", and "regsub" commands +to include a "--" switch. All initial arguments starting with "-" are now +treated as switches unless a "--" switch is present to end the list. +*** POTENTIAL INCOMPATIBILITY *** + +197. 6/17/93 Changed auto-exec so that the subprocess gets stdin, stdout, +and stderr from the parent. This allows truly interactive sub-processes +(e.g. vi) to be auto-exec'ed from a tcl shell command line. + +198. 6/18/93 Added patchlevel.h, for use in coordinating future patch +releases, and also added "info patchlevel" command to make the patch +level available to Tcl scripts. + +199. 6/19/93 Modified "glob" command so that a leading "//" in a name +gets left as is (this is needed for systems like Apollos where "//" is +the super-root; Tcl used to collapse the two slashes into a single +slash). + +200. 7/7/93 Added Tcl_SetRecursionLimit procedure so that the maximum +allowable nesting depth can be controlled for an interpreter from C. + +----------------- Released version 7.0 Beta 1, 7/9/93 ------------------ + +201. 7/12/93 Modified Tcl_GetInt and tclExpr.c so that full-precision +unsigned integers can be specified without overflow errors. + +202. 7/12/93 Configuration changes: eliminate leading blank line in +configure script; provide separate targets in Makefile for installing +binary and non-binary information; check for size_t and a few other +potentially missing typedefs; don't put tclAppInit.o into libtcl.a; +better checks for matherr support. + +203. 7/14/93 Changed tclExpr.c to check the termination pointer before +errno after strtod calls, to avoid problems with some versions of +strtod that set errno in unexpected ways. + +204. 7/16/93 Changed "scan" command to be more ANSI-conformant: +eliminated %F, %D, etc., added code to ignore "l", "h", and "L" +modifiers but always convert %e, %f, and %g with implicit "l"; +also added support for %u and %i. Also changed "format" command +to eliminate %D, %U, %O, and add %i. +*** POTENTIAL INCOMPATIBILITY *** + +205. 7/17/93 Changed "uplevel" and "upvar" so that they can be used +from global level to global level: this used to generate an error. + +206. 7/19/93 Renamed "setenv", "putenv", and "unsetenv" procedures +to avoid conflicts with system procedures with the same names. If +you want Tcl's procedures to override the system procedures, do it +in the Makefile (instructions are in the Makefile). +*** POTENTIAL INCOMPATIBILITY *** + +----------------- Released version 7.0 Beta 2, 7/21/93 ------------------ + +207. 7/21/93 Fixed bug in tclVar.c where freed memory was accidentally +used if a procedure returned an element of a local array. + +208. 7/22/93 Fixed bug in "unknown" where it didn't properly handle +errors occurring in the "auto_load" procedure, leaving its state +inconsistent. + +209. 7/23/93 Changed exec's ">2" redirection operator to "2>" for +consistency with sh. This is incompatible with earlier beta releases +of 7.0 but not with pre-7.0 releases, which didn't support either +operator. + +210. 7/28/93 Changed backslash-newline handling so that the resulting +space character *is* treated as a word separator unless the backslash +sequence is in quotes or braces. This is incompatible with 7.0b1 +and 7.0b2 but is more compatible with pre-7.0 versions that the b1 +and b2 releases were. + +211. 7/28/93 Eliminated Tcl_LinkedVarWritable, added TCL_LINK_READ_ONLY to +Tcl_LinkVar to accomplish same purpose. This change is incompatible +with earlier beta releases, but not with releases before Tcl 7.0. + +212. 7/29/93 Renamed regexp C functions so they won't clash with POSIX +regexp functions that use the same name. + +213. 8/3/93 Added "-errorinfo" and "-errorcode" options to "return" +command: these allow for much better handling of the errorInfo +and errorCode variables in some cases. + +214. 8/12/93 Changed "expr" so that % always returns a remainder with +the same sign as the divisor and absolute value smaller than the +divisor. + +215. 8/14/93 Turned off auto-exec in "unknown" unless the command +was typed interactively. This means you must use "exec" when +invoking subprocesses, unless it's a command that's typed interactively. +*** POTENTIAL INCOMPATIBILITY *** + +216. 8/14/93 Added support for tcl_prompt1 and tcl_prompt2 variables +to tclMain.c: makes prompts user-settable. + +217. 8/14/93 Added asynchronous handlers (Tcl_AsyncCreate etc.) so +that signals can be taken cleanly by Tcl applications. + +218. 8/16/93 Moved information about open files from the interpreter +structure to global variables so that a file can be opened in one +interpreter and read or written in another. + +219. 8/16/93 Removed ENV_FLAGS from Makefile, so that there's no +official support for overriding setenv, unsetenv, and putenv. + +220. 8/20/93 Various configuration improvements: coerce chars +to unsigned chars before using macros like isspace; source ~/.tclshrc +file during initialization if it exists and program is running +interactively; allow there to be directories in auto_path that don't +exist or don't have tclIndex files (ignore them); added Tcl_Init +procedure and changed Tcl_AppInit to call it. + +221. 8/21/93 Fixed bug in expr where "+", "-", and " " were all +getting treated as integers with value 0. + +222. 8/26/93 Added "tcl_interactive" variable to tclsh. + +223. 8/27/93 Added procedure Tcl_FilePermissions to return whether a +given file can be read or written or both. Modified Tcl_EnterFile +to take a permissions mask rather than separate read and write arguments. + +224. 8/28/93 Fixed performance bug in "glob" command (unnecessary call +to "access" for each file caused a 5-10x slow-down for big directories). + +----------------- Released version 7.0 Beta 3, 8/28/93 ------------------ + +225. 9/9/93 Renamed regexp.h to tclRegexp.h to avoid conflicts with system +include file by same name. + +226. 9/9/93 Added Tcl_DontCallWhenDeleted. + +227. 9/16/93 Changed not to call exit C procedure directly; instead +always invoke "exit" Tcl command so that application can redefine the +command to do additional cleanup. + +228. 9/17/93 Changed auto-exec to handle names that contain slashes +(i.e. don't use PATH for them). + +229. 9/23/93 Fixed bug in "read" and "gets" commands where they didn't +clear EOF conditions. + +----------------- Released version 7.0, 9/29/93 ------------------ + +230. 10/7/93 "Scan" command wasn't properly aligning things in memory, +so segmentation faults could arise under some circumstances. + +231. 10/7/93 Fixed bug in Tcl_ConvertElement where it forgot to +backslash leading curly brace when creating lists. + +232. 10/7/93 Eliminated dependency of tclMain.c on tclInt.h and +tclUnix.h, so that people can copy the file out of the Tcl source +directory to make modified private versions. + +233. 10/8/93 Fixed bug in auto-loader that reversed the priority order +of entries in auto_path for new-style index files. Now things are +back to the way they were before 3.0: first in auto_path is always +highest priority. + +234. 10/13/93 Fixed bug where Tcl_CommandComplete didn't recognize +comments and treat them as such. Thus if you typed the line + # { +interactively, Tcl would think that the command wasn't complete and +wait for more input before evaluating the script. + +235. 10/14/93 Fixed bug where "regsub" didn't set the output variable +if the input string was empty. + +236. 10/23/93 Fixed bug where Tcl_CreatePipeline didn't close off enough +file descriptors in child processes, causing children not to exit +properly in some cases. + +237. 10/28/93 Changed "list" and "concat" commands not to generate +errors if given zero arguments, but instead to just return an empty +string. + +----------------- Released version 7.1, 11/4/93 ------------------ + +Note: there is no 7.2 release. It was flawed and was thus withdrawn +shortly after it was released. + +238. 11/10/93 TclMain.c didn't compile on some systems because of +R_OK in call to "access". Changed to eliminate call to "access". + +----------------- Released version 7.3, 11/26/93 ------------------ + +239. 11/6/93 Modified "lindex", "linsert", "lrange", and "lreplace" +so that "end" can be specified as an index. + +240. 11/6/93 Modified "append" and "lappend" to allow only two +words total (i.e., nothing to append) without generating an error. + +241. 12/2/93 Changed to use EAGAIN as the errno for non-blocking +I/O instead of EWOULDBLOCK: this should fix problem where non-blocking +I/O didn't work correctly on System-V systems. + +242. 12/22/93 Fixed bug in expressions where cancelled evaluation +wasn't always working correctly (e.g. "set one 1; eval {1 || 1/$one}" +failed with a divide by zero error). + +243. 1/6/94 Changed TCL_VOLATILE definition from -1 to the address of +a dummy procedure Tcl_Volatile, since -1 causes portability problems on +some machines (e.g., Crays). + +244. 2/4/94 Added support for unary plus. + +245. 2/17/94 Changed Tcl_RecordAndEval and "history" command to +call Tcl_GlobalEval instead of Tcl_Eval. Otherwise, invocation of +these facilities in nested procedures can cause unwanted results. + +246. 2/17/94 Fixed bug in tclExpr.c where an expression such as +"expr {"12398712938788234-1298379" != ""}" triggers an integer +overflow error for the number in quotes, even though it isn't really +a proper integer anyway. + +247. 2/19/94 Added new procedure Tcl_DStringGetResult to move result +from interpreter to a dynamic string. + +248. 2/19/94 Fixed bug in Tcl_DStringResult that caused it to overwrite +the contents of a static result in some situations. This can cause +bizarre errors such as variables suddenly having empty values. + +249. 2/21/94 Fixed bug in Tcl_AppendElement, Tcl_DStringAppendElement, +and the "lappend" command that caused improper omission of a separator +space in some cases. For example, the script + set x "abc{"; lappend x "def" +used to return the result "abc{def" instead of "abc{ def". + +250. 3/3/94 Tcl_ConvertElement was outputting empty elements as \0 if +TCL_DONT_USE_BRACES was set. This depends on old pre-7.0 meaning of +\0, which is no longer in effect, so it didn't really work. Changed +to output empty elements as {} always. + +251. 3/3/94 Renamed Tcl_DStringTrunc to Tcl_DStringSetLength and extended +it so that it can be used to lengthen a string as well as shorten it. +Tcl_DStringTrunc is defined as a macro for backward compatibility, but +it is deprecated. + +252. 3/3/94 Added Tcl_AllowExceptions procedure. + +253. 3/13/94 Fixed bug in Tcl_FormatCmd that could cause "format" +to mis-behave on 64-bit Big-Endian machines. + +254. 3/13/94 Changed to use vfork instead of fork on systems where +vfork exists. + +255. 3/23/94 Fixed bug in expressions where ?: didn't associate +right-to-left as they should. + +256. 4/3/94 Fixed "exec" to flush any files used in >@ or >&@ +redirection in exec, so that data buffered for them is written +before any new data added by the subprocess. + +257. 4/3/94 Added "subst" command. + +258. 5/20/94 The tclsh main program is now called Tcl_Main; tclAppInit.c +has a "main" procedure that calls Tcl_Main. This makes it easier to use +Tcl with C++ programs, which need their own main programs, and it also +allows an application to prefilter the argument list before calling +Tcl_Main. +*** POTENTIAL INCOMPATIBILITY *** + +259. 6/6/94 Fixed bug in procedure returns where the errorInfo variable +could get truncated if an unset trace was invoked as part of returning +from the procedure. + +260. 6/13/94 Added "wordstart" and "wordend" options to "string" command. + +261. 6/27/94 Fixed bug in expressions where they didn't properly cancel +the evaluation of math functions in &&, ||, and ?:. + +262. 7/11/94 Incorrect boolean values, like "ogle", weren't being +handled properly. + +263. 7/15/94 Added Tcl_RegExpCompile, Tcl_RegExpExec, and Tcl_RegExpRange, +which provide lower-level access to regular expression pattern matching. + +264. 7/22/94 Fixed bug in "glob" command where "glob -nocomplain ~bad_user" +would complain about a missing user. Now it doesn't complain anymore. + +265. 8/4/94 Fixed bug with linked variables where they didn't behave +correctly when accessed via upvars. + +266. 8/17/94 Fixed bug in Tcl_EvalFile where it didn't clear interp->result. + +267. 8/31/94 Modified "open" command so that errors in exec-ing +subprocesses are returned by the open immediately, rather than +being delayed until the "close" is executed. + +268. 9/9/94 Modified "expr" command to generate errors for integer +overflow (includes addition, subtraction, negation, multiplication, +division). + +269. 9/23/94 Modified "regsub" to return a count of the number of +matches and replacements, rather than 0/1. + +279. 10/4/94 Added new features to "array" command: + - added "get" and "set" commands for easy conversion between arrays + and lists. + - added "exists" command to see if a variable is an array, changed + "names" and "size" commands to treat a non-existent array (or scalar + variable) just like an empty one. + - added pattern option to "names" command. + +280. 10/6/94 Modified Tcl_SetVar2 so that read traces on variables get +called during append operations. + +281. 10/20/94 Fixed bug in "read" command where reading from stdin +required two control-D's to stop the reading. + +282. 11/3/94 Changed "expr" command to use longs for division just like +all other expr operators; it previously used ints for division. + +283. 11/4/94 Fixed bugs in "unknown" procedure: it wasn't properly +handling exception returns from commands that were executed after +being auto-loaded. + +----------------- Released version 7.4b1, 12/23/94 ------------------ + +284. 12/26/94 Fixed "install" target in Makefile (couldn't always +find install program). + +285. 12/26/94 Added strcncasecmp procedure to compat directory. + +286. 1/3/95 Fixed all procedure calls to explicitly cast arguments: +implicit conversions from prototypes (especially integer->double) +don't work when compiling under non-ANSI compilers. Tcl is now clean +under gcc -Wconversion. + +287. 1/4/95 Fixed problem in Tcl_ArrayCmd where same name was used for +both a label and a variable; caused problems on several older compilers, +making array command misbehave and causing many errors in Tcl test suite. + +----------------- Released version 7.4b2, 1/12/95 ------------------ + +288. 2/9/95 Modified Tcl_CreateCommand to return a token, and added +Tcl_GetCommandName procedure. Together, these procedures make it possible +to track renames of a command. + +289. 2/13/95 Fixed bug in expr where "089" was interpreted as a +floating-point number rather than a bogus octal number. +*** POTENTIAL INCOMPATIBILITY *** + +290. 2/14/95 Added code to Tcl_GetInt and Tcl_GetDouble to check for +overflows when reading in numbers. + +291. 2/18/95 Changed "array set" to stop after first error, rather than +continuing after error. + +292. 2/20/95 Upgraded to use autoconf version 2.2. + +293. 2/20/95 Fixed core dump that could occur in "scan" command if a +close bracket was omitted. + +294. 2/27/95 Changed Makefile to always use install-sh for installations: +there's just too much variation among "install" system programs, which +makes installation flakey. + +----------------- Released version 7.4b3, 3/24/95 ------------------ + +3/25/95 (bug fix) Changed "install" to "./install" in Makefile so that +"make install" will work even when "." isn't in the search path. + +3/29/95 (bug fix) Fixed bug where the auto-loading mechanism wasn't +protecting the values of the errorCode and errorInfo variables. + +3/29/95 (new feature) Added optional pattern argument to "parray" procedure. + +3/29/95 (bug fix) Made the full functionality of + "return -code ... -errorcode ..." +work not just inside procedures, but also in sourced files and at +top level. + +4/6/95 (new feature) Added "pattern" option to "array names" command. + +4/18/95 (bug fix) Fixed bug in parser where it didn't allow backslash-newline +immediately after an argument in braces or quotes. + +4/19/95 (new feature) Added tcl_library variable, which application can +set to override default library directory. + +4/30/95 (bug fix) During trace callbacks for array elements, the variable +name used in the original reference would be temporarily modified to +separate the array name and element name; if the trace callback used +the same name string, it would get the wrong name (the array name without +element). Fixed to restore the variable name before making trace +callbacks. + +4/30/95 (new feature) Added -nobackslashes, -nocommands, and -novariables +switches to "subst" command. + +5/4/95 (new feature) Added TCL_EVAL_GLOBAL flag to Tcl_RecordAndEval. + +5/5/95 (bug fix) Format command would overrun memory when printing +integers with very large precision, as in "format %.1000d 0". + +5/5/95 (portability improvement) Changed to use BSDgettimeofday on +IRIX machines, to avoid compilation problems with the gettimeofday +declaration. + +5/6/95 (bug fix) Changed manual entries to use the standard .TH +macro instead of a custom .HS macro; the .HS macro confuses index +generators like makewhatis. + +5/9/95 (bug fix) Modified configure script to check for Solaris bug +that makes vfork unreliable (core dumps result if vforked child +changes a signal handler); will use fork instead of vfork if the +bug is present. + +6/5/95 (bug fix) Modified "lsort" command to disallow recursive calls +to lsort from a comparison function. This is needed because qsort +is not reentrant. + +6/5/95 (bug fix) Undid change 243 above: changed TCL_VOLATILE and +TCL_DYNAMIC back to integer constants rather than procedure addresses. +This was needed because procedure addresses can have multiple values +under some dynamic loading systems (e.g. SunOS 4.1 and Windows). + +6/8/95 (feature change) Modified interface to Tcl_Main to pass in the +address of the application-specific initialization procedure. +Tcl_AppInit is no longer hardwired into Tcl_Main. This is needed +in order to make Tcl a shared library. + +6/8/95 (feature change) Modified Makefile so that the installed versions +of tclsh and libtcl.a have version number in them (e.g. tclsh7.4 and +libtcl7.4.a) and the library directory name also has an embedded version +number (e.g., /usr/local/lib/tcl7.4). This should make it easier for +Tcl 7.4 to coexist with earlier versions. + +----------------- Released version 7.4b4, 6/16/95 ------------------ + +6/19/95 (bug fix) Fixed bugs in tclCkalloc.c that caused core dumps +if TCL_MEM_DEBUG was enabled on word-addressed machines such as Crays. + +6/21/95 (feature removal) Removed overflow checks for integer arithmetic: +they just cause too much trouble (e.g. for random number generators). + +6/28/95 (new features) Added tcl_patchLevel and tcl_version variables, +for consistency with Tk. + +6/29/95 (bug fix) Fixed problem in Tcl_Eval where it didn't record +the right termination character if a script ended with a comment. This +caused erroneous output for the following command, among others: +puts "[ +expr 1+1 +# duh! +]" + +6/29/95 (message change) Changed the error message for ECHILD slightly +to provide a hint about why the problem is occurring. + +----------------- Released version 7.4, 7/1/95 ------------------ + +7/18/95 (bug fix) Changed "lreplace" so that nothing is deleted if +the last index is less than the first index or if the last index +is < 0. + +7/18/95 (bug fix) Fixed bugs with backslashes in comments: +Tcl_CommandComplete (and "info complete") didn't properly handle +strings ending in backslash-newline, and neither Tcl_CommandComplete +nor the Tcl parser handled other backslash sequences right, such +as two backslashes before a newline. + +7/19/95 (bug fix) Modified Tcl_DeleteCommand to delete the hash table +entry for the command before invoking its callback. This is needed in +order to deal with reentrancy. + +7/22/95 (bug fix) "exec" wasn't reaping processes correctly after +certain errors (e.g. if the name of the executable was bogus, as +in "exec foobar"). + +7/27/95 (bug fix) Makefile.in wasn't using the LIBS variable provided +by the "configure" script. This caused problems on some SCO systems. + +7/27/95 (bug fix) The version of strtod in fixstrtod.c didn't properly +handle the case where endPtr == NULL. + +----------------- Released patch 7.4p1, 7/29/95 ----------------------- + +8/4/95 (bug fix) C-level trace callbacks for variables were sometimes +receiving the PART1_NOT_PARSED flag, which could cause errors in +subsequent Tcl library calls using the flags. (JO) + +8/4/95 (bug fix) Calls to toupper and tolower weren't using the +UCHAR macros, which caused trouble in non-U.S. locales. (JO) + +8/10/95 (new feature) Added the "load" command for dynamic loading of +binary packages, and the Tcl_PackageInitProc prototype for package +initialization procedures. (JO) + +8/23/95 (new features) Added "info sharedlibextension" and +"info nameofexecutable" commands, plus Tcl_FindExtension procedure. (JO) + +8/25/95 (bug fix) If the target of an "upvar" was non-existent but +had traces set, the traces were silently lost. Change to generate +an error instead. (JO) + +8/25/95 (bug fix) Undid change from 7/19, so that commands can stay +around while their deletion callbacks execute. Added lots of code to +handle all of the reentrancy problems that this opens up. (JO) + +8/25/95 (bug fix) Fixed core dump that could occur in TclDeleteVars +if there was an upvar from one entry in the table to the next entry +in the same table. (JO) + +8/28/95 (bug fix) Exec wasn't handling bad user names properly, as +in "exec ~bogus_user/foo". (JO) + +8/29/95 (bug fixes) Changed backslash-newline handling to correct two +problems: + - Only spaces and tabs following the backslash-newline are now + absorbed as part of the backslash-newline. Newlinew are no + longer absorbed (add another backslash if you want to absorb + another newline). + - TclWordEnd returns the character just before the backslash in + the sequence as the end of the sequence; it used to not consider + the backslash-newline as a word separator. (JO) + +8/31/95 (new feature) Changed man page installation (with "mkLinks" +script) to create additional links for manual pages corresponding to +each of the procedure and command names described in the pages. (JO) + +9/10/95 Reorganized Tcl sources for Windows and Mac ports. All sources +are now in subdirectories: "generic" contains sources that work on all +platforms, "windows", "mac", and "unix" directories contain platform- +specific sources. Some UNIX sources are also used on other platforms. (SS) + +9/10/95 (feature change) Eliminated exported global variables (they +don't work with Windows DLLs). Replaced tcl_AsyncReady and +tcl_FileCloseProc with procedures Tcl_AsyncReady() and +Tcl_SetFileCloseProc(). Replaced C variable tcl_RcFileName with +a Tcl variable tcl_rcFileName. (SS) +*** POTENTIAL INCOMPATIBILITY *** + +9/11/95 (new feature) Added procedure Tcl_SetPanicProc to override +the default implementation of "panic". (SS) + +9/11/95 (new feature) Added "interp" command to allow creation of +new interpreters and execution of untrusted scripts. Added many new +procedures, such as Tcl_CreateSlave, Tcl_CreateAlias,and Tcl_MakeSafe, +to provide C-level access to the interpreter facility. This mechanism +now provides almost all of the generic functions of Borenstein's and +Rose's Safe-Tcl (but not any Tk or email-related stuff). (JL) + +9/11/95 (feature change) Changed file management so that files are +no longer shared between interpreters: a file cannot normally be +referenced in one interpreter if it was opened in another. This +feature is needed to support safe interpreters. Added Tcl_ShareHandle() +procedure for allowing files to be shared, and added "interp" argument +to Tcl_FilePermissions procedure. (JL) +*** POTENTIAL INCOMPATIBILITY *** + +9/11/95 (new feature) Added "AssocData" mechanism, whereby extensions +can associate their own data with an interpreter and get called back +when the interpreter is deleted. This is visible at C level via the +procedures Tcl_SetAssocData and Tcl_GetAssocData. (JL) + +9/11/95 (new feature) Added Tcl_ErrnoMsg to translate an errno value +into a human-readable string. This is now used instead of calling +strerror because strerror mesages vary dramatically from platform +to platform, which messes up Tcl tests. Tcl_ErrnoMsg uses the standard +POSIX messages for all the common signals, and calls strerror for +signals it doesn't understand. + +----------------- Released patch 7.4p2, 9/15/95 ----------------------- + +----------------- Released 7.5a1, 9/15/95 ----------------------- + +9/22/95 (bug fix) Changed auto_mkindex to create tclIndex files that +handle directories whose paths might contain spaces. (RJ) + +9/27/95 (bug fix) The "format" command didn't check for huge or negative +width specifiers, which could cause core dumps. (JO) + +9/27/95 (bug fix) Core dumps could occur if an interactive command typed +to tclsh returned a very long result for tclsh to print out. The bug is +actually in printf (in Solaris 2.3 and 2.4, at least); switched to use +puts instead. (JO) + +9/28/95 (bug fix) Changed makefile.bc to eliminate a false dependency +for tcl1675.dll on the Borland run time library. (SS) + +9/28/95 (bug fix) Fixed tcl75.dll so it looks for tcl1675.dll instead +of tcl16.dll. (SS) + +9/28/95 (bug fix) Tcl was not correctly detecting the difference +between Win32s and Windows '95. (SS) + +9/28/95 (bug fix) "exec" was not passing environment changes to child +processes under Windows. (SS) + +9/28/95 (bug fix) Changed Tcl to ensure that open files are not passed +to child processes under Windows. (SS) + +9/28/95 (bug fix) Fixed Windows '95 and NT versions of exec so it can +handle both console and windows apps. (SS) + +9/28/95 (bug fix) Fixed Windows version of exec so it no longer leaves +temp files lying around. Also changed it so the temp files are +created in the appropriate system dependent temp directory. (SS) + +9/28/95 (bug fix) Eliminated source dependency on the Win32s Universal +Thunk header file, since it is not bundled with VC++. (SS) + +9/28/95 (bug fix) Under Windows, Tcl now constructs the HOME +environment variable from HOMEPATH and HOMEDRIVE when HOME is not +already set. (SS) + +9/28/95 (bug fix) Added support for "info nameofexecutable" and "info +sharedlibextension" to the Windows version. (SS) + +9/28/95 (bug fix) Changed tclsh to correctly parse command line +arguments so that backslashes are preserved under Windows. (SS) + +9/29/95 (bug fix) Tcl 7.5a1 treated either return or newline as end +of line in "gets", which caused lines ending in CRLF to be treated as +two separate lines. Changed to allow only character as end-of-line: +carriage return on Macs, newline elsewhere. (JO) + +9/29/95 (new feature) Changed to install "configInfo" file in same +directory as library scripts. It didn't used to get installed. (JO) + +9/29/95 (bug fix) Tcl was not converting Win32 errors into POSIX +errors under some circumstances. (SS) + +10/2/95 (bug fix) Safe interpreters no longer get initialized with +a call to Tcl_Init(). (JL) + +10/1/95 (new feature) Added "tcl_platform" global variable to provide +environment information such as the instruction set and operating +system. (JO) + +10/1/95 (bug fix) "exec" command wasn't always generating the +"child process exited abnormally" message when it should have. (JO) + +10/2/95 (bug fix) Changed "mkLinks.tcl" so that the scripts it generates +won't create links that overwrite original manual entries (there was +a problem where pack-old.n was overwriting pack.n). (JO) + +10/2/95 (feature change) Changed to use -ldl for dynamic loading under +Linux if it is available, but fall back to -ldld if it isn't. (JO) + +10/2/95 (bug fix) File sharing was causing refcounts to reach 0 +prematurely for stdin, stdout and stderr, under some circumstances. (JL) + +10/2/95 (platform support) Added support for Visual C++ compiler on +Windows, Windows '95 and Windows NT, code donated by Gordon Chaffee. (JL) + +10/3/95 (bug fix) Tcl now frees any libraries that it loads before it +exits. (SS) + +10/03/95 (bug fix) Fixed bug in Macintosh ls command where the -l +and -C options would fail in anything but the HOME directory. (RJ) + +----------------- Released 7.5a2, 10/6/95 ----------------------- + +10/10/95 (bug fix) "file dirnam /." was returning ":" on UNIX instead +of "/". (JO) + +10/13/95 (bug fix) Eliminated dependency on MKS toolkit for generating +the tcl.def file from Borland object files. (SS) + +10/17/95 (new features) Moved the event loop from Tcl to Tk, made major +revisions along the way: + - New Tcl commands: after, update, vwait (replaces "tkwait variable"). + - "tkerror" is now replaced with "bgerror". + - The following procedures are similar to their old Tk counterparts: + Tcl_DoOneEvent, Tcl_Sleep, Tcl_DoWhenIdle, Tcl_CancelIdleCall, + Tcl_CreateFileHandler, Tcl_DeleteFileHandler, Tcl_CreateTimerHandler, + Tcl_DeleteTimerHandler, Tcl_BackgroundError. + - Revised notifier, add new concept of "event source" with the following + procedures: Tcl_CreateEventSource, Tcl_DeleteEventSource, + Tcl_WatchFile, Tcl_SetMaxBlockTime, Tcl_FileReady, Tcl_QueueEvent, + Tcl_WaitForEvent. (JO) + +10/31/95 (new features) Implemented cross platform file name support to make +it easier to write cross platform scripts. Tcl now understands 4 file naming +conventions: Windows (both DOS and UNC), Mac, Unix, and Network. The network +convention is a new naming mechanism that can be used to paths in a platform +independent fashion. See the "file" command manual page for more details. +The primary interfaces changes are: + - All Tcl commands that expect a file name now accept both network and + native form. + - Two new "file" subcommands, "nativename" and "networkname", provide a + way to convert between network and native form. + - Renamed Tcl_TildeSubst to Tcl_TranslateFileName, and changed it so that + it always returns a filename in native form. Tcl_TildeSubst is defined + as a macro for backward compatibility, but it is deprecated. (SS) + +11/5/95 (new feature) Made "tkerror" and "bgerror" synonyms, so that +either name can be used to manipulate the command (provides temporary +backward compatibility for existing scripts that use tkerror). (JO) + +11/5/95 (new feature) Added exit handlers and new C procedures +Tcl_CreateExitHandler, Tcl_DeleteExitHandler, and Tcl_Exit. (JO) + +11/6/95 (new feature) Added pid command for Macintosh version of +Tcl (it didn't previously exist on the Mac). (RJ) + +11/7/95 (new feature) New generic IO facility and support for IO to +files, pipes and sockets based on a common buffering scheme. Support +for asynchronous (non-blocking) IO and for event driver IO. Support +for automatic (background) asynchronous flushing and asynchronous +closing of channels. (JL) + +11/7/95 (new feature) Added new commands "fconfigure" and "fblocked" +to support new I/O features such as nonblocking I/O. Added "socket" +command for creating TCP client and server sockets. (JL). + +11/7/95 (new feature) Complete set of C APIs to the new generic IO +facility: + - Opening channels: Tcl_OpenFileChannel, Tcl_OpenCommandChannel, + Tcl_OpenTcpClient, Tcl_OpenTcpServer. + - I/O procedures on channels, which roughly mirror the ANSI C stdio + library: Tcl_Read, Tcl_Gets, Tcl_Write, Tcl_Flush, Tcl_Seek, + Tcl_Tell, Tcl_Close, Tcl_Eof, Tcl_InputBlocked, Tcl_GetChannelOption, + Tcl_SetChannelOption. + - Extension mechanism for creating new kinds of channels: + Tcl_CreateChannel, Tcl_GetChannelInstanceData, Tcl_GetChannelType, + Tcl_GetChannelName, Tcl_GetChannelFile, Tcl_RegisterChannel, + Tcl_UnregisterChannel, Tcl_GetChannel. + - Event-driven I/O on channels: Tcl_CreateChannelHandler, + Tcl_DeleteChannelHandler. (JL) + +11/7/95 (new feature) Channel driver interface specification to allow +new types of channels to be added easily to Tcl. Currently being used +in three drivers - for files, pipes and TCP-based sockets. (JL). + +11/7/95 (new feature) interp delete now takes any number of path +names of interpreters to delete, including zero. (JL). + +11/8/95 (new feature) implemented 'info hostname' and Tcl_GetHostName +command to get host name of machine on which the Tcl process is running. (JL) + +11/9/95 (new feature) Implemented file APIs for access to low level files +on each system. The APIs are: Tcl_CloseFile, Tcl_OpenFile, Tcl_ReadFile, +Tcl_WriteFile and Tcl_SeekFile. Also implemented Tcl_WaitPid which waits +in a system dependent manner for a child process. (JL) + +11/9/95 (new feature) Added Tcl_UpdateLinkedVar procedure to force a +Tcl variable to be updated after its C variable changes. (JO) + +11/9/95 (bug fix) The glob command has been totally reimplemented so +that it can support different file name conventions. It now handles +Windows file names (both UNC and drive-relative) properly. It also +supports nested braces correctly now. (SS) + +11/13/95 (bug fix) Fixed Makefile.in so that configure can be run +from a clean directory separate from the Tcl source tree, and compilations +can be performed there. (JO) + +11/14/95 (bug fix) Fixed file sharing between interpreters and file +transferring between interpreters to correctly manage the refcount so that +files are closed when the last reference to them is discarded. (JL) + +11/14/95 (bug fix) Fixed gettimeofday implementation for the +Macintosh. This fixes several timing related bugs. (RJ) + +11/17/95 (new feature) Added missing support for info nameofexecutable +on the Macintosh. (RJ) + +11/17/95 (bug fix) The Tcl variables argc argv and argv0 now return +something reasonable on the Mac. (RJ) + +11/22/95 (new feature) Implemented "auto-detect" mode for end of line +translations. On input, standalone "\r" mean MAC mode, standalone "\n" +mean Unix mode and "\r\n" means Windows mode. On output, the mode is +modified to whatever the platform specific mode for that platform is. (JL) + +11/24/95 (feature change) Replaced "configInfo" file with tclConfig.sh, +which is more complete and uses slightly different names. Also +arranged for tclConfig.sh to be installed in the platform-specific +library directory instead of Tcl's script library directory. (JO) +*** POTENTIAL INCOMPATIBILITY with Tcl 7.5a2, but not with Tcl 7.4 *** + +----------------- Released patch 7.4p3, 11/28/95 ----------------------- + +12/5/95 (new feature) Added Tcl_File facility to support platform- +independent file handles. Changed all interfaces that used Unix- +style integer fd's to use Tcl_File's instead. (SS) +*** POTENTIAL INCOMPATIBILITY *** + +12/5/95 (new feature) Added a new "clock" command to Tcl. The command +allows you to get the current "clicks" or seconds & allows you to +format or scan human readable time/date strings. (RJ) + +12/18/95 (new feature) Moved Tk_Preserve, Tk_Release, and Tk_EventuallyFree +to Tcl, renamed to Tcl_Preserve, Tcl_Release, and Tcl_EventuallyFree. (JO) + +12/18/95 (new feature) Added new "package" command and associated +procedures Tcl_PkgRequire and Tcl_PkgProvide. Also wrote +pkg_mkIndex library procedure to create index files from binaries +and scripts. (JO) + +12/20/95 (new feature) Added Tcl_WaitForFile procedure. (JO) + +12/21/95 (new features) Made package name argument to "load" optional +(Tcl will now attempt to guess the package name if necessary). Also +added Tcl_StaticPackage and support in "load" for statically linked +packages. (JO) + +12/22/95 (new feature) Upgraded the foreach command to accept multiple +loop variables and multiple value lists. This lets you iterate over +multiple lists in parallel, and/or assign multiple loop variables from +one value list during each iteration. The only potential compatibility +problem is with scripts that used loop variables with a name that could be +construed to be a list of variable names (i.e. contained spaces). (BW) + +1/5/96 (new feature) Changed tclsh so it builds as a console mode +application under Windows. Now tclsh can be used from the command +line with pipes or interactively. Note that this only works under +Windows 95 or NT. (SS) + +1/17/96 (new feature) Modified Makefile and configure script to allow +Tcl to be compiled as a shared library: use the --enable-shared option +when configuing. (JO) + +1/17/96 (removed obsolete features) Removed the procedures Tcl_EnterFile +and Tcl_GetOpenFile: these no longer make sense with the new I/O system. (JL) +*** POTENTIAL INCOMPATIBILITY *** + +1/19/96 (bug fixes) Prevented formation of circular aliases, through the +Tcl 'interp alias' command and through the 'rename' command, as well as +through the C API Tcl_CreateAlias. (JL) + +1/19/96 (bug fixes) Fixed several bugs in direct deletion of interpreters +with Tcl_DeleteInterp when the interpreter is a slave; fixes based on a +patch received from Viktor Dukhovni of ESM. (JL) + +1/19/96 (new feature) Implemented on-close handlers for channels; added +the C APIs Tcl_CreateCloseHandler and Tcl_DeleteCloseHandler. (JL) + +1/19/96 (new feature) Implemented portable error reporting mechanism; added +the C APIs Tcl_SetErrno and Tcl_GetErrno. (JL) + +1/24/96 (bug fix) Unknown command processing properly invokes external +commands under Windows NT and Windows '95 now. (SS) + +1/23/96 (bug fix) Eliminated extremely long startup times under Windows '95. +The problem was a result of the option database initialization code that +concatenated $HOME with /.Xdefaults, resulting in a // in the middle of the +file name. Under Windows '95, this is incorrectly interpreted as a UNC +path. They delays came from the network timeouts needed to determine that +the file name was invalid. Tcl_TranslateFileName now suppresses duplicate +slashes that aren't at the beginning of the file name. (SS) + +1/25/96 (bug fix) Changed exec and open to create children so they are +attached to the application's console if it exists. (SS) + +1/31/96 (bug fix) Fixed command line parsing to handle embedded +spaces under Windows. (SS) + +----------------- Released 7.5b1, 2/1/96 ----------------------- + +2/7/96 (bug fix) Fixed off by one error in argument parsing code under +Windows. (SS) + +2/7/96 (bug fix) Fixed bugs in VC++ makefile that improperly +initialized the tcl75.dll. Fixed bugs in Borland makefile that caused +build failures under Windows NT. (SS) + +2/9/96 (bug fix) Fixed deadlock problem in AUTO end of line translation +mode which would cause a socket server with several concurrent clients +writing in CRLF mode to hang. (JL) + +2/9/96 (API change) Replaced -linemode option to fconfigure with a +new -buffering option, added "none" setting to enable immediate write. (JL) +*** INCOMPATIBILITY with b1 *** + +2/9/96 (new feature) Added C API Tcl_InputBuffered which returns the count +of bytes currently buffered in the input buffer of a channel, and o for +output only channels. (JL) + +2/9/96 (new feature) Implemented asynchronous connect for sockets. (JL) + +2/9/96 (new feature) Added C API Tcl_SetDefaultTranslation to set (per +channel) the default end of line translation mode. This is the mode that +will be installed if an output operation is done on the channel while it is +still in AUTO mode. (JL) + +2/9/96 (bug fix) Changed Tcl_OpenCommandChannel interface to properly +handle all of the combinations of stdio inheritance in background +pipelines. See the Tcl_OpenFileChannel(3) man page for more +info. This change fixes the bug where exec of a background pipeline +was not getting passed the stdio handles properly. (SS) + +2/9/96 (bug fix) Removed the new Tcl_CreatePipeline interface, and +restored the old version for Unix platforms only. All new code should +use Tcl_CreateCommandChannel instead. (SS) + +2/9/96 (bug fix) Changed Makefile.in to use -L and -ltcl7.5 for Tcl +library so that shared libraries are more likely to be found correctly +on more platforms. (JO) + +2/13/96 (new feature) Added C API Tcl_SetNotifierData and +Tcl_GetNotifierData to allow notifier and channel driver writers to +associate data with a Tcl_File. The result of this change is that +Tcl_GetFileInfo now always returns an OS file handle, and Tcl_GetFile +can be used to construct a Tcl_File for an externally constructed OS +handle. (SS) + +2/13/96 (bug fix) Changed Windows socket implementation so it doesn't +set SO_REUSEADDR on server sockets. Now attempts to create a server +socket on a port that is already in use will be properly identified +and an error will be generated. (SS) + +2/13/96 (bug fix) Fixed problems with DLL initialization under Visual +C++ that left the C run time library uninitialized. (SS) + +2/13/96 (bug fix) Fixed Windows socket initialization so it loads +winsock the first time it is used, rather than at the time tcl75.dll +is loaded. This should fix the bug where the modem immediately starts +trying to connect to a service provider when wish or tclsh are +started. (SS) + +2/13/96 (new feature) Added C APIs Tcl_MakeFileChannel and +Tcl_MakeTcpClientChannel to wrap up existing fds and sockets into +channels. Provided implementations on Unix and Windows. (JL) + +2/13/96 (bug fix) Fixed bug with seek leaving EOF and BLOCKING set. (JL) + +2/14/96 (bug fix) Fixed reentrancy problem in fileevent handling +and made it more robust in the face of errors. (JL) + +2/14/96 (feature change) Made generic IO level emulate blocking mode if the +channel driver is unable to provide it, e.g. if the low level device is +always nonblocking. Thus, now blocking behavior is an advisory setting for +channel drivers and can be ignored safely if the channel driver is unable +to provide it. (JL) + +2/15/96 (new feature) Added "binary" end of line translation mode, which is +a synonym of "lf" mode. (JL) + +2/15/96 (bug fix) Fixed reentrancy problem in fileevent handling vs +deletion of channel event handlers. (JL) + +2/15/96 (bug fix) Fixed bug in event handling which would cause a +nonblocking channel to not see further readable events after the first +readable event that had insufficient input. (JL) + +2/17/96 (bug fix) "info complete" didn't properly handle comments +in nested commands. (JO) + +2/21/96 (bug fix) "exec" under Windows NT/95 did not properly handle +very long command lines (>200 chars). (SS) + +2/21/96 (bug fix) Sockets could get into an infinite loop if a read +event arrived after all of the available data had been read. (SS) + +2/22/96 (bug fix) Added cast of st_size elements to (long) before +sprintf-ing in "file size" command. This is needed to handle systems +like NetBSD with 64-bit file offsets. (JO) + +----------------- Released 7.5b2, 2/23/96 ----------------------- + +2/23/96 (bug fix) TCL_VARARGS macro in tcl.h wasn't defined properly +when compiling with C++. (JO) + +2/24/96 (bug fix) Removed dependencies on Makefile in the UNIX Makefile: +this caused problems on some platforms (like Linux?). (JO) + +2/24/96 (bug fix) Fixed configuration bug that made Tcl not compile +correctly on Linux machines with neither -ldl or -ldld. (JO) + +2/24/96 (new feature) Added a block of comments and definitions to +Makefile.in to make it easier to have Tcl's TclSetEnv etc. replace +the library procedures setenv etc, so that calls to setenv etc. in +the application automatically update the Tcl "env" variable. (JO) + +2/27/96 (feature change) Added optional Tcl_Interp * argument (may be NULL) +to C API Tcl_Close and simplified closing of command channels. (JL) +*** INCOMPATIBILITY with Tcl 7.5b2, but not with Tcl 7.4 *** + +2/27/96 (feature change) Added optional Tcl_Interp * argument (may be NULL) +to C type definition Tcl_DriverCloseProc; modified all channel drivers to +implement close procedures that accept the additional argument. (JL) +*** INCOMPATIBILITY with Tcl 7.5b2, but not with Tcl 7.4 *** + +2/28/96 (bug fix) Fixed memory leak that could occur if an upvar +referred to an element of an array in the same stack frame as the +upvar. (JO) + +2/29/96 (feature change) Modified both Tcl_DoOneEvent and Tcl_WaitForEvent +so that they return immediately in cases where they would otherwise +block forever (e.g. if there are no event handlers of any sort). (JO) + +2/29/96 (new feature) Added C APIs Tcl_GetChannelBufferSize and +Tcl_SetChannelBufferSize to set and retrieve the size, in bytes, for +buffers allocated to store input or output in a channel. (JL) + +2/29/96 (new feature) Added option -buffersize to Tcl fconfigure command +to allow Tcl scripts to query and set the size of channel buffers. (JL) + +2/29/96 (feature removed) Removed channel driver function to specify +the buffer size to use when allocating a buffer. Removed the C typedef +for Tcl_DriverBufferSizeProc. Channels are now created with a default +buffer size of 4K. (JL) +*** INCOMPATIBILITY with Tcl 7.5b2, but not with Tcl 7.4 *** + +2/29/96 (feature change) The channel driver function for setting blocking +mode on the device may now be NULL. If the generic code detects that the +function is NULL, operations that set the blocking mode on the channel +simply succeed. (JL) + +3/2/96 (bug fix) Fixed core dump that could occur if a syntax error +(such as missing close paren) occurred in an array reference with a +very long array name. (JO) + +3/4/96 (bug fix) Removed code in the "auto_load" procedure that deletes +all existing auto-load information whenever the "auto_path" variable +is changed. Instead, new information adds to what was already there. +Otherwise, changing the "auto_path" variable causes all package- +related information to be lost. If you really want to get rid of +existing auto-load information, use auto_reset before setting auto_path. (JO) + +3/5/96 (new feature) Added version suffix to shared library names so that +Tcl will compile under NetBSD and FreeBSD (I hope). (JO) + +3/6/96 (bug fix) Cleaned up error messages in new I/O system to correspond +more closely to old I/O system. (JO) + +3/6/96 (new feature) Added -myaddr and -myport options to the socket +command, removed -tcp and -- options. This lets clients and servers +choose a particular interface. Also changed the default server address +from the hostname to INADDR_ANY. The server accept callback now gets +passed the client's port as well as IP address. The C interfaces for +Tcl_OpenTcpClient and Tcl_OpenTcpServer have changed to support the +above changes. (BW) +*** POTENTIAL INCOMPATIBILITY with Tcl 7.5b2, but not with Tcl 7.4 *** + +3/6/96 (changed feature) The library function auto_mkindex will now +default to using the pattern "*.tcl" if no pattern is given. (RJ) + +3/6/96 (bug fix) The socket channel code for the Macintosh has been +rewritten to use native MacTcp. (RJ) + +3/7/96 (new feature) Added Tcl_SetStdChannel and Tcl_GetStdChannel +interfaces to allow applications to explicitly set and get the global +standard channels. (SS) + +3/7/96 (bug fix) Tcl did close not the file descriptors associated +with "stdout", etc. when the corresponding channels were closed. (SS) + +3/7/96 (bug fix) Reworked shared library and dynamic loading stuff to +try to get it working under AIX. Added new @SHLIB_LD_LIBS@ autoconf +symbol as part of this. AIX probably doesn't work yet, but it should +be a lot closer. (JO) + +3/7/96 (feature change) Added Tcl_ChannelProc typedef and changed the +signature of Tcl_CreateChannelHandler and Tcl_DeleteChannelHandler to take +Tcl_ChannelProc arguments instead of Tcl_FileProc arguments. This change +should not affect any code outside Tcl because the signatures of +Tcl_ChannelProc and Tcl_FileProc are compatible. (JL) + +3/7/96 (API change) Modified signature of Tcl_GetChannelOption to return +an int instead of char *, and to take a Tcl_DString * argument. Modified +the implementation so that the option name can be NULL, to mean that the +call should retrieve a list of alternating option names and values. (JL) +*** INCOMPATIBILITY with Tcl 7.5b2, but not with Tcl 7.4 *** + +3/7/96 (API change) Added Tcl_DriverSetOptionProc, Tcl_DriverGetOptionProc +typedefs, added two slots setOptionProc and getOptionProc to the channel +type structure. These may be NULL to indicate that the channel type does +not support any options. (JL) +*** INCOMPATIBILITY with Tcl 7.5b2, but not with Tcl 7.4 *** + +3/7/96 (feature change) stdin, stdout and stderr can now be put into +nonblocking mode. (JL) + +3/8/96 (feature change) Eliminated dependence on the registry for +finding the Tcl library files. (SS) + +----------------- Released 7.5b3, 3/8/96 ----------------------- + +3/12/96 (feature improvement) Modified startup script to look in several +different places for the Tcl library directory. This should allow Tcl +to find the libraries under all but the weirdest conditions, even without +the TCL_LIBRARY environment variable being set. (JO) + +3/13/96 (bug fix) Eliminated use of the "linger" option from the Windows +socket implementation. (JL) + +3/13/96 (new feature) Added -peername and -sockname options for fconfigure +for socket channels. Code contributed by John Haxby of HP. (JL) + +3/13/96 (bug fix) Fixed panic and core dump that would occur if the accept +callback script on a server socket encountered an error. (JL) + +3/13/96 (feature change) Added -async option to the Tcl socket command. +If the command is creating a client socket and the flag is present, the +client is connected asynchronously. If the option is absent (the default), +the client socket is connected synchronously, and the command returns only +when the connection has been completed or failed. This change was suggested +by Mark Diekhans. (JL) + +3/13/96 (feature change) Modified the signature of Tcl_OpenTcpClient to +take an additional int argument, async. If nonzero, the client is connected +to the server asynchronously. If the value is zero, the connection is made +synchronously, and the call to Tcl_OpenTcpClient returns only when the +connection fails or succeeds. This change was suggested by Mark Diekhans. (JL) +*** INCOMPATIBILITY with Tcl 7.5b3, but not with Tcl 7.4 *** + +3/14/96 (bug fix) "tclsh bogus_file_name" didn't print an error message. (JO) + +3/14/96 (bug fix) Added new procedures to tclCkalloc.c so that libraries +and applications can be compiled with TCL_MEM_DEBUG even if Tcl isn't +(however, the converse is still not true). Patches provided by Jan +Nijtmans. (JO) + +3/15/96 (bug fix) Marked standard IO handles of a process as close-on-exec +to fix bug in Ultrix where exec was not sharing standard IO handles with +subprocesses. Fix suggested by Mark Diekhans. (JL) + +3/15/96 (bug fix) Fixed asynchronous close mechanism so that it closes the +channel instead of leaking system resources. The manifestation was that Tcl +would eventually run out of file descriptors if it was handling a large +number of nonblocking sockets or pipes with high congestion. (JL) + +3/15/96 (bug fix) Fixed tests so that they no longer leak file descriptors. +The manifestation was that Tcl would eventually run out of file descriptors +if the tests were rerun many times (> a hundred times on Solaris). (JL) + +3/15/96 (bug fix) Fixed channel creation code so that it never creates +unnamed channels. This would cause a panic and core dump when the channel +was closed. (JL) + +3/16/96 (bug fixes) Made lots of changes in configuration stuff to get +Tcl working under AIX (finally). Tcl should now support the "load" +command under AIX and should work either with or without shared +libraries for Tcl and Tk. (JO) + +3/21/96 (configuration improvement) Changed configure script so it +doesn't use version numbers (as in -ltcl7.5 and libtcl7.5.so) under +SunOS 4.1, where they don't work anyway. (JO) + +3/22/96 (new feature) Added C API Tcl_InterpDeleted that allows extension +writers to discover when an interpreter is being deleted. (JL) + +3/22/96 (bug fix) The standard IO channels are now added to each +trusted interpreter as soon as the interpreter is created. This ensures +against the bug where a child would do IO before the master had done any, +and then the child is destroyed - the standard IO channels would be then +closed and the master would be unable to do any IO. (JL) + +3/22/96 (bug fix) Made Tcl more robust against interpreter deletion, by +using Tcl_Preserve, Tcl_Release and Tcl_EventuallyFree to split the process +of interpreter deletion into two distinct phases. Also went through all of +Tcl and added calls to Tcl_Preserve and Tcl_Delete where needed. (JL) + +3/22/96 (bug fix) Fixed several places where C code was reading and writing +into freed memory, especially during interpreter deletion. (JL) + +3/22/96 (bug fix) Fixed very deep bug in Tcl_Release that caused memory to +be freed twice if the release callback did Tcl_Preserve and Tcl_Release on +the same memory as the chunk currently being freed. (JL) + +3/22/96 (bug fix) Removed several memory leaks that would cause memory +buildup on half-K chunks in the generic IO level. (JL) + +3/22/96 (bug fix) Fixed several core dumps which occurred when new +AssocData was being created during the cleanups in interpreter deletion. +The solution implemented now is to loop repeatedly over the AssocData until +none is left to clean up. (JL) + +3/22/96 (bug fix) Fixed a bug in event handling which caused an infinite +loop if there were no files being watched and no timer. Fix suggested by +Jan Nijtmans. (JL) + +3/22/96 (bug fix) Fixed Tcl_CreateCommand, Tcl_DeleteCommand to be more +robust if the interpreter is being deleted. Also fixed several order +dependency bugs in Tcl_DeleteCommand which kicked in when an interpreter +was being deleted. (JL) + +3/26/96 (bug fix) Upon a "short read", the generic code no longer calls +the driver for more input. Doing this caused blocking on some platforms +even on nonblocking channels. Bug and fix courtesy Mark Roseman. (JL) + +3/26/96 (new feature) Added 'package Tcltest' which is present only in +test versions of Tcl; this allows the testing commands to be loaded into +new interpreters besides the main one. (JL) + +3/26/96 (restored feature) Recreated the Tcl_GetOpenFile C API. You can +now get a FILE * from a registered channel; Unix only. (JL) + +3/27/96 (bug fix) The regular expression code did not support more +than 9 subexpressions. It now supports up to 20. (SS) + +4/1/96 (bug fixes) The CHANNEL_BLOCKED bit was being left on on a short +read, so that fileevents wouldn't fire correctly. Bug reported by Mark +Roseman.(JL, RJ) + +4/1/96 (bug fix) Moved Tcl_Release to match Tcl_Preserve exactly, in +tclInterp.c; previously interpreters were being freed only conditionally +and sometimes not at all. (JL) + +4/1/96 (bug fix) Fixed error reporting in slave interpreters when the +error message was being generated directly by C code. Fix suggested by +Viktor Dukhovni of ESM. (JL) + +4/2/96 (bug fixes) Fixed a series of bugs in Windows sockets that caused +events to variously get lost, to get sent multiple times, or to be ignored +by the driver. The manifestation was blocking if the channel is blocking, +and either getting EAGAIN or infinite loops if the channel is nonblocking. +This series of bugs was found by Ian Wallis of Cisco. Now all tests (also +those that were previously commented out) in socket.test pass. (JL, SS) + +4/2/96 (feature change/bug fix) Eliminated network name support in +favor of better native name support. Added "file split", "file join", +and "file pathtype" commands. See the "file" man page for more +details. (SS) +*** INCOMPATIBILITY with Tcl 7.5b3, but not with Tcl 7.4 *** + +4/2/96 (bug fix) Changed implementation of auto_mkindex so tclIndex +files will properly handle path names in a cross platform context. (SS) + +4/5/96 (bug fix) Fixed Tcl_ReadCmd to use the channel buffer size as the +chunk size it reads, instead of a fixed 4K size. Thus, on large reads, the +user can set the channel buffer size to a large size and the read will +occur orders of magnitude faster. For example, on a 2MB file, reading in 4K +chunks took 34 seconds, while reading in 1MB chunks took 1.5 seconds (on a +SS-20). Problem identified and fix suggested by John Haxby of HP. (JL) + +4/5/96 (bug fix) Fixed socket creation code to invoke gethostbyname only if +inet_addr failed (very unlikely). Before this change the order was reversed +and this made things much slower than they needed to be (gethostbyname +generally requires an RPC, which is slow). Problem identified and fix +suggested by John Loverso of OSF. (JL) + +4/9/96 (feature change) Modified "auto" translation mode so that it +recognizes any of "\n", "\r" and "\r\n" in input as end of line, so +that a file can have mixed end-of-line sequences. It now outputs +the platform specific end of line sequence on each platform for files and +pipes, and for sockets it produces crlf in output on all platforms. (JL) +*** INCOMPATIBILITY with Tcl 7.5b3, but not with Tcl 7.4 *** + +4/11/96 (new feature) Added -eofchar option to Tcl_SetChannelOption to allow +setting of an end of file character for input and output. If an input eof +char is set, it is recognized as EOF and further input from the channel is +not presented to the caller. If an output eof char is set, on output, that +byte is appended to the channel when it is closed. On Unix and Macintosh, +all channels start with no eof char set for input or output. On Windows, +files and pipes start with input and output eof chars set to Crlt-Z (ascii +26), and sockets start with no input or output eof char. (JL) +*** INCOMPATIBILITY with Tcl 7.5b3, but not with Tcl 7.4 *** + +4/17/96 (bug fix) Fixed series of bugs with handling of crlf sequence split +across buffer boundaries in input, in AUTO mode. (JL, BW) + +4/17/96 (test suite improvement) Fixed test suite so that tests that +depend on the availability of Unix commands such as echo, cat and others +are not run if these commands are not present. (JL) + +4/17/96 (test suite improvement) The socket test now automatically starts, +on platformst that support exec, a separate process for remote testsing. (JL) + +----------------- Released 7.5, 4/21/96 ----------------------- + +5/1/96 (bug fix) "file tail ~" did not correctly return the tail +portion of the user's home directory. (SS) + +5/1/96 (bug fix) Fixed bug in TclGetEnv where it didn't lookup environment +variables correctly: could confuse "H" and "HOME", for example. (JO) + +5/1/96 (bug fix) Changed to install tclConfig.sh under "make install-binaries", +not "make install-libraries". (JO) + +5/2/96 (bug fix) Changed pkg_mkIndex not to attempt to "load" a file unless +it has the standard shared library extension. On SunOS, attempts to load +Tcl scripts cause the whole application to be aborted (there's no way to +get the error back into Tcl). (JO) + +5/7/96 (bug fix) Moved initScript in tclUnixInit.c to writable memory to +avoid potential core dumps. (JO) + +5/7/96 (bug fix) Auto_reset procedure was removing procedure from init.tcl, +such as pkg_mkIndex. (JO) + +5/7/96 (bug fix) Fixed cast on socket address resolution code that +would cause a failure to connect on Dec Alphas. (JL) + +5/7/96 (bug fix) Added "time", "subst" and "fileevent" commands to set of +commands available in a safe interpreter. (JL) + +5/13/96 (bug fix) Preventing OS level handles for stdin, stdout and stderr +from being implicitly closed when the last reference to the standard +channel containing that handle is discarded when an interpreter is deleted. +Explicitly closing standard channels by using "close" still works. (JL) + +5/21/96 (bug fix) Do not create channels for stdin, stdout and stderr on +Unix if the devices are closed. This prevents a duplicate channel name +panic later on when the fd is used to open a channel and the channel is +registered in an interpreter. (JL) + +5/23/96 (bug fix) Fixed bug that prevented the use of standard channels in +interpreters created after the last interpreter was destroyed. In the sequence + + interp = Tcl_CreateInterp(); + Tcl_DeleteInterp(interp); + interp = Tcl_CreateInterp(); + +channels for stdio would not be available in the second interpreter. (JL) + +5/23/96 (bug fix) Fixed bug that allowed Tcl_MakeFileChannel to create new +channels with Tcl_Files in them that are already used by another channel. +This would cause core dumps when the Tcl_Files were being freed twice. (JL) + +5/23/96 (bug fix) Fixed a logical timing bug that caused a standard channel +to be removed from the standard channel table too early when the channel +was being closed. If the channel was being flushed asynchronously, it could +get recreated before being actually destroyed, and the recreated channel +would contain the same Tcl_File as the one being closed, leading to +dangling pointers and core dumps. (JL) + +5/27/96 (bug fix) Fixed a bug in Tcl_GetChannelOption which caused it to +always return a list of one element, a list of the settings, for +-translation and -eofchar options. Now correctly returns the value +described by the documentation (Mark Diekhans found this, thanks!). (JL) + +5/30/96 (bug fix) Fixed a couple of syntax errors in io.test. (JL) + +5/30/96 (bug fix) If a fileevent scripts gets an error, delete it before +causing a background error. This is to allow the error handler to reinstall +the fileevent and to prevent infinite loops if the event loop is reentered +in the error handler. (JL) + +5/31/96 (bug fix) Channels now will get properly flushed on exit. (JL) + +6/5/96 (bug fix) Changed Tcl_Ckalloc, Tcl_Ckfree, and Tcl_Ckrealloc to +Tcl_Alloc, Tcl_Free, and Tcl_Realloc. Added documentation for these +routines now that they are officially supported. Extension writers +should use these routines instead of free() and malloc(). (SS) + +6/10/96 (bug fix) Changes the Tcl close command so that it no longer +waits on nonblocking pipes for the piped processes to exit; instead it +reaps them in the background. (JL) + +6/11/96 (bug fix) Increased the length of the listen queue for server +sockets on Unix from 5 to 100. Some OSes will disregard this and reset it +to 5, but we should try to get as long a queue as we can, for performance +reasons. (JL) + +6/11/96 (bug fix) Fixed windows sockets bug that caused a cascade of events +if the fileevent script read less than was available. Now reading less than +is available does not cause a flood of Tcl events. (JL, SS) + +6/11/96 (bug fix) Fixed bug in background flushing on closed channels that +would prevent the last buffer from getting flushed. (JL) + +6/13/96 (bug fix) Fixed bug in Windows sockets that caused a core dump if +a DLL linked with tcl.dll and referred to e.g. ntohs() without opening a +Tcl socket. The problem was that the indirection table was not being +initialized. (JL) + +6/13/96 (bug fix) Fixed OS level resource leak that would occur when a +Tcl channel was still registered in some interpreter when the process +exits. Previously the channel was not being closed and the OS level handles +were not being released; the output was being flushed but the device was +not being closed. Now the device is properly closed. This was only a +problem on Win3.1 and MacOS. (JL, SS) + +6/28/96 (bug fix) Fixed bug where transient errors were leaving an error +code around, so that it would erroneously get reported later. This bug was +exercised intermittently by closing a channel to a file on a very loaded +NFS server, or to a socket whose other end blocked. (JL, BW) + +7/3/96 (bug fix) Fileevents declared in an interpreter are now deleted +when the channel is closed in that interpreter. Before this fix, the +fileevent would hang around until the channel is completely closed, and +would cause errors if events happened before the channel was closed. This +could happen in two cases: first if the channel is shared between several +interpreters, and second if an async flush is in progress that prevents the +channel from being closed until the flush finishes. (JL) + +7/10/96 (bug fix) Fixed bugs in both "lrange" and "lreplace" commands +where too much white space was being removed. For example, the command + lreplace {\}\ hello} end end +was returning "\}\", losing the significant space in the first list +element and corrupting the list. (JO) + +7/20/96 (bug fix) The procedure pkg_mkIndex didn't work properly for +extensions that depend on Tk, because it didn't load Tk into the child +interpreter before loading the extension. Now it loads Tk if Tk is +present in the parent. (JO) + +7/23/96 (bug fix) Added compat version of strftime to fix crashes +resulting from bad implementations under Windows. (SS) + +7/23/96 (bug fix) Standard implementations of gmtime() and localtime() +under Windows did not handle dates before 1970, so they were replaced +with a revised implementation. (SS) + +7/23/96 (bug fix) Tcl would crash on exit under Borland 5.0 because +the global environ pointer was left pointing to freed memory. (SS) + +7/29/96 (bug fix) Fixed memory leak in Tcl_LoadCmd that could occur if +a package's AppInit procedure called Tcl_StaticPackage to register +static packages. (JO) + +8/1/96 (bug fix) Fixed a series of bugs in Windows sockets so that async +writebehind in the presence of read event handlers now works, and so that +async writebehind also works on sockets for which a read event handler was +declared and whose channels were then closed before the async write +finished. The bug was reported by John Loverso and Steven Wahl, +independently, test case supplied by John Loverso. (JL) + +----------------- Released patch 7.5p1, 8/2/96 ----------------------- + +5/8/96 (new feature) Added Tcl_GetChannelMode C API for retrieving whether +a channel is open for reading and writing. (JL) + +5/8/96 (API changes) Revised C APIs for channel drivers: + - Removed all Tcl_Files from channel driver interface; you can now have + channels that are not based on Tcl_Files. + - Added channelReadyProc and watchChannelProc procedures to interface; + these are used to implement event notification for channels. + - Added getFileProc to channel driver, to allow the generic IO code + to retrieve a Tcl_File from a channel (presumably if the channel + uses Tcl_Files they will be stored inside its instanceData). (JL) +*** INCOMPATIBILITY with Tcl 7.5 *** + +5/8/96 (API change) The Tcl_CreateChannel C API was modified to not take +Tcl_File arguments, and instead to take a mask specifying whether the +channel is readable and/or writable. (JL) +*** INCOMPATIBILITY with Tcl 7.5 *** + +6/3/96 (bug fix) Made Tcl_SetVar2 robust against the case where the value +of the variable is a NULL pointer instead of "". (JL) + +6/17/96 (bug fix) Fixed "reading uninitialized memory" error reported by +Purify, in Tcl_Preserve/Tcl_Release. (JL) + +8/9/96 (bug fix) Fixed bug in init.tcl that caused incorrect error message +if the act of autoloading a procedure caused the procedure to be invoked +again. (JO) + +8/9/96 (bug fix) Configure script produced bad library names and extensions +under SunOS and a few other platforms if the --disable-load switch was used. +(JO) + +8/9/96 (bug fix) Tcl_UpdateLinkedVar generated an error if the variable +being updated was read-only. (JO) + +8/14/96 (bug fix) The macintosh now supports synchronous socket +connections. Other minor bugs were also fixed. (RJ) + +8/15/96 (configuration improvement) Changed the file patchlevel.h +to be tclPatch.h. This avoids conflict with the Tk file and is now +in 8.3 format on the Windows platform. (RJ) + +8/20/96 (bug fix) Fixed core dump in interp alias command for interpreters +created with Tcl_CreateInterp (as opposed to with Tcl_CreateSlave). (JL) + +8/20/96 (bug fix) No longer masking ECONNRESET on Windows sockets so +that the higher level of the IO mechanism sees the error instead of +entering an infinite loop. (JL) + +8/20/96 (bug fix) Destroying the last interpreter no longer closes the +standard channels. (JL) + +8/20/96 (bug fix) Closing one of the stdin, stdout or stderr channels and +then opening a new channel now correctly assigns the new channel as the +standard channel that was closed. (JL) + +8/20/96 (bug fix) Added code to unix/tclUnixChan.c for using ioctl with +FIONBIO instead of fcntl with O_NONBLOCK, for those versions of Unix where +either O_NONBLOCK is not supported or implemented incorrectly. (JL) + +8/21/96 (bug fix) Fixed "file extension" so it correctly returns the +extension on files like "foo..c" as "..c" instead of ".c". (SS) + +8/22/96 (bug fix) If environ[] contains static strings, Tcl would core +dump in TclSetupEnv because it was trying to write NULLs into the actual +data in environ[]. Now we instead copy as appropriate. (JL) + +8/22/96 (added impl) Added missing implementation of Tcl_MakeTcpClientChannel +for Windows platform. Code contributed by Mark Diekhans. (JL) + +8/22/96 (new feature) Added a new memory allocator for the Macintosh +version of Tcl. It's quite a bit faster than MetroWerk's version. (RJ) + +8/26/96 (documentation update) Removed old change bars (for all changes +in Tcl 7.5 and earlier releases) from manual entries. (JO) + +8/27/96 (enhancement) The exec and open commands behave better and work in +more situations under Windows NT and Windows 95. Documentation describes +what is still lacking. (CS) + +8/27/96 (enhancement) The Windows makefiles will now compile even if the +compiler is not in the path and/or the compiler's environment variables +have not been set up. (CS) + +8/27/96 (configuration improvement) The Windows resource files are +automatically updated when the version/patch level changes. The header file +now has a comment that reminds the user which other files must be manually +updated when the version/patch level changes. (CS) + +8/28/96 (new feature) Added file manipulation features (copy, rename, delete, +mkdir) that are supported on all platforms. They are implemented as +subcommands to the "file" command. See the documentation for the "file" +command for more information. (JH) + +----------------- Released 7.6b1, 8/30/96 ----------------------- + +9/3/96 (bug fix) Simplified code so that standard channels are created +lazily, they are added to an interpreter lazily, and they are never added +to a safe interpreter. (JL) + +9/3/96 (bug fix) Closing a channel after closing a standard channel, e.g. +stdout, would cause the implicit recreation of that standard channel. (JL) + +9/3/96 (new feature) Now calling Tcl_RegisterChannel with a NULL +interpreter increments the refcount so that code outside any interpreter +can use channels that are also registered in interpreters, without worrying +that the channel may turn into a dangling pointer at any time. Calling +Tcl_UnregisterChannel with a NULL interpreter only decrements the recount +so that code outside any interpreter can safely declare it is no longer +interested in a channel. (JL) + +9/4/96 (new features) Two changes to dynamic loading: + - If the file name is empty in the "load" command and there is no + statically loaded version of the package, a dynamically loaded + version will be used if there is one. + - Tcl_StaticPackage ignores redundant calls for the same package. (JO) + +9/6/96 (bug fix) Platform specific procedures for manipulating files are +no longer macros and have been prefixed with "Tclp", such as TclpRenameFile. +Unix file code now handles symbolic links and other special files correctly. +The semantics of file copy and file rename has been changed so that if +a target directory exists, the source files will NOT be merged with the +existing files. (JH) + +9/6/96 (bug fix) If standard channel is NULL, because Tcl cannot connect +to the standard channel, do not increment the refcount. The channel can +be NULL if there is for example no standard input. (JL) + +9/6/96 (portability improvement) Changed parsing of backslash sequences +like \n to translate directly to absolute values like 0xa instead of +letting the compiler do the translation. This guarantees that the +translation is done the same everywhere. (JO) + +9/9/96 (bug fix) If channel is opened and not associated with any +interpreter, but Tcl decides to use it as one of the standard channels, it +became impossible to close the channel with Tcl_Close -- instead you had +to call Tcl_UnregisterChannel. Fixed now so that it's safe to call +Tcl_Close even when Tcl is using the channel as one of the standard ones. (JL) + +9/11/96 (feature change) The Tcl library is now placed in the Tcl +shared libraries resource. You no longer need to place the Tcl files +in your applications explicitly. (RJ) + +9/11/96 (feature change) Extensions no longer automatically have the +resource fork of the extension opened for it. Instead you need to +use the tclMacLibrary.c file in your extension. (RJ) +*** POTENTIAL INCOMPATIBILITY *** + +9/12/96 (bug fix) The extension loading mechanism on the Macintosh now +looks at the 'cfrg' resource to determine where to load the code +fragment from. This means FAT fragments should now work. (RJ) + +9/18/96 (enhancement) The exec and open commands behave better and work in +more situations under Windows 3.X. Documentation describes what is still +lacking. (CS) + +9/19/96 (bug fix) Fixed a panic which would occur if you delete a +non-existent alias before any aliases are created. Now instead correctly +returns an error that the alias is not found. (JL) + +9/19/96 (bug fix) Slave interpreters could rename aliases and they would +not get deleted when the alias was being redefined. This led to dangling +pointers etc. (JL) + +9/19/96 (bug fix) Fixed a panic where a hash table entry was being deleted +twice during alias management operations. (JL) + +9/19/96 (bug fix) Fixed bug in event loop that could cause the input focus +in Tk to get confused during menu traversal, among other problems. The +problem was related to handling of the "marker" when its event was +deleted. (JO) + +9/26/96 (bug fix) Windows was losing EOF on a socket if the FD_CLOSE event +happened to precede any left over FD_READ events. Now correctly remembers +seeing FD_CLOSE, so that trailing FD_READ events are not discarded if they +do not contain any data. This allows Tcl to correctly get a zero read and +notice EOF. (JL) + +9/26/96 (bug fix) Was not resetting READABLE state properly on sockets +under Windows if the driver discarded an FD_READ event because no data was +present. Now correctly resets the state. (JL) + +9/30/96 (bug fix) Made EOF sticky on Windows sockets, so that fileevent +readable will fire repeatedly until the socket is closed. Previously the +fileevent fired only once. This could lead to never-closed connections if +the Tcl script in the fileevent wasn't closing the socket immediately. (JL) + +10/2/96 (new feature) Improved the package loader: + - Added new variable tcl_pkgPath, which holds the default + directories under which packages are normally installed (each + package goes in a separate subdirectory of a directory in + $tcl_pkgPath). These directories are included in auto_path by + default. + - Changed the package auto-loader to look for pkgIndex.tcl files + not only in the auto_path directories but also in their immediate + children. This should make it easier to install and uninstall + packages (don't have to change auto_path or merge pkgIndex.tcl + files). (JO) + +10/3/96 (bug fix) Changed tclsh to look for tclshrc.tcl instead of +tclsh.rc on startup under Windows. This is more consistent with wish and +uses the right extension. (SS) +*** POTENTIAL INCOMPATIBILITY *** + +10/8/96 (bug fix) Convertclock does not parse 24-hour times of the +form "hhmm" correctly when hour = 00. In the parse code, hour must be +>= 100 for minutes to be non-zero. Thanks to Lint LaCour for this +bug fix. (RJ) + +10/11/96 (bug fix) Under Windows, the pid command returned the process +handle instead of the process id. (SS) + +----------------- Released 7.6, 10/16/96 ----------------------- + +10/29/96 (bug fix) Under Windows, sockets would consume 100% CPU time after +the first accept(), due to a typo. (JL) + +10/29/96 (bug fix) Incorrect refcount management caused standard channels +not to get deleted at process exit or DLL unload time, causing a memory +leak of upwards of 20K each time. (JL) + +11/7/96 (bug fix) Auto-exec didn't work on file names that contained +spaces. (JO) + +11/8/96 (bug fix) Fixed core dump that would occur if more than one call +to Tcl_DeleteChannelHandler was made to delete a given channel handler. (JL) + +11/8/96 (bug fix) Fixed test for return value in Tcl_Seek and Tcl_SeekCmd +to only treat -1 as error, instead of all negative numbers. (JL) + +11/12/96 (bug fix) Do not blocking waiting for processes at the end of a +pipe during exit cleanup. (JL) + +11/12/96 (bug fix) If we are in exit cleanup, do not close the system level +file descriptors 0, 1 and 2. Previously they were being closed which is +incorrect, in the embedded case. This led to weird behavior for programs +that want to interpose on I/O through the standard file descriptors (e.g. +Netscape Navigator). (JL) + +11/15/96 (bug fix) Fixed core dump on Windows sockets due to dependency on +deletion order at exit. Now all socket functions check to see if sockets +are (still) initialized, before calling through function pointers. Before, +they would call and might end up calling unloaded object code. (JL) + +11/15/96 (bug fix) Fixed core dump in Windows socket initialization routine +if sockets were not installed on the system. Before, it was not properly +checking the result of attempting to load the socket DLL, so it would call +through uninitialized function pointers. (JL) + +11/15/96 (bug fix) Fixed memory leak in Windows sockets which left socket +DLL handle open and could hold the socket DLL in memory uneccessarily, +until a reboot. (JL) + +12/4/96 (bug fix) Fixed bug in Macintosh socket code that could result +in lost data if a client was closed too soon after sending data. (RJ) + +12/17/96 (bug fix) Fixed deadlock bug in Windows sockets due to losing an +event. This was happening because of an interaction between buffering and +nonblocking mode on sockets. Now switched to sockets being blocking by +default, so we are also no longer emulating blocking through a private +event loop. (JL) + +1/21/97 (performance bug fix) Client TCP connections were slow to create +because getservbyname was always called on the port. Now this is only +done if Tcl_GetInt fails. (BW) + +1/21/97 (configuration fix) Made it possible to override TCL_PACKAGE_PATH +during make. Previously it was only set during autoconf process. + +1/29/97 (bug fix) Fixed some problems with the clock command that +impacted how dates were scaned after the year 2000. (RJ) + +----------------- Released 7.6p2, 1/31/97 ----------------------- + +2/5/97 (bug fix) Fixed a bug where in CR-LF translation mode, \r bytes +in the input stream were not being handled correctly. (JL) + +2/24/97 (bug fix) Fix bug with exec under Win32s not being able to create +stderr file which caused all execs to fail. Fixed temp file leak under +Win32s. Fixed optional parameter bug with SearchPath that only happened +under Win32s 1.25. (CCS) + +---------------------------------------------------------- +Changes for Tcl 7.6 go above this line. +Changes for Tcl 7.7 go below this line. +---------------------------------------------------------- + +5/8/96 (new feature) Added Tcl_Ungets C API for putting a sequence of bytes +into a channel's input buffer. This can be used for "push" model channels +where the input is obtained via callbacks instead of by request of the +generic IO code. No Tcl procedure yet. (JL) + +11/15/96 (new feature) Implemented hidden commands. New C APIs: + Tcl_HideCommand -- hides an existing exposed command. + Tcl_ExposeCommand -- exposes an existing hidden command. +New tcl APIs: + interp invokehidden -- invokes a hidden command in a slave. + interp hide -- hides an existing exposed command. + interp expose -- exposes an existing hidden command. + interp hidden -- returns a list of hidden commands. +The implementation of Safe Tcl now uses the new hidden commands facility +to implement the safe base, instead of deleting the commands from a safe +interpreter. (JL) + +11/15/96 (new feature) Implemented the safe base, a mechanism for +installing and requesting security policies, purely in Tcl code. Overloads +the package command to also allow an interpreter to "require" a policy. The +following new library commands are provided: + tcl_safeCreateInterp -- creates a slave an initializes the + policy mechanism. + tcl_safeInitInterp -- initializes an existing slave with the + policy mechanism. + tcl_safeDeleteInterp -- deletes a slave and deinitializes the + policy mechanism. +Added a new file to the library, safeinit.tcl, to hold implementation. (JL) +On 7/9/97, removed the policy loading mechanism from the Safe Base. Left +only the Safe Base aliases dealing with auto-loading and source. (JL) + +12/6/96 (new feature) Implemented Tcl_Finalize, an API that should be +called by a process when it is done using Tcl. This API runs all the exit +handlers to allow them to clean up resources etc. (JL) + +12/17/96 (new feature) Add an http Tcl script package to the Tcl library. +This package implements the client side of HTTP/1.0; the GET, HEAD, +and POST requests. (BW) + +1/21/97 (new feature) Added a "marktrusted" subcommand to the "interp" and +to the interpreter object command. It removes the "safe" mark on an +interpreter and disables hard-wired checks for safety in the C sources. (JL) + +1/21/97 (removed feature) Removed "vwait" from set of commands available in +a safe interpreter. (JL) + +2/11/97 (new feature, bug fix) http package. Added -accept to http_config +so you can set the Accept header. Added -handler option to http_get so +you can supply your own data handler. Also fixed POST operation to +set the correct MIME type on the request. (BW) + +---------------------------------------------------------- +Changes for Tcl 7.7 go above this line. +Changes for Tcl 8.0 go below this line. +---------------------------------------------------------- + +9/17/96 (bug fix) Using "upvar" it was possible to turn an array element +into an array itself. Changed to disallow this; it was quirky and didn't +really work correctly anyway. (JO) + +10/21/96 (new feature) The core of the Tcl interpreter has been replaced +with an on-the-fly compiler that translates Tcl scripts to bytecoded +instructions; a new interpreter then executes the bytecodes. The compiler +introduces only a few minor changes at the level of Tcl scripts. The biggest +changes are to expressions and lists. + - A second level of substitutions is no longer done for expressions. + This substantially improves their execution time. This means that + the expression "$x*4" produces a different result than in the past + if x is "$y+2". Fortunately, not much code depends on the old + two-level semantics. Some expressions that do, such as + "expr [join $list +]" can be recoded to work in Tcl8.0 by adding + an eval: e.g., "eval expr [join $list +]". + - Lists are now completely parsed on the first list operation to + create a faster internal representation. In the past, if you had a + misformed list but the erroneous part was after the point you + inserted or extracted an element, then you never saw an error. + In Tcl8.0 an error will be reported. This should only effect + incorrect programs that took advantage of behavior of the old + implementation that was not documented in the man pages. +Other changes to Tcl scripts are discussed in the web page at +http://www.scriptics.com/doc/compiler.html. (BL) +*** POTENTIAL INCOMPATIBILITY *** + +10/21/96 (new feature) In earlier versions of Tcl, strings were used as a +universal representation; in Tcl 8.0 strings are replaced with Tcl_Obj +structures ("objects") that can hold both a string value and an internal +form such as a binary integer or compiled bytecodes. The new objects make it +possible to store information in efficient internal forms and avoid the +constant translations to and from strings that occurred with the old +interpreter. There are new many new C APIs for managing objects. Some of the +new library procedures for objects (such as Tcl_EvalObj) resemble existing +string-based procedures (such as Tcl_Eval) but take advantage of the +internal form stored in Tcl objects for greater speed. Other new procedures +manage objects and allow extension writers to define new kinds of objects. +See the manual entries doc/*Obj*.3 (BL) + +10/24/96 (bug fix) Fixed memory leak on exit caused by some IO related +data structures not being deallocated on exit because their refcount was +artificially boosted. (JL) + +10/24/96 (bug fix) Fixed core dump in Tcl_Close if called with NULL +Tcl_Channel. (JL) + +11/19/96 (new feature) Added library procedures for finding word +breaks in strings in a platform specific manner. See the library.n +manual entry for more information. (SS) + +11/22/96 (feature improvements) Added support for different levels of +tracing during bytecode compilation and execution. This should help in +tracking down suspected problems with the compiler or with converting +existing code to use Tcl8.0. Two global Tcl variables, traceCompile +and traceExec, can be set to generate tracing information in stdout: + - traceCompile: 0 no tracing (default) + 1 trace compilations of top level commands and procs + 2 trace and display instructions for all compilations + - traceExec: 0 no tracing + 1 trace only calls to Tcl procs + 2 trace invocations of all commands including procs + 3 detailed trace showing the result of each instruction +traceExec >= 2 provides a one line summary of each called command and +its arguments. Commands that have been "compiled away" such as set are +not shown. (BL) + +11/30/96 (bug fix) The command "info nameofexecutable" could sometimes +return the name of a directory. (JO) + +11/30/96 (feature improvements) Changed the code in library/init.tcl +that reads in pkgIndex.tcl so that (a) it reads the files from child +directories before those in the parent, so that the parent gets +precedence, and (b) it doesn't quit if there is an error in a +pkgIndex.tcl file; instead, it prints an error message on standard +error and continues. (JO) + +10/5/96 (feature improvements) Partial implementation of binary string +support: the ability for Tcl string values to contain embedded null bytes. +Changed the Tcl object-based APIs to take a byte pointer and length pair +instead of a null-terminated C string. Modified several object type managers +to support binary strings but not, for example, the list type manager. +Existing string-based C APIs are unchanged and will truncate binary +strings. Compiled scripts containing nulls are also truncated. (BL) + +12/12/96 (feature change) Removed the commands "cp", "mkdir", "mv", +"rm", and "rmdir" from the Macintosh version of Tcl. They were never +officially supported and their functionality is now available via +the file command. (RJ) + +----------------- Released 8.0a1, 12/20/96 ----------------------- + +1/7/97 (bug fix) Under Windows, "file stat c:" was returning error instead +of stat for current dir on c: drive. + +1/10/97 (new feature) Added Tcl_GetIndexFromObj procedure for quick +lookups of keyword arguments. (JO) + +1/12/97 (new feature) Serial IO channel drivers for Windows and Unix, +available by using Tcl open command to open pseudo-files like "com1:" or +"/dev/ttya". New option to Tcl fconfigure command for serial files: +"-mode baud,parity,data,stop" to specify baud rate, parity, data bits, and +stop bits. Serial IO is not yet available on Mac. + +1/16/97 (feature change) Restored the Tcl7.x "two level substitution +semantics" for expressions. Expressions not enclosed in braces are +implemented, in general, by calling the expr command procedure +(Tcl_ExprObjCmd) at runtime after the Tcl interpreter has already done a +first round of substitutions. This is slow (about Tcl7.x speed) because new +code for the expression is generally compiled each time. However, if the +expression has only variable substitutions (and not command substitutions), +"optimistic" fast code is generated inline. This inline code will fail if a +second round of substitutions is needed (i.e., if the value of a substituted +variable itself requires more substitutions). The optimistic code will +catch the error and back off to call the slower but guaranteed correct +expr command procedure. (BL) + +1/16/97 (feature improvements) Added Tcl_ExprLongObj and Tcl_ExprDoubleObj +to round out expression-related procedures. (BL) + +1/16/97 (feature change) Under Windows, at startup the environment variables +"path", "comspec", and "windir" in any capitalization are converted +automatically to upper case. The PATH variable could be spelled as path, +Path, PaTh, etc. and it makes programming rather annoying. All other +environment variables are left alone. (CS) + +1/20/97 (new features) Rewrote the "lsort" command: + - The new version is based on reentrant merge sort code provided + by Richard Hipp, so it eliminates the reentrancy and stability + problems with the old qsort-based implementation. + - The new version supports a -dictionary option for sorting, and + it also supports a -index option for sorting lists using one + element for comparison. + - The new version is an object command, so it works well with the + Tcl compiler, especially in conjunction with the new -index + option. When the -index option is used, this version of lsort + is more than 100 times faster than the Tcl 7.6 lsort, which had + to use the -command option to get the same effect. (JO) + +1/20/97 (feature improvements) Added the improved debugging support for Tcl +objects prototyped by Karl Lehenbauer . +If TCL_MEM_DEBUG is defined, the object creation calls use Tcl_DbCkalloc +directly in order to record the caller's source file name and line +number. (BL) + +1/21/97 (removed feature) Desupported the tcl_precision variable: if +set, it is ignored. Tcl now uses the full 17 digits of precision when +converting real numbers to strings (with the new object system real +numbers are rarely converted to strings so there is no efficiency +disadvantage to printing all 17 digits; the new scheme improves +accuracy and simplifies several APIs). (JO) +*** POTENTIAL INCOMPATIBILITY *** + +1/21/97 (feature change) Removed the "interp" argument for the +procedures Tcl_GetStringFromObj, Tcl_StringObjAppend, and +Tcl_StringObjAppendObj. Also removed the "interp" argument for +the updateStringProc procedure in Tcl_ObjType structures. With +the tcl_precision changes above, these are no longer needed. (JO) +*** POTENTIAL INCOMPATIBILITY with Tcl 8.0a1, but not with Tcl 7.6 *** + +1/22/97 (bug fix) Fixed http.tcl so that http_reset does not result in +an extra call to the command callback. In addition, if the transaction +gets a premature eof, the state(status) is "eof", not "ok". (BW) + +----------------- Released 8.0a2, 1/24/97 ----------------------- + +1/29/97 (feature change) Changed how two digit years are parsed in the +clock command. The old interface just added 1900 which will seem +broken by the year 2000. The new scheme follows the POSIX standard +and treats dates 70-99 as 1970-1999 and dates 00-38 as 2000-2038. All +other two digit dates are undefined. (RJ) +*** POTENTIAL INCOMPATIBILITY *** + +2/4/97 (bug fix) Fixed bug in clock code that dealt with relative +dates. Using the relative month code you could get an invalid date +because it jumped into a non-existant day. (For example, Jan 31 +to Feb 31.) The code now will return the last valid day of the +month in these situations. Thanks to Hume Smith for sending in +this bug fix. (RJ) + +2/10/97 (feature change) Eliminated Tcl_StringObjAppend and +Tcl_StringObjAppendObj procedures, replaced them with Tcl_AppendToObj +and Tcl_AppendStringsToObj procedures. Added new procedure +Tcl_SetObjLength. (JO) +*** POTENTIAL INCOMPATIBILITY with Tcl 8.0a2, but not with Tcl 7.6 *** + +2/10/97 (new feature) Added Tcl_WrongNumArgs procedure for generating +error messages about incorrect number of arguments. (JO) + +2/11/97 (new feature, bug fix) http package. Added -accept to http_config +so you can set the Accept header. Added -handler option to http_get so +you can supply your own data handler. Also fixed POST operation to +set the correct MIME type on the request. (BW) + +2/22/97 (bug fix) Fixed bug that caused $tcl_platform(osVersion) to be +computed incorrectly under AIX. (JO) + +2/25/97 (new feature, feature change) Added support for both int and long +integer objects. Added Tcl_NewLongObj/Tcl_GetLongFromObj/Tcl_SetLongFromObj +procedures and renamed the Tcl_Obj internalRep intValue member to +longValue. Tcl_GetIntFromObj now checks for integer values too large to +represent as non-long integers. Changed Tcl_GetAllObjTypes to +Tcl_AppendAllObjTypes. (BL) + +3/5/97 (new feature) Added new Tcl_SetListObj procedure to round out +collection of procedures that set the type and value of existing Tcl +objects. (BL) + +3/6/97 (new feature) Added -global flag for interp invokehidden. (JL) + +3/6/97 (new feature, feature change) Added isNativeObjectProc field to the +Tcl_CmdInfo structure to indicate (when 1) if the command has an +object-based command procedure. Removed the nameLength arg from +Tcl_CreateObjCommand since command names can't contain null characters. (BL) + +3/6/97 (bug fix) Fixed bug in "unknown" procedure that caused auto- +loading to fail on commands whose names begin with digits. (JO) + +3/7/97 (bug fix) Auto-loading now works in Safe Base. Safe interpreters +only accept the Version 2 and onwards tclIndex files. (JL) + +3/13/97 (bug fix) Fixed core dump due to interaction between aliases and +hidden commands. Bug found by Lindsay Marshall. (JL) + +3/14/97 (bug fix) Fixed mac bugs relating to time. The -gmt option +now adjusts the time in the correct direction. (Thanks to Ed Hume for +reporting a fix to this problem.) Also fixed file "mtime" etc. to +return times from GMT rather than local time zone. (RJ) + +3/18/97 (feature change) Declaration of objv in Tcl_ObjCmdProc function +changed from "Tcl_Obj *objv[]" to "Tcl_Obj *CONST objv[]". All Tcl object +commands changed to use new declaration of objv. Naive translation of +string-based command procs to object-based command procs could very easily +have yielded code where the contents of the objv array were changed. This +is not a problem with string-based command procs, but doing something as +simple as objv[2] = objv[3] would corrupt the runtime stack and cause Tcl to +crash. Introduced CONST in declaration of objv so that attempted assignment +of new pointer values to elements of the objv array will be caught by the +compiler. (CCS) +*** POTENTIAL INCOMPATIBILITY with Tcl 8.0a2 *** + +3/19/97 (bug fix) Fixed panic due to object sharing. The root cause was +that old code was using Tcl_ResetResult instead of Tcl_ResetObjResult. (JL) + +3/20/97 (new feature) Added a new subcommand for the file +command. file attributes filename can give a list of platform-specific +options (such as file/creator type on the Mac, permissions on Unix) or +set the values of them. Added a new subcommand for the file +command. file nativename name gives back the platform-specific form +for the file. This is useful when the filename is needed to pass to +the OS, such as exec under Windows 95 or AppleScript on the Mac. For +more info, see file.n. (SRP) + +3/24/97 (removed feature) Removed the tcl_safePolicyPath procedure. Now +the policy path is computed from the auto_path by appending the directory +'policies' to each element. Also fixed several bugs in automatic tracking +of auto_path by computed policy path. (JL) +*** POTENTIAL INCOMPATIBILITY with Tcl 8.0a2 but not with Tcl 7.6 *** + +4/8/97 (new feature) If the variable whose name is passed to lappend doesn't +already exist, and there are no value arguments, lappend now creates the +variable with an empty value instead of returning an error. Change suggested +by Tom Tromey. (BL) + +4/9/97 (feature change) Changed the name of the TCL_PART1_NOT_PARSED flag to +TCL_PARSE_PART1. (BL) +*** POTENTIAL INCOMPATIBILITY with Tcl 8.0a2 but not with Tcl 7.6 *** + +4/10/97 (bug fixes) Fixed various compilation-related bugs: + - "UpdateStringOfCmdName should never be invoked" panic. + - Bad code generated for expressions not in {}'s inside catch commands. + - Segmentation fault in some command procedures when two argument + object pointers refer to the same object. + - Second level of substitutions were never done for expressions not + in {}'s that consist of a single variable reference: e.g., + "set x 27; set bool {$x}; if $bool {puts foo}" would fail with error. + - Bad code generated when code storage was grown while compiling some + expressions: ones with compilation errors or consisting of only a + variable reference. + - Bugs involving multiple interpreters: wasn't checking that a + procedure's code was compiled for the same interpreter as the one + executing it, and didn't invalidate code on hidden-exposed command + transitions. + - "Bad stack top" panic when executing scripts that require a huge + amount of stack space. + - Incorrect sharing of code for procedure bodies, and procedure code + deallocated before last execution of the procedure finished. + - Fixed compilation of expression words in quotes. For example, + if "0 < 3" {puts foo}. + - Fixed performance bug in array set command with large assignments. + - Tcl_SetObjLength segmentation fault setting length of empty object. + - If Tcl_SetObjectResult was passed the same object as the interpreter's + result object, it freed the object instead of doing nothing. Bug fix + by Michael J. McLennan. + - Tcl_ListObjAppendList inserted elements from the wrong list. Bug fix + by Michael J. McLennan. + - Segmentation fault if empty variable list was specified in a foreach + command. Bug fix by Jan Nijtmans. + - NULL command name was always passed to Tcl_CreateTrace callback + procedure. + - Wrong string representation generated for the value LONG_MIN. + For example, expr 1<<31 printed incorrectly on a 32 bit machine. + - "set {a($x)} 1" stored value in wrong variable. + - Tcl_GetBooleanFromObj was not checking for garbage after a numeric + value. + - Garbled "bad operand type" error message when evaluating expressions + not surrounded by {}'s. (BL) + +4/16/97 (new feature) The expr command now has the "rand()" and +"srand()" functions for getting random numbers in expr. (RJ) + +4/23/97 (bug fix) Fixed core dump in bgerror when the error handler command +deletes the current interpreter. Found by Juergen Schoenwald. (JL) + +4/23/97 (feature change) The notifier interfaces have been redesigned +to make embedding in applications with external event loops possible. +A number of interfaces in the notifier and the channel drivers have +changed. Refer to the Notifier.3 and CrtChannel.3 manual entries for +more details. (SS) +*** POTENTIAL INCOMPATIBILITY *** + +4/23/97 (removed feature) The Tcl_File interfaces have been removed. +The Tcl_CreateFileHandler/Tcl_DeleteFileHandler interfaces now take +Unix fd's and are only supported on the Unix platform. +Tcl_GetChannelFile has been replaced with Tcl_GetChannelHandle. +Tcl_MakeFileChannel now takes a platform specific file handle. (SS) +*** POTENTIAL INCOMPATIBILITY *** + +4/23/97 (removed feature) The modal timeout interface has been +removed (Tcl_CreateModalTimeout/Tcl_DeleteModalTimeout) (SS) +*** POTENTIAL INCOMPATIBILITY *** + +4/23/97 (feature change) Channel drivers are now required to correctly +implement blocking behavior when they are in blocking mode. (SS) +*** POTENTIAL INCOMPATIBILITY *** + +4/23/97 (new feature) Added the "binary" command for manipulating +binary strings. Also, changed the "puts", "gets", and "read" commands +to preserve embedded nulls. (SS) + +4/23/97 (new feature) Added tcl_platform(byteOrder) element to the +tcl_platform array to identify the native byte order for the current +host. (SS) + +4/23/97 (bug fix) Fixed bug in date parsing around year boundaries. (SS) + +4/24/97 (bug fix) In the process of copying a file owned by another user, +Tcl was changing the owner of the copy back to the owner of the original +file, therefore causing further file operations to fail because the current +user didn't own the copy anymore. The owner of the copy is now left as the +current user. (CCS) + +4/24/97 (feature change) Under Windows, don't automatically uppercase the +environment variable "windir" -- it's supposed to be lower case. (CCS) + +4/29/97 (new feature) Added namespace support based on a namespace +implementation by Michael J. McLennan of Lucent Technologies. A namespace +encapsulates a collection of commands and variables to ensure that they +won't interfere the commands and variables of other namespaces. The global +namespace holds all global variables and commands. Additional namespaces are +created with the new namespace command. The new variable command lets you +create Tcl variables inside a namespace. The names of Tcl variables and +commands may now be qualified by the name of the namespace containing them. +The key namespace-related commands are summarized below: + - namespace ?eval? name arg ?arg...? + Used to define the commands and variables in a namespace. + Optionally creates the namespace. + - namespace export ?-clear? ?pattern pattern...? + Specifies which commands are exported from a namespace. These + are the ones that can be imported into another namespace. + - namespace import ?-force? ?pattern pattern...? + Makes the specified commands accessible in the current namespace. + - namespace current + Returns the name of the current namespace. + - variable name ?value? ?name ?value?...? + Creates one or more namespace variables. (BTL) + +5/1/97 (bug fix) Under Windows, file times were reported in GMT. Should be +reported in local time. (CCS) + +5/2/97 (feature change) Changed the name of the two Tcl variables used for +tracing bytecode compilation and execution to tcl_traceCompile and +tcl_traceExec respectively. These variables are now documented in the +tclvars man page. (BL) + +5/5/97 (new feature) Support "end" as the index for "lsort -index". (BW) + +5/5/97 (bug fixes) Cleaned up the way the http package resets connections (BW) + +5/8/97 (feature change) Newly created Tcl objects now have a reference count +of zero instead of one. This simplifies C code that stores newly created +objects in Tcl variables or in data structures such as list objects. That C +code must increment the new object's reference count since the variable or +data structure will contain a long-term reference to the object. Formerly, +when new objects started out with reference count one, it was necessary to +decrement the new object's reference count after the store to make sure it +was left with the correct value; this is no longer necessary. (BL) + +5/9/97 (new feature) Added the Tcl_GetsObj interface that takes an +object reference instead of a dynamic string (as in Tcl_Gets). (SS) + +5/12/97 (new feature) Added Tcl_CreateAliasObj and Tcl_GetAliasObj C APIs +to allow an alias command to be created with a vector of Tcl_Obj structures +and to get the vector back later. (JL) + +5/12/97 (feature change) Changed Tcl_ExposeCommand and Tcl_HideCommand to +leave an object result instead of a string result. (JL) + +5/14/97 (feature change) Improved the handling of the interpreter result. +This is still either an object or a string, but the two values are now kept +consistent unless some C code reads or writes interp->result directly. See +the SetResult man page for details. Removed the Tcl_ResetObjResult +procedure. (BL) +*** POTENTIAL INCOMPATIBILITY with Tcl 8.0a2 *** + +5/16/97 (new feature) Added "fcopy" command to move data between +channels. Refer to the manual page for more information. Removed the +"unsupported0" command since it is obsolete now. (SS) + +5/16/97 (new feature) Added Tcl_GetStringResult procedure to allow programs +to get an interpreter's result as a string. If the result was previously set +to an object, this procedure will convert the object to a string. Use of +Tcl_GetStringResult is intended to replace direct access to interp->result, +which is not safe. (BL) + +5/20/97 (new features) Fixed "fcopy" to return the number of bytes +transferred in the blocking case. Updated the http package to use +fcopy instead of unsupported0. Added -timeout and -handler options to +http_get. http_get is now blocking by default. It is only non-blocking +if you supply a -command argument. (BW) + +5/22/97 (bug fix) Fixed several bugs in the "lsort" command having to do +with the -dictionary option and the presence of numbers embedded in the +strings. (JO) + +----------------- Released 8.0b1, 5/27/97 ----------------------- + +6/2/97 (bug fix) Fixed bug in startup code that caused a problem in +finding the library files when they are installed in a directory +containing a space in the name. (SS) + +6/2/97 (bug fix) Fixed bug in Unix notifier where the select mask was +not being cleared under some circumstances. (SS) + +6/4/97 (bug fix) Fixed bug that prevented creation of Tk widgets in +namespaces. Tcl_CreateObjCommand and Tcl_CreateCommand now always create +commands in the global namespace unless the command names are qualified. Tcl +procedures continue to be created in the current namespace by default. (BL) + +6/6/97 (new features) Added new namespace API procedures +Tcl_AppendExportList and Tcl_Export to allow C code to get and set a +namespace's export list. (BL) + +6/11/97 (new feature) Added Tcl_ConcatObj. This object-based routine +parallels the string-based routine Tcl_Concat. (SRP) + +6/11/97 (new feature) Added Tcl_SetObjErrorCode. This object-based +routines parallels the string-based routine Tcl_SetErrorCode. (SRP) + +6/12/97 (bug fix) Fix the "unknown" procedure so that wish under Windows +will exec an external program, instead of always complaining "console1 not +opened for writing". (CCS) + +6/12/97 (bug fix) Fixed core dump experienced by the following simple +script: + interp create x + x alias exec exec + interp delete x +This panic was caused by not installing the new CmdDeleteProc when exec +got redefined by the alias creation step. Reported by Lindsay Marshal (JL) + +6/13/97 (new features) Tcl objects newly created by Tcl_NewObj now have a +string representation that points to a shared heap string of length 1. (They +used to have NULL bytes and typePtr fields. This was treated as a special +case to indicate an empty string, but made type manager implementations +complex and error prone.) The new procedure Tcl_InvalidateStringRep is used +to mark an object's string representation invalid and to free any storage +associated with the old string representation. (BL) +*** POTENTIAL INCOMPATIBILITY with Tcl 8.0b1, but not with Tcl7.6 *** + +6/16/97 (bug fix) Tcl_ScanCountedElement could leave braces unmatched +if the string ended with a backslash. (JO) + +6/17/97 (bug fix) Fixed channel event bug where readable events would be +lost during recursive events loops if the input buffers contained +data. (SS) + +6/17/97 (bug fix) Fixed bug in Windows socket code that didn't +reenable read events in the case where an external entity is also +reading from the socket. (SS) + +6/18/97 (bug fix) Changed initial setting of the notifier service mode +to TCL_SERVICE_NONE to avoid unexpected event handling during +initialization. (SS) + +6/19/97 (bug fix/feature change) The command callback to fcopy is now +called in case of errors during the background copy. This adds a second, +optional argument to the callback that is the error string. The callback +in case of errors is required for proper cleanup by the user of fcopy. (BW) +*** POTENTIAL INCOMPATIBILITY with Tcl 8.0b1, but not with Tcl 7.6 *** + +6/19/97 (bug fix) Fixed a panic due to the following four line script: + interp create x + x alias foo bar + x eval rename foo blotz + x alias foo {} +The problem was that the interp code was not using the actual current name +of the command to be deleted as a result of un-aliasing foo. (JL) + +6/19/97 (feature change) Pass interp down to the ChannelOption and +driver specific calls so system errors can be differentiated from syntax +ones. Changed Tcl_DriverGetOptionProc type. Affects Tcl_GetChannelOption, +TcpGetOptionProc, TtyGetOptionProc, etc. (DL) +*** POTENTIAL INCOMPATIBILITY *** + +6/19/97 (new feature) Added Tcl_BadChannelOption for use by by driver +specific option procedures (Set and Get) to return a complete and +meaningful error message. (DL) + +6/19/97 (bug fixes) If a system call error occurs while doing an +fconfigure on tcp or tty/com channel: return the appropriate error +message (instead of the syntax error one or none). (Fixed for Unix and +most of the Win and Mac drivers). (DL) + +6/20/97 (feature change) Eval is no longer assumed as the subcommand name +in namespace commands: you must now write "namespace eval nsName {...}". +Abbreviations of namespace subcommand names are now allowed. (BL) +*** POTENTIAL INCOMPATIBILITY with Tcl 8.0b1, but not with Tcl7.6 *** + +6/20/97 (feature change) Changed the errorInfo traceback message for +compilation errors from "invoked from within" to "while compiling". (BL) + +6/20/97 (bug fixes) Fixed various compilation-related bugs: + - "UpdateStringOfCmdName should never be called" and + "UpdateStringOfByteCode should never be called" panics. + - Segfault in TclObjInterpProc getting procedure name after evaluation + stack is reallocated (grown). + - Could not use ":" at end of variable and command names. + - Bad code generated for while and for commands with test expressions + enclosed in quotes: e.g., "set i 0; while "$i > 5" {}". + - Command trace procedures would crash if they did a Tcl_EvalObj that + reallocated the evaluation stack. + - Break and continue commands did not reset the interpreter result. + - The Tcl_ExprXXX routines, both string- or object-based, always + modified the interpreter result even if there was no error. + - The argument parsing procedure used by several compile procedures + always treated "]" as end of a command: e.g., "set a ]" would fail. + - Changed errorInfo traceback message for compilation errors from + "invoked from within" to "while compiling". + - Problem initializing Tcl object managers during interpreter creation. + - Added check and error message if formal parameter to a procedure is + an array element. (BL) + +6/23/97 (new feature) Added "registry" package to allow manipulation +of the Windows system registry. See manual entry for details. (SS) + +6/24/97 (feature change) Converted http to a package and added the +http1.0 subdirectory of the Tcl script library. This means you have +to do a "package require http" to use this, as advertised in the man page. (BW) +*** POTENTIAL INCOMPATIBILITY with Tcl 8.0b1, but not with Tcl 7.6 *** + +6/24/97 (bug fix) Ensure that Tcl_Set/GetVar C APIs, when called without +TCL_LEAVE_ERR_MSG, don't touch the interp result. (DL) + +6/26/97 (feature change) Changed name of Tcl_ExprStringObj to +Tcl_ExprObj. (BL) +*** POTENTIAL INCOMPATIBILITY with Tcl 8.0b1, but not with Tcl 7.6 *** + +----------------- Released 8.0b2, 6/30/97 ----------------------- + +7/1/97 (new feature) TCL_BUILD_SHARED flag set in tclConfig.sh +when Tcl has been built with --enable-shared. A new tclLibObjs +make target, echoing the list of the .o's needed to build a tcl +library, is now provided. (DL) + +7/1/97 (feature change) compat/getcwd.c removed and changed the +only place where getcwd is used so a new USEGETWD flag selects +the use of the replacement "getwd". Adding this flag is recommended +for SunOS 4 (because getcwd on SunOS 4 uses a pipe to pwd(1)!). (DL) + +7/7/97 (feature change) The split command now supports binary data (i.e., +null characters in strings). (BL) + +7/7/97 (bug fix) string first returned the wrong result if the first +argument string was empty. (BL) + +7/8/97 (bug fix) Fixed core dump in fcopy that could occur when a command +callback was supplied and an error or eof condition caused no background +activity. A refcount bug triggered a panic in Tcl_ListObjAppendElement. (BW) + +7/8/97 (bug fix) Relaxed the pattern matching on http_get so you do not +need a trailing path component. You can now get away with just +http_get www.scriptics.com (BW) + +7/9/97 (bug fix) Creating anonymous interpreters no longer smashes existing +commands with names similar to the generated name. Previously creating an +anonymous interpreter could smash an existing command, now it skips until +it finds a command name that isn't being used. (JL) + +7/9/97 (feature change) Removed the policy management mechanism from the +Safe Base; left the aliases to source and load modules, and to do a limited +form of the "file" command. See entry of 11/15/96. (JL) + +7/9/97 (bug fixes) Fixed various compilation-related bugs: + - Line numbers in errorInfo now are the same as those in Tcl7.6 unless +there are compilation errors. Compilation error messages now include the +entire command in error. + - Trailing ::s after namespace names weren't being ignored. + - Could not refer to an namespace variable with an empty name using a +name of the form "n::". (BL) + +7/9/97 (bug fix) Fixed bug in Tcl_Export that prevented you from exporting +from other than the current namespace. (BL) + +7/9/97 (bug fix) env.test was removing env var needed for proper finding +of libraries in child process. (DL) + +7/10/97 (bug fixes/new feature) Cleanup in Tcl_MakeSafe. Less information +is leaked to safe interps. Error message fixes for interp sub commands. +Likewise changes in safealias.tcl; tcl_safeCreateInterp can now be called +without argument to generate the slave name (like in interp create). (DL) + +7/10/97 (bug fixes) Bytecode compiler now generates more detailed +command location information: subcommands as well as commands now have +location information. This means command trace procedures now get the +correct source string for each command in their command parameter. (BL) + +7/22/97 (bug fixes) Performance improvement in Safe interpreters +handling. Added new mask value to (tclInt.h) Interp.flags record. (DL) + +7/22/97 (bug fix) Fixed panic in 'interp target {} foo'. This bug +was present since Tcl 7.6. (JL) + +7/22/97 (bug fix) Fixed bug in compilation of procedures in namespaces: the +procedure's namespace must be used to look up compile procedures, not the +current namespace. (BL) + +7/22/97 (bug fix) Use of the -channel option of http_get was not setting +the end of line translations mode on the channel, so copying binary data +with the -channel option was corrupting the result on non-unix platforms. (BW) + +7/22/97 (bug fixes) file commands and ~user (seg fault and other +improper returns). (DL) + +7/23/97 (feature change) Reenabled "vwait" in Safe Base. (JL) + +7/23/97 (bug fixes) Fixed two bugs involving read traces on array variables +in procedures: trace procedures were sometimes not called, and reading +nonexistant array elements didn't create undefined element variables that +could later be defined by trace procedures. (BL) + +7/24/97 (bug fix) Windows memory allocation performance was +superlinear in some cases. Made the Mac allocator generic and changed +both the Mac and Windows platforms to use the new allocator instead of +malloc and free. (SS) + +7/24/97 - 8/12/97 (bug fixes/change of features) Completely revamped safe +sourcing/loading (see safe.n) to hide pathnames, use virtual +paths tokens instead, improved security in several respects and made it +more tunable. Multi level interp loading can work too now. Package auto +loading now works in safe interps as long as the package directory is in +the auto_path (no deep crawling allowed in safe interps). (DL) +*** POTENTIAL INCOMPATIBILITY with previous alpha and beta releases *** + +7/24/97 (bug fixes) Made Tcl_SetVar* and Tcl_NewString* treat a NULL value +as an empty string. (This fixes hairy crash case where you would crash +because load command for other interps assumed presence of +errorInfo...). (DL) + +7/28/97 (bug fix) Fixed pkg_mkIndex to understand namespaces. It will +use the export list of a namespace and create auto_index entries for +all export commands. Those names are in their fully qualified form in the +auto_index. Therefore, I tweaked unknown to try both $cmd and ::$cmd. +Also fixed pkg_mkIndex so you can have "package require" commands inside +your packages. These commands are ignored, which is mostly ok except +when you must load another package before loading yours because of +linking dependencies. (BW) + +7/28/97 (bug fix) A variable created by the variable command now persists +until the namespace is destroyed or the variable is unset. This is true even +if the variable has not been initialized; these variables used to be +destroyed if an error occurred when accessing them. In addition, the "info +vars" command lists uninitialized namespace variables, while the "info +exists" command returns 0 for them. (BL) + +7/29/97 (feature change) Changed the http package to use the ::http +namespace. http_get renamed to http::geturl, http_config renamed to +http::config, http_formatQuery renamed to http::formatQuery. +It now provides the 2.0 version of the package. +The 1.0 version is still available with the old names. +*** POTENTIAL INCOMPATIBILITY with Tcl 8.0b2 but not with Tcl 7.6 *** + +7/29/97 (bug fix, new feature) Tcl_Main now uses Tcl objects internally to +preserve NULLs in commands and command output. Added new API procedure +Tcl_RecordAndEvalObj that resembles Tcl_RecordAndEval but takes an object +containing a command. (BL) + +7/30/97 (bug fix) Tcl freed strings in the environ array even if it +did not allocate them. (SS) + +7/30/97 (bug fix) If a procedure is renamed into a different namespace, it +now executes in the context of that namespace. (BL) + +7/30/97 (bug fix) Prevent renaming of commands into and from namespaces as +part of hiding them. (JL) + +7/31/97 (feature change) Moved the history command from C to tcl. +This uses the ::history namespace. The "words" and "substitute" options +are no longer supported. In addition, the "keep" option without a value +returns the current keep limit. There is a new "clear" option. +The unknown command now supports !! again. (BW) +*** POTENTIAL INCOMPATIBILTY *** + +7/30/97 (bug fix) Made sure that a slave can not fool the master into +hiding the wrong command. Made sure we don't crash in hiding + namespaces +issues. (DL) + +8/4/97 (bug fix) Concat, eval, uplevel, and similar commands were +incorrectly trimming trailing space characters from their arguments +even when the space characters were preceded by a backslash. (JO) + +8/4/97 (bug fix) Removed the hard link between bgerror and tkerror. +Only bgerror is supported in tcl core. Tk will still look for a +tkerror but using regular tcl code for that feature. (DL) +*** POTENTIAL INCOMPATIBILTY with code relying on the hard link *** + +8/6/97 (bug fix) Reduced size required for compiled bytecodes by using a +more compact encoding for the command pc-to-source map. (BL) + +8/6/97 (new feature) Added support for additional compilation and execution +statistics when Tcl is compiled with the TCL_COMPILE_STATS flag. (BL) + +8/7/97 (bug fix) Expressions not in {}s that have a comparison operator as +the topmost operator must be compiled out-of-line (call the expr cmd at +runtime) to properly support expr's two-level substitution semantics. An +example is "set a 2; set b {$a}; puts [expr $b == 2]". (BL) + +8/11/97 (bug fix) The catch command would sometimes crash if a variable name +was given and the bytecode evaluation stack was grown when executing the +argument script. (BL) + +8/12/97 (feature change) Reinstated the variable tcl_precision to control +the number of digits used when floating-point values are converted to +strings, with default of 12 digits. However, had to make tcl_precision +shared among all interpreters (except that safe interpreters can't +modify it). This makes the Tcl 8.0 behavior almost identical to 7.6 +except that the default precision is 12 instead of 6. (JO) +*** POTENTIAL INCOMPATIBILITY *** + +----------------- Released 8.0, 8/18/97 ----------------------- + +8/19/97 (bug fix) Minimal fix for glob -nocomplain bugs: +"glob -nocomplain unreadableDir/*" was generating an anonymous +error. More in depth fixes will come with 8.1. (DL). + +8/20/97 (bug fix) Removed check for FLT_MIN in binary command so +underflow conditions are handled by the compiler automatic +conversions. (SS) + +8/20/97 (bug fixes) Fixed several compilation-related bugs: + - Array cmd wasn't detecting arrays that, while compiled, do not yet + exist (e.g., are marked undefined since they haven't been assigned + to yet). + - The GetToken procedure in tclCompExpr.c wasn't recognizing properly + whether an integer token was invalid. For example, "0x$" is not + a valid integer. + - Performance bug in TclExecuteByteCode: the size of its stack frame + was reduced by over 20% by moving errorInfo code elsewhere. + - Uninitialized memory read error in tclCompile.c. (BL) + +8/21/97 (bug fix) safe::interpConfigure now behave like Tk widget's +configure : it changes only the options you provide and you can get +the current value of any single option. New ?-nested boolean? and +?-statics boolean? for all safe::interp* commands but we still +accept (upward compatibility) the previously defined non valued +flags ?-noStatics? and ?-nestedLoadOk?. Improved the documentation. (DL). + +8/22/97 (bug fix) Updated PrintDbl.3 to reflect the fact that the +tcl_precision variable is still used and that it is now shared by all +interpreters. (BL) + +8/25/97 (bug fix) Fixed array access bug in IllegalExprOperandType +procedure in tclExecute.c: it was not properly supporting the || and && +operators. (BL) + +8/27/97 (bug fix) In cases where a channel handler was created with an +empty event mask while data was still buffered in the channel, the +channel code would get stuck spinning on a timer that would starve +idle handlers. This mostly happened in Tk when reading from stdin. (SS) + +9/4/97 (bug fix) Slave interps now inherit the maximum recursion limit +of their parent instead of starting back at the default. {nb: this still +does not prevent stack overflow by multi-interps recursion or aliasing} (DL) + +9/11/97 (bug fix) An uninitialized variable in Tcl_WaitPid caused +pipes to fail to report eof properly under Windows. (SS) + +9/12/97 (bug fix) "exec" was misidentifying some DOS executables as not +executable. (CCS) + +9/14/97 (bug fix) Was using the wrong structure in sizeof operation in +tclUnixChan.c. (JL) + +9/15/97 (bug fix) Fixed notifier to break out of do-one-event loop if +Tcl_WaitForEvent returns 1, so that callers of Tcl_DoOneEvent will get +a chance to check whether the event just handled is significant. This +affected mainly recursive calls to Tcl_VWaitCmd; these did not get a +chance to notice that the variable they were waiting for has been set +and thus they didn't terminate the vwait. (JL, DL, SS) + +9/15/97 (bug fix) Alignment problems in "binary format" would cause a +crash on some platforms when formatting floating point numbers. (SS) + +9/15/97 (bug fix) Fixed bug in Macintosh socket code. Now passes all +tests in socket.test that are not platform specific. (Thanks to Mark +Roseman for the pointer on the fix.) (RJ) + +9/18/97 (bug fix) Fixed bug -dictionary option of lsort that could +cause the compare function to run off the end of an array if the +number only contained 0's. (Thanks to Greg Couch for the report.) (RJ) + +9/18/97 (bug fix) TclFinalizeEnvironment was not cleaning up +properly. (DL, JI) + +9/18/97 (bug fix) Fixed long-standing bug where an "array get" command +did not trigger traces on the array or its elements. (BL) + +9/18/97 (bug fixes) Fixed compilation-related bugs: + - Fixed errorInfo traceback information for toplevel coomands that + contain nested commands. + - In the expr command, && and || now accept boolean operands as well + as numeric ones. (BL) + +9/22/97 (bug fix) Fixed bug that prevented translation modes from being +set independently for input and output on sockets if input was "auto". (JL) + +9/24/97 (bug fix) Tcl_EvalFile(3) and thus source(n) now works fine on +files containing NUL chars. (DL) + +9/26/97 (bug fix) Fixed use of uninitialized memory in the environ array +that later could cause random core dumps. Applies to all platforms. (JL) + +9/26/97 (bug fix) Fixed use of uninitialized memory in socket address data +structure under some circumstances. This could cause random core dumps. +This applies only to Unix. (JL) + +9/26/97 (bug fix) Opening files on PC-NFS volumes would cause a hang +until the system timed after the file was closed. (SS) + +10/6/97 (bug fix) The join(n) command, though objectified, was loosing +NULs in the joinString and in list elements after the 2nd one. +Now you can "join $list \0" for instance. (DL) + +10/9/97 (bug fix) Under windows, if env(TMP) or env(TEMP) referred to a +non-existent directory, exec would fail when trying to create its temporary +files. (CCS) + +10/9/97 (bug fix) Under mac and windows, "info hostname" would crash if +sockets were installed but the hostname could not be determined anyhow. +Tcl_GetHostName() was returning NULL when it should have been returning +an empty string. (CCS) + +10/10/97 (bug fix) "file attribute /" returned error on windows. (CCS) + +10/10/97 (bug fix) Fixed the auto_load procedure to handle procedures +defined in namespaces better. Also fixed pgk_mkIndex so it sees procedures +defined in nested namespaces. Index entries are still only made for +exported procedures. (BW) + +10/13/97 (bug fix) On unix, for files with unknown group or owner +attributes, querying the "file attributes" would return an error rather than +returning the group's or owner's id number, although tha command accepts +numbers when setting the file's group or owner. (CCS) + +10/22/97 (bug fix) "fcopy" did not eval the callback script at the +global scope. (SS) + +10/22/97 (bug fix) Fixed the signature of the CopyDone callback used in +the http package(s) so they can handle error cases properly. (BW) + +10/28/97 (bug fixes) Fixed a problem where lappend would free the Tcl object +in a variable if a Tcl_ObjSetVar2 failed because of an error calling a trace +on the variable. (BL) + +10/28/97 (bug fix) Changed binary scan to properly handle sign +extension of integers on 64-bit or larger machines. (SS) + +11/3/97 (bug fixes) Fixed several bugs: + - expressions such as "expr ($x)" must be compiled out-of-line + (call the expr command procedure at runtime) to ensure the correct + behavior when "$x" is an expression such as "5+10". + - "array set a {}" now creates a new array var with an empty array + value if the var didn't already exist. + - "lreplace $foo end end" no longer returns an error (just an empty + list) if foo is empty. + - upvar will no longer create a variable in a namespace that refers + to a variable in a procedure. + - deleting a command trace within a command trace callback would + make the code that calls traces to reference freed memory. + - significantly sped up "string first" and "string last" (fix from + darrel@gemstone.com). + - seg fault in Tcl_NewStringObj() when a NULL is passed as the byte + pointer argument and Tcl is compiled with -DTCL_MEM_DEBUG. + - documentation and error msg fixes. (BL) + +11/3/97 (bug fix) Fixed a number of I/O bugs related to word sizes on +64-bit machines. (SS) + +11/6/97 (bug fix) The exit code of the first process created by Tcl +on Windows was not properly reported due to an initialization +problem. (SS) + +----------------- Released 8.0p1, 11/7/97 ----------------------- + +11/19/97 (bug fix) Fixed bug in linsert where it sometimes accidently +cleared out a shared argument list object. (BL). + +11/19/97 (bug fix) Autoloading in namespaces was not working properly. +auto_mkindex is still not really namespace aware but most common +cases should now be handled properly (see init.test). (BW, DL) + +11/20/97 (enhancement) Made the changes required by the new Apple +Universal Headers V.3.0, so that Tcl will compile with CW Pro 2. + +11/24/97 (bug fix) Fixed tests in clock test suite that needed the +-gmt flag set. Thanks to Jan Nijtmans for reporting the problem. (RJ) + +----------------- Released 8.0p2, 11/25/97 ----------------------- + +12/3/97 (bug fix/optimization) Removed uneeded and potentially dangerous +instances of double evaluations if "if" and "expr" statements from +the library files. It is recommended that unless you need a double +evaluation you always use "expr {...}" instead of "expr ..." and +"if {...} ..." instead of "if ... ...". It will also be faster +thanks to the byte compiler. (DL) + +---- Shipped as part of the plugin2.0b5 as 8.0p2Plugin1, Dec 8th 97 ---- + +12/8/97 (bug fix) Need to protect the newly accepted channel in an +accept callback on a socket, otherwise the callback may close it and +cause an error, which would cause the C code to attempt to close the +now deleted channel. Bumping the refcount assures that the channel sticks +around to be really closed in this case. (JL) + +12/8/97 (bug fix) Need to protect the channel in a fileevent so that it +is not deleted before the fileevent handler returns. (CS, JL) + +12/18/97 (bug fix) In the opt argument parsing package: if the description +had only flags, the "too many arguments" case was not detected. The default +value was not used for the special "args" ending argument. (DL) + +1/15/98 (improvement) Moved common part of initScript in common file. +Moved windows specific initialization to init.tcl so you can initialize +Tcl in windows without having to call Tcl_Init which is now only +searching for init.tcl {back ported from 8.1}. (DL) + +---- Shipped as part of the plugin as 8.0p2Plugin2, Jan 15th 98 ---- + +5/27/98 (bug fix) Windows socket driver did not notice new data arriving +on nonblocking sockets until the event loop was entered. (SS) + +5/27/98 (bug fix) Windows socket driver used FIONREAD, which is not +supported correctly by WinSock. (SS) + +6/9/98 (bug fix) Generic channel code failed to report readable file +events on buffered data that was left behind by a gets or read that +did not consume all available data. (SS) + +6/18/98 (bug fix) Compilation of loop expressions was too aggressive +and incorrectly inlined non-literal expressions. (SS) + +6/18/98 (bug fix) "info var" and "info locals" incorrectly reported +the existence of compiler temporary variables. (SS) + +6/18/98 (bug fix) Dictionary sorting used signed character +comparisons. (SS) + +6/18/98 (bug fix) Compile procs corrupted the exception stack in some +cases. (SS) + +6/18/98 (bug fix) Array set had erratic behavior when initializing a +variable from an empty value list. (SS) + +6/18/98 (bug fix) The Windows registry package had a bad bounds check +that could lead to a crash. (SS) + +6/18/98 (bug fix) The foreach compile proc did not correctly handle +non-local variable references. (SS) + +6/25/98 (new features) Added name resolution hooks to support [incr Tcl]. +There are new internal Tcl_*Resolver* APIs to add, query and remove the hooks. +With this changes it should be possible to dynamically load [incr Tcl] +as an extension. (MM) + +7/1/97 (bug fix) The commands "info args, body, default, procs" did +not correctly handle imported procedures. (RJ) + +7/6/98 (improvement) pkg_mkIndex now implements the "package require" +command. This makes it possible to create index files for packages +that require another package and then execute code from that package in +their file. Previously, this would throw an error because the required +package had not been loaded. The -nopkgrequied flag is provided to +revert back to the old functionality. (EMS) + +7/6/98 (improvement) back-ported the -direct flag from 8.1 into +pkg_mkIndex. This results in pkgIndex.tcl files that contain direct +source or load commands instead of tclPkgSetup commands. (EMS) + +7/6/98 (improvement) made changes to the AuxData items structures to support +storage of compiled scripts on disk. Also some related minor changes in +the compilation and execution engine. (EMS) + +6/4/98 (enhancement) Added new internal routines to support inserting +and deleting from the stat, access, and open-file-channel mechanisms. +TclAccessInsertProc, TclStatInsertProc, & TclOpenFileChannelInsertProc +insert pointers to such routines; TclAccessDeleteProc, TclStatDeleteProc, +& TclOpenFileChannelDeleteProc delete pointers to such routines. See +the file generic/tclIOUtils.c for more details. (SKS) + +7/1/98 (enhancement) Added a new internal C variable +tclPreInitScript. This is a pointer to a string that may hold an +initialization script; If this pointer is non-NULL it is evaluated in +Tcl_Init() prior to the built-in initialization script defined in the +file generic/tclInitScript.h. (SKS) + +7/6/98 (bug fix) Removed dead code in PlatformInitExitHandler so that +the TCL_LIBRARY value can be safely patched in binaries. (BW) + +7/24/98 (enhancement) Incorporated a new version of auto_mkindex that +can support the [incr Tcl] class structures. This version will index +all procedures in a source file, not just those where "proc" starts +at the beginning of the line. If you want the old behavior, use the +auto_mkindex_old procedure. (MM) + +7/24/98 (feature change) Changed the Windows registry key to be +HKEY_LOCAL_MACHINE\Software\Scriptics\Tcl\8.0, and to store the path +in the default value instead of "Root". Also, this key can be +specified at compile time in case Tcl is being used in a different +context where it needs an alternate library path from the standard Tcl +installation. (SS) + +7/24/98 (feature change) Changed the search order for init.tcl. The +tcl_library variable can now be set before calling Tcl_Init to avoid +doing any searches. If it isn't set, then Tcl checks +env(TCL_LIBRARY), the static value set at compile time, an install +directory relative to the executable, a source directory relative to +the executable, and a tcl directory relative to the source heirarchy +containing the executable. See the comment at the top of +generic/tclInitScript.h for more details. (SS) + +7/27/98 (config change) Changed the use of the DBGX flag in configure.in +and the makefile to be TCL_DBGX. Users of tclConfig.sh may need to pass +this through their configure files with AC_SUBST. (BW) + +729/98 (bug fix) Changed [info body] to return a copy of the body of a +compiled procedure instead of the body itself, to avoid invalidation +of the internal rep and loss of the byte-codes. (EMS) + +8/5/98 (bug fix) The platform init code could walk off the end of a +buffer when reading the PkgPath registry value on Windows. (SS) + +8/5/98 (Windows makefile change) Introduced a set of macros to deal with +exporting symbols when compiling DLLS on Windows. See win/README for +details. (EMS) + +8/5/98 (addendum) Added a second Windows registry key under +HKEY_LOCAL_MACHINE\Software\Scriptics\Tcl\8.0, named "pkgPath". +This is a multi-string value used to initialize the tcl_pkgPath +variable. This is required if extension DLLs are in architecture specific +subdirectories. (SS) + +8/6/98 (new feature) Added tcl_findLibrary to init.tcl for use by +extensions, including Tk. This searches in a canonical way for +an extensions library directory and initialization file. (BW) + +8/10/98 (bug fix) Imported commands used to get lost if the target +of the import was redefined. Tcl_CreateCommand and Tcl_CreateObjCommand +were updated to restore import links. (Note that if you rename a command, +the import links move to the new name, and if you delete a command then +the import links get lost. These semantics have not changed.) (MC) + +-------- Released 8.0.3 to the Tcl Consortium CD-ROM project, 8/10/98 ------ + +9/3/98 (bug fix) Tcl_Realloc was failing under Windows because the +GlobalReAlloc API was not correctly re-allocating blocks that were +32k+. The fix was to use newer Win32 APIs (HeapAlloc, HeapFree, and +HeapReAlloc.) (BS) + +10/5/98 (bug fix) Fixed bug in pkg_mkIndex that caused some files that do +a "package require" of packages in the Tcl libraries to give a warning like + warning: "xx.tcl" provides more than one package ({xx 2.0} {yy 0.3}) +and generate a broken pkgIndex.tcl file. (EMS) + +10/5/98 (bug fix) Pkg_mkIndex was not doing a case-insensitive comparison +of extensions to determine whether to load or source a file. Thus, under +Windows, MYDLLNAME.DLL was sourced, and mydllname.dll loaded. (EMS) + +10/5/98 (new feature) Created a new Tcl_Obj type, "procbody". This object's +internal representation holds a pointer to a Proc structure. Extended +TclCreateProc to take both strings and "procbody". (EMS) + +10/13/98 (bug fix) The "info complete" command can now handle strings +with NULLs embedded. Thanks to colin@field.medicine.adelaide.edu.au +for providing this fix. (RJ) + +10/13/98 (bug fix) The "lsort -dictionary" command did not properly +handle some numbers starting with 0. Thanks to Richard Hipp + for submitting the fix to Scriptics. (RJ) + +10/13/98 (bug fix) The function Tcl_SetListObj was creating an invalid +Tcl_Obj if the list had zero elements (despite what the comments said +it would do). Thanks to Sebastian Wangnick for reporting the +problem. (RJ) + +10/20/98 (new feature) Added tcl_platform(debug) element to the +tcl_platform array on Windows platform. The existence of the debug +element of the tcl_platform array indicates that the particular Tcl +shell has been compiled with debug information. Using +"info exists tcl_platform(debug)" a Tcl script can direct the +interpreter to load debug versions of DLLs with the load +command. (SKS) + +10/20/98 (feature change) The Makefile and configure scripts have been +changed for IRIX to build n32 binaries instead of the old 32 abi +format. If you have extensions built with the o32 abi's you will need +to update them to n32 for them to work with Tcl. (RJ) +*** POTENTIAL INCOMPATIBILITY *** + +10/23/98 (bug fix) tcl_findLibrary had a stray ] in one of the +pathnames it searched for the initialization script. tclInitScript.h +was incorrectly adding the parent of tcl_library to tcl_pkgPath. This +logic was moved into init.tcl, and the initialization of auto_path was +documented. Thanks to Donald Porter and Tom Silva for related +patches. (BW) + +10/29/98 (bug fix) Fixed Tcl_NotifyChannel to use Tcl_Preserve instead +of Tcl_RegisterChannel so that 1) unregistered channels do not get +closed after their first fileevent, and 2) errors that occur during +close in a fileevent script are actually reflected by the close +command. (BW) + +10/30/98 (bug fix) Overhaul of pkg_mkIndex to deal with transitive +package requires and packages split among scripts and binary files. +Also fixed ommision of global for errorInfo in tcl_findLibrary. (BW) + +11/08/98 (bug fix) Fixed the resource command to always detect +the case where a file is opened a second time with the same +permissions. IM claims that this will always cause the same +FileRef to be returned, but in MacOS 8.1+, this is no longer the case, +so we have to test for this explicitly. (JI) + +11/10/98 (feature change) When compiling with Metrowerk's MSL, use the +exit function from MSL rather than ExitToShell. This allows MSL to +clean up its temporary files. Thanks to Vince Darley for this +improvement. (JI) + +----------------- Released 8.0.4, 11/19/98 ------------------------- + +11/20/98 (bug fix) Handle possible NULL return in TclGetStdFiles. (RJ) + +11/20/98 (bug fix) The dltests would not build on SGI. They reported +that you could not mix n32 with 032 binaries. The configure script +has been modified to get the EXTRA_CFLAGS from the tcl configure +script. [Bug id: 840] (RJ) + +12/3/98 (bug fix) Windows NT creates sockets so they are inheritable +by default. Fixed socket code so it turns off this bit right after +creation so sockets aren't kept open by exec'ed processes. [Bug: 892] +Thanks to Kevin Kenny for this fix. (SS) + +1/11/98 (bug fix) On HP, "info sharedlibextension" was returning +empty string on static apps. It now always returns ".sl". (RJ) + +1/28/99 (configure change) Now support -pipe option on gcc. (RJ) + +2/2/99 (bug fix) Fixed initialization problem on Windows where no +searching for init.tcl would be performed if the registry keys were +missing. (stanton) + +2/2/99 (bug fix) Added support for HKEY_PERFORMANCE_DATA and +HKEY_DYN_DATA keys in the "registry" command. (stanton) + +2/2/99 (bug fix) ENOTSUP and EOPNOTSUPP clashed on some Linux +variants. (stanton) + +2/2/99 (enhancement) The "open" command has been changed to use the +object interfaces. (stanton) + +2/2/99 (bug fix) In some cases Tcl would crash due to an overflow of +the exception stack resulting from a missing byte code in some +expressions. (stanton) + +2/2/99 (bug fix) Changed configure so Linux and IRIX shared libraries +are linked with the system libraries. (stanton) + +2/2/99 (bug fix) Added support for BSDI 4.x (BSD/OS-4*) to the +configure script. (stanton) + +2/2/99 (bug fix) Fixed bug where upvar could resurrect a namespace +variable after the namespace had been deleted. (stanton) + +2/2/99 (bug fix) In some cases when creating variables, the +interpreter result was being modified even if the TCL_LEAVE_ERR_MSG +flag was set. (stanton) + +2/2/99 (bug fix & new feature) Changed the socket drivers to properly +handle failures during an async socket connection. Added a new +fconfigure option "-error" to retrieve the failure message. See the +socket.n manual entry for details. (stanton) + +2/2/99 (bug fix) Deleting a renamed interp alias could result in a +panic. (stanton) + +2/2/99 (feature change/bug fix) Changed the behavior of "file +extension" so that it splits at the last period. Now the extension of +a file like "foo..o" is ".o" instead of "..o" as in previous versions. +*** POTENTIAL INCOMPATIBILITY *** + +----------------- Released 8.0.5, 3/9/99 ------------------------- + +======== Changes for 8.0 go above this line ======== +======== Changes for 8.1 go below this line ======== + +6/18/97 (new feature) Tcl now supports international character sets: + - All C APIs now accept UTF-8 strings instead of iso8859-1 strings, + wherever you see "char *", unless explicitly noted otherwise. + - All Tcl strings represented in UTF-8, which is a convenient + multi-byte encoding of Unicode. Variable names, procedure names, + and all other values in Tcl may include arbitrary Unicode characters. + For example, the Tcl command "string length" returns how many + Unicode characters are in the argument string. + - For Java compatibility, embedded null bytes in C strings are + represented as \xC080 in UTF-8 strings, but the null byte at the end + of a UTF-8 string remains \0. Thus Tcl strings once again do not + contain null bytes, except for termination bytes. + - For Java compatibility, "\uXXXX" is used in Tcl to enter a Unicode + character. "\u0000" through "\uffff" are acceptable Unicode + characters. + - "\xXX" is used to enter a small Unicode character (between 0 and 255) + in Tcl. + - Tcl automatically translates between UTF-8 and the normal encoding for + the platform during interactions with the system. + - The fconfigure command now supports a -encoding option for specifying + the encoding of an open file or socket. Tcl will automatically + translate between the specified encoding and UTF-8 during I/O. + See the directory library/encoding to find out what encodings are + supported (eventually there will be an "encoding" command that + makes this information more accessible). + - There are several new C APIs that support UTF-8 and various encodings. + See Utf.3 for procedures that translate between Unicode and UTF-8 + and manipulate UTF-8 strings. See Encoding.3 for procedures that + create new encodings and translate between encodings. See + ToUpper.3 for procedures that perform case conversions on UTF-8 + strings. + +9/18/97 (enhancement) Literal objects are now shared by the ByteCode +structures created when compiled different scripts. This saves up to 45% +of the total memory needed for all literals. (BL) + +9/24/97 (bug fixes) Fixed Tcl_ParseCommand parsing of backslash-newline +sequences at start of command words. Suppressed Tcl_EvalDirect error logging +if non-TCL_OK result wasn't an error. (BL) + +10/17/97 (feature enhancement) "~username" now refers to the users' home +directory on Windows (previously always returned failure). (CCS) + +10/20/97 (implementation change) The Tcl parser has been completely rewritten +to make it more modular. It can now be used to parse a script without actually +executing it. The APIs for the new parser are not correctly exported, but +they will eventually be exported and augmented with Tcl commands so that +Tcl scripts can parse other Tcl scripts. (JO) + +10/21/97 (API change) Added "flags" argument to Tcl_EvalObj, removed +Tcl_GlobalEvalObj procedure. Added new procedures Tcl_Eval2 and +Tcl_EvalObjv. (JO) +*** POTENTIAL INCOMPATIBILITY *** + +10/22/97 (API change) Renamed Tcl_ObjSetVar2 and Tcl_ObjGetVar2 to +Tcl_SetObjVar2 and Tcl_GetObjVar2 (for consistency with other C APIs) +and changed the name arguments to be strings instead of objects. (JO) +*** POTENTIAL INCOMPATIBILITY *** + +10/27/97 (enhancement) Bytecode compiler rewritten to use the new Tcl +parser. (BL) + +11/3/97 (New routines) Added Tcl_AppendObjToObj, which appends the +string rep of one Tcl_Obj to another. Added Tcl_GetIndexFromObjStruct, +which is similar to Tcl_GetIndexFromObj, except that you can give an +offset between strings. This allows Tcl_GetIndexFromObjStruct to be +called with a table of records which have strings in them. (SRP) + +12/4/97 (enhancement) New Tcl expression parser added. Added new procedure +Tcl_ParseExpr and new token types TCL_TOKEN_SUB_EXPR and +TCL_TOKEN_OPERATOR. Expression compiler is reimplemented to use this +parser. (BL) + +12/9/97 (bug fix) Tcl_EvalObj() increments/decrements the refcount of the +script object to prevent the object from deleting itself while in the +middle of being evaluated. (CCS) + +12/9/97 (bug fix) Memory leak in Tcl_GetsObjCmd(). (CCS) + +12/11/97 (bug fix) Environment array leaked memory when compiled with +Visual C++. (SS) + +12/11/97 (bug fix) File events and non-blocking I/O did not work on +pipes under Windows. Changed to use threads to achieve non-blocking +behavior. (SS) + +12/18/97 (bug fixes) Fixed segfault in "namespace import"; importing a +procedure that causes a cycle now returns an error. Modified "info procs", +"info args", "info body", and "info default" to return information about +imported procedures as well as procedures defined in a namespace. (BL) + +12/19/97 (enhancement) Added new Tcl_GetString() procedure that can be used +in place of Tcl_GetStringFromObj() if the string representation's length +isn't needed. (BL) + +12/18/97 (bug fix) In the opt argument parsing package: if the description +had only flags, the "too many arguments" case was not detected. The default +value was not used for the special "args" ending argument. (DL) + +1/7/98 (clean up) Moved everything not absolutly necessary out of init.tcl +procs now in auto.tcl and package.tcl can be autoloaded if needed. (DL) + +1/7/98 (enhancement) tcltest made at install time will search for it's +init.tcl where it is, even when using virtual path compilation. (DL) + +1/8/98 (os bug workaround) when needed, using a replacement for memcmp so +string compare "char with high bit set" "char w/o high bit set" returns +the expected value on all platforms. (DL) + +1/8/98 (unix portability/configure) building from .../unix/targetName/ +subdirectories and simply using "../configure" should now work fine. (DL) + +1/14/98 (enhancement) Added new regular expression package that +supports AREs, EREs, and BREs. The new package includes new escape +characters, meta-syntax, and character classes inside brackets. +Regexps involving backslashes may behave differently. (MH) +*** POTENTIAL INCOMPATIBILITY *** + +1/16/98 (os workaround) Under windows, "file volume" was causing chatter +and/or several seconds of hanging when querying empty floppy drives. +Changed implementation to call an empirically-derived function that doesn't +cause this. (CCS) + +1/16/98 (enhancement) Converted regular expressions to a Tcl_Obj type so +their compiled form gets cached automatically. Reduced NSUBEXP from 100 +to 20. (BW) + +1/16/98 (documentation) Change unclear documentation and comments for +functions like Tcl_TranslateFileName() and Tcl_ExternalToUtfDString(). Now +it explicitly says they take an uninitialized or free DString. A DString +that is "empty" or "not holding anything" could have been interpreted as one +currently with a zero length, but with a large dynamically allocated buffer. +(CCS) + +----------------- Released 8.1a1, 1/22/98 ----------------------- + +1/28/98 (new feature) Added a "-direct" optional flag to pkg_mkIndex +to generate direct loading package indexes (such those you need +if you use namespaces and plan on using namespace import just after +package require). pkg_mkIndex still has limitations regarding +package dependencies but errors are now ignored and with -direct, correct +package indexes can be generated even if there are dependencies as long +as the "package provide" are done early enough in the files. (DL) + +1/28/98 (enhancement) Performance tuning of regexp and regsub. (CCS) + +1/28/98 (bug fix) regexp and regsub with "-indices" returned the byte-offsets +of the characters in the UTF-8 representation, not the character offsets +themselves. (CCS) + +1/28/98 (bug fix) "clock format 0 -format %Z -gmt 1" would return the local +timezone string instead of "GMT" on Solaris and Windows. + +1/28/98 (bug fix) Restore tty settings when closing serial device on Unix. +This is good behavior when closing real serial devices, essential when +closing the pseudo-device /dev/tty because the user's terminal settings +would be left useless, in raw mode, when tcl quit. (CCS) + +1/28/98 (bug fix) Tcl_OpenCommandChannel() was modifying the contents of the +argv array passed to it, causing problems for any caller that wanted to +continue to use the argv array after calling Tcl_OpenCommandChannel(). (CCS) + +2/1/98 (bug fix) More bugs with %Z in format string argument to strftime(): +1. Borland always returned empty string. +2. MSVC always returned the timezone string for the current time, not the + timezone string for the specified time. +3. With MSVC, "clock format 0 -format %Z -gmt 1" would return "GMT" the first + time it was called, but would return the current timezone string on all + subsequent calls. (CCS) + +2/1/98 (bug fix) "file stat" was broken on Windows. +1. "file stat" of a root directory (local or network) or a relative path that + resolved to a root directory (c:. when in pwd was c:/) was returning error. +2. "file stat" on a regular file (S_IFREG), the st_mode was sign extended to + a negative int if the platform-dependant type "mode_t" was declared as a + short instead of an unsigned short. +3. "file stat" of a network directory, the st_dev was incorrectly reported + as the id of the last accessed local drive rather than the id of the + network drive. (CCS) + +2/1/98 (bug fix) "file attributes" of a relative path that resolved to a +root directory was returning error. (CCS) + +2/1/98 (bug fix) Change error message when "file attribute" could not +determine the attributes for a file. Previously it would return different +error messages on Unix vs. Windows vs. Mac. (CCS) + +2/4/98 (bug fixes) Fixed several instances of bugs where the parser/compiler +would reach outside the range of allocated memory. Improved the array +lookup algorithm in set compilation. (DL) + +2/5/98 (change) The TCL_PARSE_PART1 flag for Set/Get(Obj)Var2 C APIs is now +deprecated and ignored. The part1 is always parsed when the part2 argument +is NULL. This is to avoid a pattern of errors for extension writers converting +from string based Tcl_SetVar() to new Tcl_SetObjVar2() and who could easily +forget to provide the flag and thus get code working for normal variables +but not for array elements. The performance hit is minimal. A side effect +of that change is that is is no longer possible to create scalar variables +that can't be accessed by tcl scripts because of their invalid name +(ending with parenthesis). Likewise it is also parsed and checked to +ensure that you don't create array elements of array whose name is a valid +array element because they would not be accessible from scripts anyway. +Note: There is still duplicate array elements parsing code. (DL) +*** POTENTIAL INCOMPATIBILITY *** + +2/11/98 (bug fix) Sharing objects between interps, such as by "interp +eval" or "send" could cause a crash later when dereferencing an interp +that had been deleted, given code such as: + set a {set x y} + interp create foo + interp eval foo $a + interp delete foo + unset a +Interp "foo" was gone, but "a" had a internal rep consisting of bytecodes +containing a dangling pointer to "foo". Unsetting "a" would attempt to +return resources back to "foo", causing a crash as random memory was +accessed. The lesson is that that if an object's internal rep depends on +an interp (or any other data structure) it must preserve that data in +some fashion. (CCS) + +2/11/98 (enhancement) The "interp" command was returning inconsistent error +messages when the specified slave interp could not be found. (CCS) + +2/11/98 (bug fix) Result codes like TCL_BREAK and TCL_CONTINUE were not +propagating through the master/slave interp boundaries, such as "interp +eval" and "interp alias". TCL_OK, TCL_ERROR, and non-standard codes like +teh integer 57 work. There is still a question as to whether TCL_RETURN +can/should propagate. (CCS) + +2/11/98 (bug fix) TclCompileScript() was derefering memory 1 byte before +start of the string to compile, looking for ']'. (CCS,DL) + +2/11/98 (bug fix) Tcl_Eval2() was derefering memory 1 byte before start +of the string to eval, looking for ']'. (CCS,DL) + +2/11/98 (bug fix) Compiling "set a(b" was running off end of string. (CCS,DL) + +2/11/98 (bug fix) Windows initialization code was dereferencing +uninitialized memory if TCL_LIBRARY environment didn't exist. (CCS) + +2/11/98 (bug fix) Windows "registry" command was dereferencing +uninitialized memory when constructing the $errorCode for a failed +registry call. (CCS) + +2/11/98 (enhancement) Eliminate the TCL_USE_TIMEZONE_VAR definition from +configure.in, because it was the same information as the already existing +HAVE_TM_ZONE definition. The lack of HAVE_TM_ZONE is used to work around a +Solaris and Windows bug where "clock format [clock sec] -format %Z -gmt 1" +produces the local timezone string instead of "GMT". (CCS) + +2/11/98 (bug fix) Memleaks and dereferencing of uninitialized memory in +regexp if an error occurred while compiling a regular expression. (CCS). + +2/18/98 (new feature) Added mutexes and thread local storage in order +to make Tcl thread safe. For testing purposes, there is a testthread +command that creates a new thread and an interpreter inside it. See +thread.test for examples, but this script-level interface is not fixed. +Each thread has its own notifier instance to manage its own events, +and threads can post messages to each other's message queue. +This uses pthreads on UNIX, and native thread support on other platforms. +You enable this by configuring with --enable-threads. Note that at +this time *Tk* is still not thread safe. Special thanks to +Richard Hipp: his earlier implementation inspired this work. (BW, SS, JI) + +2/18/98 (hidden feature change) The way the env() array is shared among +interpreters changed. Updates to env used to trigger write traces in +other interpreters. This undocumented feature is no longer implemented. +Instead, variable tracing is used to keep the C-level environ array in sync +with the Tcl-level env array. This required adding TCL_TRACE_ARRAY support +to Tcl_TraceVar2 so that array names works properly. (BW) +*** POTENTIAL INCOMPATIBILITY *** + +2/18/98 (enhancement) Conditional compilation for unix systems (e.g., +IRIX, SCO) that use f_bsize instead of st_blksize to determine disk block +size. (CCS) + +2/23/98 (bug fix) Fixed the emulation of polling selects in the threaded +version of the Unix notifier. The bug was showing up on a multiprocessor +as starvation of the notifier thread. (BW) + +----------------- Released 8.1a2, Feb 23 1998 ----------------------- + +9/22/98 (bug fix) Changed the value of TCL_TRACE_ARRAY so it no longer +conflicts with the deprecated TCL_PARSE_PART1 flag. This should +improve portability of C code. (stanton) + +10/6/98 (bug fix) The compile procedure for "if" incorrectly attempted +to match against the literal string "if", resulting in a stack +overflow when "::if" was compiled. It also would incorrectly accept +"if" instead of "elsif" in later clauses. (stanton) + +10/15/98 (new feature) Added a "totitle" subcommand to the "string" +command to convert strings to capitalize the first character of a string +and lowercase all of the other characters. (stanton) + +10/15/98 (bug fix) Changed regexp and string commands to properly +handle case folding according to the Unicode character +tables. (stanton) + +10/21/98 (new feature) Added an "encoding" command to facilitate +translations of strings between different character encodings. See +the encoding.n manual entry for more details. (stanton) + +11/3/98 (bug fix) The regular expression character classification +syntax now includes Unicode characters in the supported +classes. (stanton) + +11/6/98 (bug fix) Variable traces were causing crashes when upvar +variables went out of scope. [Bug: 796] (stanton) + +11/9/98 (bug fix) "format" now correctly handles multibyte characters +in %s format strings. (stanton) + +11/10/98 (new feature) "regexp" now accepts three new switches +("-line", "-lineanchor", and "-linestop") that control how regular +expressions treat line breaks. See the regexp manual entry for more +details. (stanton) + +11/17/98 (bug fix) "scan" now correctly handles Unicode +characters. (stanton) + +11/17/98 (new feature) "scan" now supports XPG3 position specifiers +and the "%n" conversion character. See the "scan" manual entry for +more details. (stanton) + +11/17/98 (bug fix) The Tcl memory allocator now returns 8-byte aligned +chunks of memory which improves performance on Windows and avoids +crashes on other platforms. [Bug: 834] (stanton) + +11/23/98 (bug fix) Applied various regular expression performance bug +fixes supplied by Henry Spencer. (stanton) + +11/30/98 (bug fix) Fixed various thread related race conditions. [Bug: +880 & 607] (stanton) + +11/30/98 (bug fix) Fixed a number of memory overflow and leak +bugs. [Bug: 584] (stanton) + +12/1/98 (new feaure) Added support for Korean encodings. (stanton) + +12/1/98 (feature change) Changed the Tcl_EvalObjv interface to remove +the string and length arguments. +*** POTENTIAL INCOMPATIBILITY with previous alpha releases *** + +12/2/98 (bug fix) Fixed various bugs related to line feed +translation. [Bug: 887] (stanton) + +12/4/98 (new feature) Added a message catalog facility to help with +localizing Tcl scripts. Thanks to Mark Harrison for contributing the +initial implementation of the "msgcat" package. (stanton) + +12/7/98 (bug fix) The memory allocator was failing to update the +block list for large memory blocks that were reallocated into a +different address. [Bug: 933] (stanton) + +----------------- Released 8.1b1, Dec 10 1998 ----------------------- + +12/22/98 (performance improvement) Improved the -command option of the +lsort command to better use the object system for improved +performance (about 5x speed up). Thanks to Syd Polk for suppling the +patch. [RFE: 726] (rjohnson) + +2/10/99 (bug fix) Restored the Tcl_ObjSetVar2/Tcl_ObjGetVar2 +interfaces from 8.0 and renamed the Tcl_GetObjVar2/Tcl_SetObjVar2 +interfaces to Tcl_GetVar2Ex and Tcl_SetVar2Ex. This should provide +better compatibility with 8.0. (stanton) +*** POTENTIAL INCOMPATIBILITY with previous alpha/beta releases *** + +2/10/99 (bug fix) Made the eval interfaces compatible with 8.0 by +renaming Tcl_EvalObj to Tcl_EvalObjEx, renaming Tcl_Eval2 to +Tcl_EvalEx and restoring Tcl_EvalObj and Tcl_GlobalEvalObj interfaces +so they match Tcl 8.0. (stanton) +*** POTENTIAL INCOMPATIBILITY with previous alpha/beta releases *** + +2/25/99 (bug fix/new feature) On Windows, the channel drivers for +consoles and serial ports now completely support file events. (redman) + +3/5/99 (bug fix) Integrated patches to fix various configure problems +that affected HP-UX-11, 64-bit IRIX, Linux, and Solaris. (stanton) + +3/9/99 (bug fix) Integrated various AIX related patches to improve +support for shared libraries. (stanton) + +3/9/99 (new feature) Added tcl_platform(user) to provide a portable +way to get the name of the current user. (welch) + +3/9/99 (new feature) Integrated the stub library mechanism contributed +by Jan Nijtmans, Paul Duffin, and Jean-Claude Wippler. This feature +should make it possible to write extensions that support multiple +versions of Tcl simultaneously. It also makes it possible to +dynamically load extensions into statically linked interpreters. This +patch includes the following changes: + - Added a Tcl_InitStubs() interface + - Added Tcl_PkgProvideEx, Tcl_PkgRequireEx, Tcl_PkgPresentEx, + and Tcl_PkgPresent. + - Added va_list versions of all VARARGS functions so they can be + invoked from wrapper functions. +See the manual for more information. (stanton) + + +3/10/99 (feature change) Replaced Tcl_AlertNotifier with +Tcl_ThreadAlert since the Tcl_AlertNotifier function relied on passing +internal data structures. (stanton) +*** POTENTIAL INCOMPATIBILITY with previous alpha/beta releases *** + +3/10/99 (new feature) Added a Tcl_GetVersion API to make it easier to +check the Tcl version and patch level from C. (redman) + +3/14/99 (feature change) Tried to unify the TclpInitLibrary path +routines to look in similar places from Windows to UNIX. The new +library search path is: TCL_LIBRARY, TCL_LIBRARY/../tcl8.1, relative +to DLL (Windows Only) relative to installed executable, relative to +develop executable, and relative to compiled-in in location (UNIX +Only.) This fix included: + - Defining a TclpFindExecutable + - Moving Tcl_FindExecutable to a common area in tclEncoding.c + - Modifying the TclpInitLibraryPath routines. +(surles) + +3/14/99 (feature change) Added hooks for TclPro Wrapper to initialize +the location of the encoding files and libraries. This fix included: + - Adding the TclSetPerInitScript routine. + - Modifying the Tcl_Init routines to evaluate the non-NULL + pre-init script. + - Adding the Tcl_SetdefaultEncodingDir and Tcl_GetDefaultEncodingDir + routines. + - Modifying the TclpInitLibrary routines to append the default + encoding dir. +(surles) + +3/14/99 (feature change) Test suite now uses "test" namespace to +define the test procedure and other auxiliary procedures as well as +global variables. + - Global array testConfige is now called ::test::testConfig. + - Global variable VERBOSE is now called ::test::verbose, and + ::test::verbose no longer works with numerical values. We've + switched to a bitwise character string. You can set + ::test::verbose by using the -verbose option on the Tcl command + line. + - Global variable TESTS is now called ::test::matchingTests, and + can be set on the Tcl command line via the -match option. + - There is now a ::test::skipTests variable (works similarly to + ::test::matchTests) that can be set on the Tcl command line via + the -match option. + - The test suite can now be run in any working directory. When + you run "make test", the working directory is nolonger switched + to ../tests. +(hirschl) +*** POTENTIAL INCOMPATIBILITY *** + +--------------- Released 8.1b2, March 16, 1999 ---------------------- + +3/18/99 (bug fix) Fixed missing/incorrect characters in shift-jis table +(stanton) + +3/18/99 (feature change) The glob command ignores the +FS_CASE_IS_PRESERVED bit on file systesm and always returns +exactly what it gets from the system. (stanton) +*** POTENTIAL INCOMPATIBILITY *** + +3/19/99 (new feature) Added support for --enable-64bit. For now, +this is only supported on Solaris 7 64bit (SunOS 5.7) using the Sun +compiler. (redman) + +3/23/99 (bug fix) Fixed fileevents and gets on Windows consoles and +serial devices so that non-blocking channels do not block on partial +input lines. (redman) + +3/23/99 (bug fix) Added a new Tcl_ServiceModeHook interface. +This is used on Windows to avoid the various problems that people +have been seeing where the system hangs when tclsh is running +outside of the event loop. As part of this, renamed +TclpAlertNotifier back to Tcl_AlertNotifier since it is public. +(stanton) + +3/23/99 (feature change) Test suite now uses "tcltest" namespace to +define the test procedure and other auxiliary procedures as well as +global variables. The previously chosen "test" namespace was thought +to be too generic and likely to create conflits. +(hirschl) +*** POTENTIAL INCOMPATIBILITY *** + +3/24/99 (bug fix) Make sockets thread safe on Windows. +(redman) + +3/24/99 (bug fix) Fix cases where expr would incorrect return +a floating point value instead of an integer. (stanton) + +3/25/99 (bug fix) Added ASCII to big5 and gb2312 encodings. +(stanton) + +3/25/99 (feature change) Changed so aliases are invoked at current +scope in the target interpreter instead of at the global scope. This +was an incompatibility introduced in 8.1 that is being removed. +(stanton) +*** POTENTIAL INCOMPATIBILITY with previous beta releases *** + +3/26/99 (feature change) --enable-shared is now the default and build +Tcl as a shared library; specify --disable-shared to build a static Tcl +library and shell. +*** POTENTIAL INCOMPATIBILITY *** + +3/29/99 (bug fix) Removed the stub functions and changed the stub +macros to just use the name without params. Pass &tclStubs into the +interp (don't use tclStubsPtr because of collisions with the stubs on +Solaris). (redman) + +3/30/99 (bug fix) Loadable modules are now unloaded at the last +possible moment during Tcl_Finalize to fix various exit-time crashes. +(welch) + +3/30/99 (bug fix) Tcl no longer calls setlocale(). It looks at +env(LANG) and env(LC_TYPE) instead. (stanton) + +4/1/99 (bug fix) Fixed the Ultrix multiple symbol definition problem. +Now, even Tcl includes a copy of the Tcl stub library. (redman) + +4/1/99 (bug fix) Internationalized the registry package. + +4/1/99 (bug fix) Changed the implemenation of Tcl_ConditionWait and +Tcl_ConditionNotify on Windows. The new algorithm eliminates a race +condition and was suggested by Jim Davidson. (welch) + +4/2/99 (new apis) Made various Unicode utility functions public. +Tcl_UtfToUniCharDString, Tcl_UniCharToUtfDString, Tcl_UniCharLen, +Tcl_UniCharNcmp, Tcl_UniCharIsAlnum, Tcl_UniCharIsAlpha, +Tcl_UniCharIsDigit, Tcl_UniCharIsLower, Tcl_UniCharIsSpace, +Tcl_UniCharIsUpper, Tcl_UniCharIsWordChar, Tcl_WinUtfToTChar, +Tcl_WinTCharToUtf (stanton) + +4/2/99 (feature change) Add new DDE package and removed the Tk +send command from the Windows version. Changed DDE-based send +code into "dde eval" command. The DDE package can be loaded +into tclsh, not just wish. Windows only. (redman) + +4/5/99 (bug fix) Changed safe-tcl so that the encoding command +is an alias that masks out the "encoding system" subcommand. +(redman) + +4/5/99 (bug fix) Configure patches to improve support for +OS/390 and BSD/OS 4.*. (stanton) + +4/5/99 (bug fix) Fixed crash in the clock command that occurred +with negative time values in timezones east of GMT. (stanton) + +4/6/99 (bug fix) Moved the "array set" C level code into a common +routine (TclArraySet). The TclSetupEnv routine now uses this API to +create an env array w/ no elements. This fixes the bug caused when +every environ varaible is removed, and the Tcl env variable is +synched. If no environ vars existed, the Tcl env var would never be +created. (surles) + +4/6/99 (bug fix) Made the Env module I18N compliant. (surles) + +4/6/99 (bug fix) Changed the FindVariable routine to TclpFindVariable, +that now does a case insensitive string comparison on Windows, and not +on UNIX. (surles) + +--------------- Released 8.1b3, April 6, 1999 ---------------------- + +4/9/99 (bug fix) Fixed notifier deadlock situation when the pipe used +to talk back notifier thread is filled with data. Found as a result of the +focus.test for Tk hanging. (redman) + +4/13/99 (bug fix) Fixed bug where socket -async combined with +fileevent for writing did not work under Windows NT. (redman) + +4/13/99 (encoding fix) Restored the double byte definition of GB2312 +and added the EUC-CN encoding. EUC-CN is a variant of GB2312 that +shifts the characters into bytes with the high bit set and includes +ASCII as a subset. (stanton) + +4/27/99 (bug fix) Added 'extern "C" {}' block around the stub table +pointer declaration so the stub library can be used from C++. (stanton) + +--------------- Released 8.1 final, April 29, 1999 ---------------------- + +4/22/99 (bug fix) Changed Windows NT socket implementation to avoid +creating a communication window. This avoids the problem where the +system hangs waiting for tclsh to respond to a system-wide synchronous +broadcast (e.g. if you change system colors). (redman) + +4/22/99 (bug fix) Added call to TclWinInit from TclpInitPlatform when +building a static library since DllMain will not be invoked. This +could break old code that explicitly called TclWinInit, but should be +simpler in the long run. (stanton) +*** POTENTIAL INCOMPATIBILITY *** + +4/23/99 (bug fix) Added support for the koi8-r Cyrillic +encoding. [Bug: 1771] (stanton) + +4/28/99 (bug fix) Changed internal Tcl_Obj usage to avoid freeing the +internal representation after the string representation has been +freed. This makes it easier to debug extensions. (stanton) + +4/30/99 (bug fix) Fixed a memory leak in CommandComplete. (stanton) + +5/3/99 (bug fix) Fixed a bug where the Tcl_ObjType was not being set +in a duplicated Tcl_Obj. [Bug: 1975, 2047] (stanton) + +5/3/99 (bug fix) Changed Tcl_ParseCommand to avoid modifying eval'ed +strings that are already null terminated. [Bug: 1793] (stanton) + +5/3/99 (new feature) Applied Jeff Hobbs's string patch which includes +the following changes: + - added new subcommands: equal, repeat, map, is, replace + - added -length option to "string compare|equal" + - added -nocase option to "string compare|equal|match" + - string and list indices can be an integer or end?-integer?. + - added optional first and last index args to string toupper, et al. +See the string.n manual entry for more details about the new string +features. [Bug: 1845] (stanton) + +5/6/99 (new feature) Added Tcl_UtfNcmp and Tcl_UtfNcasecmp to make Utf +string comparision easier. (stanton) + +5/7/99 (bug fix) Improved OS/390 support. [Bug: 1976, 1997] (stanton) + +5/12/99 (bug fix) Changed Windows initialization code to avoid using +GetUserName system call in favor of the env(USERNAME) variable. This +provides a significant startup speed improvement. (stanton) + +5/12/99 (bug fix) Replaced the per-interpreter regexp cache with a +per-thread cache. Changed the Regexp object to take advantage of this +extra cache. Added a reference count to the TclRegexp type so regexps +can be shared by multiple objects. Removed the per-interp regexp cache +from the interpreter. Now regexps can be used with no need for an +interpreter. This set of changes should provide significant speed +improvements for many Tcl scripts. [Bug: 1063] (stanton) + +5/14/99 (bug fix) Durining initialization on Unix, Tcl now extracts the +encoding subfield from the LANG/LC_ALL environment variables in cases +where the locale is not found in the built-in locale table. It also +attempts to initialize the locale subsystem so X11 is happy. [Bug: 1989] +(stanton) + +5/14/99 (bug fix) Applied the patch to fix 100-year and 400-year +boundaries in leap year code, from Isaac Hollander. [Bug: 2066] (redman) + +5/14/99 (bug fix) Fixed a crash caused by a failure to reset the result +before evaluating the test expression in an uncompiled for +statement. (stanton) + +5/18/99 (bug fix) Modified initialization code on Windows to avoid +inherenting closed or invalid channels. If the standard input is +anything other than a console, file, serial port, or pipe, then we fall +back to the standard Tk window console. (stanton) + +5/19/99 (bug fix) Added an extern "C" block around the entire tcl.h +header file to avoid C++ linkage issues. (redman) + +5/19/99 (new feature) Applied Jeff Hobb's patch to add +Tcl_StringCaseMatch to support case insensitive glob style matching and +Tcl_UniCharIs* character classification functions. (stanton) + +5/20/99 (bug fix) Added the directory containing the executuble and the +../lib directory relative to that to the auto_path variable. (redman) + +--------------- Released 8.1.1, May 25, 1999 ---------------------- + +5/21/99 (bug fix) Fixed launching command.com on Win95/98, no longer +hangs. [Bug: 2105] (redman) + +5/28/99 (bug fix) Fixed bug where dde calls were being passed an +invalid dde handle. [Bug: 2124] (stanton) + +6/1/99 (bug fix) Small configure.in patches. [Bug: 2121] (stanton) + +6/1/99 (bug fix) Applied latest regular expression patches to fix an +infinite loop bug and add support for testing whether a string could +match with additional input. [Bug: 2117] (stanton) + +6/2/99 (bug fix) Fixed incorrect computation of relative ordering in +Utf case-insensitive comparison. [Bug: 2135] (stanton) + +6/3/99 (bug fix) Fxied bug where string equal/compare -nocase +reported wrong result on null strings. [Bug: 2138] (stanton) + +6/4/99 (new feature) Windows build now uses Cygwin tools plus GNU +make and autoconf to build static/dynamic and debug/nodebug. (stanton) + +6/7/99 (new feature) Optimized string index, length, range, and +append commands. Added a new Unicode object type. (hershey) + +6/8/99 (bug fix) Rolled back Windows socket driver to 8.1.0 +version. (stanton) + +6/9/99 (new feature) Added Tcl_RegExpMatchObj and Tcl_RegExpGetInfo +to public Tcl API, these functions are needed by Expect. Changed +tools/genStubs.tcl to always write output in LF mode. (stanton) + +6/14/99 (new feature) Merged string and Unicode object types. Added +new public Tcl API functions: Tcl_NewUnicodeObj, Tcl_SetUnicodeObj, +Tcl_GetUnicode, Tcl_GetUniChar, Tcl_GetCharLength, Tcl_GetRange, +Tcl_AppendUnicodeToObj. (hershey) + +6/16/99 (new feature) Changed to conform to TEA specification, added +tcl.m4 and aclocal.m4 macro libraries for configure. (wart) + +6/17/99 (new feature) Added new regexp interfaces: -expanded, -line, +-linestop, and -lineanchor switches. Renamed Tcl_RegExpMatchObj to +Tcl_RegExpExecObj and added new Tcl_RegExpMatchObj that is equivalent +to Tcl_RegExpMatch. Added public macros for regexp flags. Added +REG_BOSONLY flag to allow Expect to iterate through a string and only +find matches that start at the current position within the +string. (stanton) + +6/21/99 (bug fix) Fixed memory leak in TclpThreadCreate where thread +attributes were not being released. [Bug: 2254] (stanton) + +6/23/99 (new feature) Updated Unicode character tables to reflect +Unicode 2.1 data. (stanton) + +6/25/99 (new feature) Fixed bugs in non-greedy quantifiers for regular +expression code. (stanton) + +6/25/99 (new feature) Added initial implementation of new Tcl test +harness package. Modified test files to use new tcltest package. +(jenn) + +6/26/99 (new feature) Applied patch from Peter Hardie to add poke +command to dde and changed the dde package version number to +1.1. (redman) + +6/28/99 (bug fix) Applied patch from Peter Hardie to fix problem in +Tcl_GetIndexFromObj() when the key being passed is the empty string. +[Bug: 1738] (redman) + +6/29/99 (new feature) Added options to tcltest package: -preservecore, +-limitconstraints, -help, -file, -notfile, and flags. (jenn) + +7/3/99 (new feature) Changed parsing of variable names to allow empty +array names. Now "$(foo)" is a variable reference. Previously you +had to use something line $::(foo), which is slower. This change was +requested by Jean-Luc Fontaine for his STOOOP package. (welch) + +7/3/99 (new feature) Added Tcl_SetNotifier (public API) and +associated hook points in the notifiers to be able to replace the +notifier calls at runtime. The Xt notifier and test program use this +hook. (welch) + +7/3/99 (new feature) Added a new variant of the "Trf core patch" from +Andreas Kupries that adds new C APIs Tcl_StackChannel, +Tcl_UnstackChannel, and Tcl_GetStackedChannel. This allows the Trf +extension to work without applying patches to the Tcl core. (welch) + +7/6/99 (new feature) Added -timeout option to http.tcl to handle +timeouts that occur during connection attempts to hosts that are +down. (welch) + +7/6/99 (bug fix) Applied new implementation of the Windows serial +port driver from Rolf Schroedter that fixes reading only one byte from +the port at a time. Uses polling every 10ms to implement +fileevents. [Bug: 1980 2217] (redman) + +7/8/99 (bug fix) Applied fix for bug in DFA state caching under +lookahead conditions (regular expressions). [Bug: 2318] (stanton) + +7/8/99 (bug fix) Fixed bug in string range bounds checking +code. (stanton) + +--------------- Released 8.2b1, July 14, 1999 ---------------------- + +7/16/99 (bug fix) Added Tcl_SetNotifier to stub table. [Bug: 2364] +Added check for Alpha/Linux to correct the IEEE floating point flag, +patch from Don Porter. (redman) + +7/20/99 (bug fix) Merged 8.0.5 code to handle tcl_library properly, +also fixed a bug that caused TCL_LIBRARY to be ignored. (hershey) + +7/21/99 (bug fix) Implemented modified socket driver for Windows that +uses a thread to manage the socket event window. Code works the same +on all supported versions of Windows and was based on original 8.1.0 +code. [Bug: 2178 2256 2259 2329 2323 2355] (redman) + +7/21/99 (new feature) Applied patch from Rolf Schroedter to add +-pollinterval option to fconfigure for Windows serial ports. Allows +the maxblocktime to be modified to control how often serial ports are +checked for fileevents. Also added documentation for \\.\comX +notation for opening serial ports on Windows. (redman) + +7/21/99 (bug fix) Changed APIs in stub tables to use "unsigned long" +instead of the platform-specific "size_t", primarily after SunOS 4 +users could no longer compile. (redman) + +7/22/99 (bug fix) Fixed crashing during "array set a(b) {}". +[Bug: 2427] (redman) + +7/22/99 (bug fix) The install-sh script must be given execute +permissions prior to running. [Bug: 2413] (redman) + +7/22/99 (bug fix) Applied patch from Ulrich Ring to remove ANSI-style +prototypes in the code. [Bug: 2391] (redman) + +7/22/99 (bug fix) Added #if blocks around #includes of sys/*.h header +files, to allow an extension author on Windows to use the MetroWerks +compiler. [Bug: 2385] (redman) + +7/22/99 (bug fix) Fixed running the safe.test test suite, one change +to the Windows Makefile.in to fix paths and another in safe.test to +check for the tcl_platform(threaded) variable properly. (redman) + +7/22/99 (bug fix) Fixed hanging in new Win32 socket driver with +threads enabled. (redman) + +7/26/99 (bug fix) Fixed terminating of helper threads by holding any +mutexes from the primary thread while waiting for the helper thread to +terminate. Fixes dual-CPU WinNT hangs, only one rare sporadic hang +that still exists with dual-CPU WinNT. Also fixed test cases so that +they would not depend as much on timing for dual-CPU WinNT. (redman) + +7/27/99 (bug fix) Some test suite cleanup. (jenn) + +7/29/99 (bug fix) Applied patch to fix typo in .SH NAME line in +doc/Encoding.n [Bug: 2451]. Applied patch to avoid linking pack.n to +pack-old.n [Bug: 2469]. Patches from Don Porter. (redman) + +7/29/99 (bug fix) Allow tcl to open CON and NUL, even for redirection +of std channels. [Bug: 2393 2392 2209 2458] (redman) + +7/30/99 (bug fix) Applied fixed Trf patch from Andreas Kupries. +[Bug: 2386] (hobbs) + +7/30/99 (bug fix) Fixed bug in info complete. [Bug: 2383 2466] (hobbs) + +7/30/99 (bug fix) Applied patch to fix threading on Irix 6.5, patch +provided by James Dennett. [Bug: 2450] (redman) + +7/30/99 (bug fix) Fixed launching of 16bit applications on Win9x from +wish. The command line was being primed with tclpip82.dll, but it was +ignored later. + +7/30/99 (bug fix) Added functions to stub table, patch provided by Jan +Nijtmans. [Bug: 2445] (hobbs) + +8/1/99 (bug fix) Changed Windows socket driver to terminate threads +by sending a message to the window rather than calling +TerminateThread(), which seems to leak about 4k from the helper +thread's stack space. (redman) + +--------------- Released 8.2b2, August 5, 1999 ---------------------- + +8/4/99 (bug fix) Applied patches supplied by Henry Spencer to greatly +enhance performance of certain classes of regular expressions. +[Bug: 2440 2447] (stanton) + +8/5/99 (doc change) Made it clear that tcl_pkgPath was not set for +Windows. [Bug: 2455] (hobbs) + +8/5/99 (bug fix) Fixed reference to bytes that might not be null +terminated in tclLiteral.c. [Bug: 2496] (hobbs) + +8/5/99 (bug fix) Fixed typo in http.tcl. [Bug: 2502] (hobbs) + +8/9/99 (bug fix) Fixed test suite to handle larger integers +(64bit). Patch from Don Porter. (hobbs) + +8/9/99 (documentation fix) Clarified Tcl_DecrRefCount docs +[Bug: 1952]. Clarified array pattern docs [Bug: 1330]. Fixed clock docs +[Bug: 693]. Fixed formatting errors [Bug: 2188 2189]. Fixed doc error +in tclvars.n [Bug: 2042]. (hobbs) + +8/9/99 (bug fix) Fixed path handling in auto_execok [Bug: 1276] (hobbs) + +8/9/99 (internal api change) Removed the TclpMutexLock and TclpMutexUnlock +APIs and added a new exported api, Tcl_GetAllocMutex. These APIs are all for +the mutex used in the simple memory allocators. By making this change +we are able to substitute different implementations of the thread-related +APIs without having to recompile the Tcl core. (welch) + +8/9/99 (new C API) Tcl_GetChannelNames returns a list of open channel +names in the interpreter result. Still no Tcl-level version of this, +but server-like applications can use this to clean up files without +deleting interpreters. (welch) + +8/9/99 (bug fix) Traces were not firing on "info exists", which used to +happen in Tcl 7.6 and earlier. An "info exists" now fires a read trace, +if defined. This makes it possible to fully implement variables that +are defined via traces. (welch) + +8/10/99 (bug fix) Fixed Brent's changes so that they work on +Windows. (redman) + +--------------- Released 8.2b3, August 11, 1999 ---------------------- + +8/12/99 (Mac) Rearrange projects in tclMacProjects.sea.hqx so that the +build directory is separate from the sources. (Jim Ingham) + +8/12/99 (bug fix) Fixed bug in Tcl_EvalEx where the termOffset was not +being updated in cases where the evaluation returned a non TCL_OK +error code. [Bug: 2535] (stanton) + +--------------- Released 8.2.0, August 17, 1999 ---------------------- + +9/21/99 (config fixes) fixed several AIX configuration issues. gcc and +threading may still cause problems on AIX. (hobbs) + +9/21/99 (bug fix) fixed expr double-eval problem. [Bug: 732] (hobbs) + +9/21/99 (bug fix) fixed static buffer overflow problem. [Bug: 2483] (hobbs) + +9/21/99 (bug fix) fixed end-int linsert interpretation. [Bug: 2693] (hobbs) + +9/21/99 (bug fix) fixed bug when setting array in non-existent +namespace. [Bug: 2613] (hobbs) + +--- Released 8.2.1, October 04, 1999 --- See ChangeLog for details --- + +10/30/99 (feature enhancement) new regexp engine from Henry Spencer +was patched in - should greatly reduce stack space usage. (spencer) + +10/30/99 (bug fix) fixed Purify reported memory leaks in findexecutable +test command, TclpCreateProcess on Unix, in handling of C environ array, +and in testthread code. No more known (reported) mem leaks for Tcl +built using gcc on Solaris 2.5.1. Also none reported for Tcl on NT +(using Purify 6.0). (hobbs) + +10/30/99 (bug fix) fixed improper bytecode handling of +'eval {set array($unknownvar) 5}' (also for incr) (hobbs) + +10/30/99 (bug fix) fixed event/io threading problems by making +triggerPipe non-blocking (nick kisserbeth) + +10/30/99 (bug fix) fixed Tcl_AppendStringsToObjVA and Tcl_AppendResultVA +to only iterates once over the va_list (avoiding non-portable memcpy). +(joe english, hobbs) + +10/30/99 (bug fix) removed savedChar trick in tclCompile.c that appeared +to be causing a segv when the literal table was released. +[Bug: 2459, 2515] (David Whitehouse) + +10/30/99 (bug fix) fixed [string index] to return ByteArrayObj +when indexing into one (test case string-5.16) [Bug: 2871] (hobbs) + +10/30/99 (bug fix) fixes for mac UTF filename handling (ingham) + +--- Released 8.2.2, November 04, 1999 --- See ChangeLog for details --- + +11/19/99 (feature enhancement) bug fixes for http package as well as +patch required by TLS (SSL) extension that adds http::(un)register +and -type to http::geturl. Up'd http pkg version to 2.2. + +11/19/99 (bug fix) removed extra decr of numLevels in Tcl_EvalObjEx +that could cause seg fault (mjansen@wendt.de) + +11/19/99 (bug fixes) numerous minor big fixes, including correcting the +installation of the koi8-r encoding and tcltest1.0 on Windows. + +11/30/99 (bug fix) fixes scan where %[..] didn't match anything + +11/30/99 (bug fix) fixed setting of isNonBlocking flag in PipeBlockModeProc +so you can now close a non-blocking channel without waiting. + +11/30/99 (bug work-around) prevented the unloading of DLLs for Unix in +TclFinalizeLoad. This stops the seg fault on exit that some users would +see (ie with oratcl) when using DLLs that do nasty things like register +atexit handlers. + +12/07/99 (bug fix) fixes for 'expr + {[incr]}' and 'expr + {[error]}' +cases (different causes). + +--- Released 8.2.3, December 16, 1999 --- See ChangeLog for details --- + +1999-09-14 (feature enhancement) added -start switch to regexp and regsub. + +1999-09-15 (feature enhancement) add 'array unset' command. + +1999-09-15 (feature enhancement) rewrote runtime libraries to use new +string functions + +1999-08-18 (feature enhancement) added 'file channels' command, along with +Tcl_GetChannelNames(Ex) public C APIs. + +1999-10-19 (feature enhancement) enhanced tcltest package + +1999-09-16 (feature enhancement) added -milliseconds switch to 'clock clicks' + +1999-10-28 (feature enhancement) added support for inline 'scan' + +1999-10-28 (feature enhancement) added support for touch functionality by +extendeding 'file atime' and 'file mtime' to take an optional time argument + +1999-11-24 (feature enhancement) added 'fconfigure $sock -lasterror' +command to Windows to query the last error received on a serial socket. + +1999-11-30 (bug fix) fixed handling of %Z on NT for timezones that don't +have DST + +1999-12-03 (feature enhancement) improved error message in bad octal cases +and improper use of comments. (hobbs) + +1999-12-07 (bug fix) fixed Tcl_ScanCountedElement to not step +beyond the end of the counted string + +1999-12-09 (feature enhancement) removed all references to 16 bit +compatibility code for Windows (hobbs) + +1999-12-10 (bug fix) removed check for vfork - Tcl now uses only fork in +exec. (hobbs) + +1999-12-10 (optimization) changed Tcl_ConcatObj to return a list +object when it receives all pure list objects as input (used by 'concat'), +added optimizations in Tcl_EvalObjEx for pure list case, and optimized +INST_TRY_CVT_TO_NUMERIC in TclExecuteByteCode for boolean objects. +(oakley, hobbs) + +1999-12-12 (feature enhancement) enhanced glob command with -type, -path, +-directory and -join switches. (darley, hobbs) + +1999-12-21 (bug fix) changed CreateThread to _beginthreadex and +ExitThread to _endthreadex to prevent 4K mem leak (gravereaux) + +1999-12-21 (bug fix) fixed applescript for I18N + +1999-12-21 (feature enhancement) added -unique option to lsort (hobbs) + +1999-12-21 (bug fix) changed thread ids to longs (for 64bit systems) + +--- Released 8.3b1, December 22, 1999 --- See ChangeLog for details --- + +2000-01-10 (feature enhancement) clock scan now supports the common +ISO 8601 date/time formats. See docs for details. (melski) + +2000-01-10 (bug fix) prevented \ooo substitution from accepting +non-octal digits [Bug: 3975] (hobbs) + +2000-01-11 (bug fix) fixed improper handling of DST by clock when +using relative times (like "1 month" or "tomorrow"). (melski) + +2000-01-12 (bug fix) improved build support for Tru64 v5, NetBSD +and Reliant Unix (hobbs) + +2000-01-12 (bug fix) made imported commands also import their +compile procedure (duffin) + +2000-01-12 (bug fix) fixed 'info procs ::namesp::*' behavior to return +procs in a namespace (dejong) + +2000-01-12 (feature enhancement) added support for setting permissions +symbolicly (like chmod) in [file attributes $file -permissions ...] (schoebel) + +2000-01-13 (bug fix) fixed lsort -dictionary problem when sorting +characters between 'Z' and 'a' (flawed upper/lower comparison logic) (melski) + +--- Released 8.3b2, January 13, 2000 --- See ChangeLog for details --- + +2000-01-14 (feature enhancement) clock format %Q added, clock scan updated + +2000-01-20 (bug fix) corrected complex array elem compiling (Spjuth) + +2000-01-20 (bug fix) made [info body] always return a string type arg, +to prevent possible misuse of bytecodes in the wrong context (hobbs) + +2000-01-20 (bug fixes) several fixes to variable handling to prevent +possible crashes, and further definition of correct behavior (melski) + +2000-01-25 (bug fixes) improved QNX, Ultrix and OSF1 (Tru64) config and +compatibility (edge, furukawa) + +2000-01-25 (bug fix) fixed mem leak when calling lsort with a bad -command +argument (hobbs) + +2000-01-27 (feature enhancement) package mechanism overhaul: changed +behavior of pkg_mkIndex to do -direct by default, added -lazy option. +Fixed pkg_mkIndex to handle odd proc names and auto_mkIndex to use platform +independent file paths. Other fixes for odd package quirks. Added +::pkg namespace and ::pkg::create helper function. (melski) + +2000-02-01 (bug fix) fixed problem where http POST would send one extra +newline (vasiljevic) + +2000-02-02 (feature enhancement) added docs for new regexp -inline and +-all switches. (hobbs) + +2000-02-08 (bug fix) corrected handling of "next monthname" in clock scan +(melski) + +2000-02-09 (bug fix) restored Mac source to build readiness and prevented +mac panic from an error when closing an async socket (steffen, ingham) + +2000-02-10 (feature enhancement) improved error reporting for failed +loads on Windows (dejong, hobbs) + +--- Released 8.3.0, February 10, 2000 --- See ChangeLog for details --- + +2000-03 (bug fixes, feature enhancement) overhaul of http package for +proper handling of async callbacks (new options), version is now at 2.3 +(tamhankar, welch) + +2000-03 (speed improvements) speedup in Windows filename handling (newman) +and ==/!= empty string in exprs. (hobbs) + +2000-03-27 (bug fix) added uniq'ing test to namespace export list to +prevent unnecessary mem growth (hobbs) + +2000-03-29 (bug fix) fixed mem leak when repeatedly sourcing the same +bytecompiled (tbc) code repeatedly across different interpreters (hobbs) + +2000-03-29 (config enhancement) improved build support for gcc/mingw on +Windows (nijtmans, hobbs) and added RPM target (melski) + +2000-03-31 (bug fix) corrected data encoding problem when using +"exec << $data" construct (melski) + +2000-04 (feature enhancement) overhaul of threading mechanism to better +support tcl level thread command (new APIs Tcl_ConditionFinalize, +Tcl_MutexFinalize, Tcl_CreateThread, etc, all docs in Thread.3). +(kupries, graveraux) +This enables the tcl level thread extension. (welch) + +2000-04-10 (bug fix) fixed infinite loop case in regexp -all (melski) + +2000-04-13 (config enhancement) added support for --enable-64bit-vis +Sparc target. (hobbs) + +2000-04-18 (bug fix) moved tclLibraryPath to thread-local storage to fix +possible race condition on MP machines (hobbs) + +2000-04-18 (config enhancement) added MacOS X build target and +tclLoadDyld.c dl type. (sanchez) + +2000-04-23 (bug fix) several Mac socket fixes (ingham) + +2000-04-24 (bug fix) fixed hang in threaded Unix case when backgrounded +exec process was running (dejong) + +--- Released 8.3.1, April 26, 2000 --- See ChangeLog for details --- + +2000-05-29 (bug fix) corrected resource cleanup in http error cases. +Improved handling of error cases in http. (tamhankar) + +2000-07 (feature rewrite) complete rewrite of the Tcl IO channel subsystem +to correct problems (hangs, core dumps) with the initial stacked channel +implementation. The new system has many more tests for robustness and +scalability. There are new C APIs (see Tcl_CreateChannel), but only +stacked channel drivers are affected (ie: TLS, Trf, iogt). The iogt +extension has been added to the core test code to test the system. +(hobbs, kupries) + **** POTENTIAL INCOMPATABILITY **** + +2000-07 (build improvements) cleanup of the makefiles and configure scripts +to correct support for building under gcc for Windows. (dejong) + +2000-08-07 (bug fix) corrected sizeof error in Tcl_GetIndexFromObjStruct. +(perkins) + +2000-08-07 (bug fix) correct off-by-one error in HistIndex, which was +causing [history redo] to start its search at the wrong event index. (melski) + +2000-08-07 (bug fix) corrected setlocale calls for XIM support and locale +issues in startup. (takahashi) + +2000-08-07 (bug fix) correct code to handle locale specific return values +from strftime, if any. (wagner) + +2000-08-07 (bug fix) tweaked grammar to properly handle the "ago" keyword +when it follows multiple relative unit specifiers, as in +"2 days 2 hours ago". (melski) + +2000-08-07 (doc fixes) numerous doc fixes to correct SEE ALSO and NAME +sections. (english) + +2000-08-07 (bug fix) new man pages memory.n, TCL_MEM_DEBUG.3, Init.3 and +DumpActiveMemory.3. (melski) + +--- Released 8.3.2, August 9, 2000 --- See ChangeLog for details --- + +2001-04-04 (build improvements) redid Mac build structure (steffen) +Corrected IRIX-5* configure (english). Added support for AIX-5 (hobbs). +Added support for Win64 (hobbs). + +2001-04-03 (doc fixes) numerous doc corrections and clarifications. +Update of READMEs. + +2001-03-30 (bug fix) corrected Windows memory error on exit (wu) +Fixed race condition in readability of socket on Windows. + +2001-03-29 (bug fix) prevent potential race condition and security leak in +tmp filename creation on Unix. (max) +Fixed handling of timeout for threads (corrects excessive CPU usage issue +for Tk on Unix in threaded Tcl environment). (ruppert) + +2001-03-13 (bug fix) Correctly possible memory corruption in string map {} +$str (fellows) + +2001-02-15 (feature enhancement) improved efficiency of [string split] +(fellows) + +2001-01-30 (bug fix) Fixed possible hangs in fcopy. (porter) + +2001-01-04 (bug fix) corrected parsing of $tcl_libPath at startup on +Windows (porter) + +2000-12-14 (feature enhancement) improved (s)rand for 64-bit platforms +(porter) + +2000-12-09 (feature enhancement) changed %o and %x to use strtoul instead +of strtol to correctly preserve scan<>format conversion of large integers +(hobbs) +Fixed handling of {!} in expressions (hobbs, fellows) + +2000-11-23 (mem leak) fixed potential memory leak in error case of lsort +(fellows) + +2000-11-02 (bug fix) Corrected sharing of tclLibraryPath in threaded +environment (gravereaux) + +2000-11-01 (mem leak) Corrected excessive mem use of info exists on a +non-existent array element (hobbs) + +2000-10-20 (feature enhancement) call stat only when necessary in 'glob' to +speed up command significantly in base cases (hobbs) + +2000-10-06 (bug fix) corrected [file channels] to only return channels in +the current interpreter (hobbs) + +2000-09-29 (bug fix) corrected reporting of space parity on Windows (Eason) + +2000-09-27 (bug fix) fixed a bug introduced by a partial fix in 8.3.2 that +didn't set nonBlocking correctly when resetting the flags for the write +side (mem leak) Correct mem leak in channels when statePtr was released +(hobbs) + +--- Released 8.3.3, April 6, 2001 --- See ChangeLog for details --- + +2001-06-27 (bug fix) corrected backslash substitution of non-ASCII characters. +(hobbs, riefenstahl) + +2001-07-02 (bug fix) corrected [concat] treatment of UTF-8 strings (hobbs, +barras) + +2001-07-16 (bug fix) corrected thread-enabled pipe closing on Windows +(hobbs, jsmith) + +2001-07-18 (bug fix) corrected memory overwrite error when buffer size +of a channel is changed after channel use has already begun (kupries, porter) + +2001-08-06 (bug fix) corrected object reference counting in [gets] (jikamens) + +2001-08-06 (new feature) added GNU (HURD) configuration target. (brinkmann) + +2001-08-07 (bug fix) corrected bytecode stack management during [break] +(see test foreach-5.5) (sofer, tallneil, jstrot) + +2001-08-08 (new features) updated packages msgcat 1.1.1, opt 0.4.3, +tcltest 1.0.1, dependencies checked (porter) + +2001-08-20 (new feature) http 2.3.2: include port number in Host: header +to comply with HTTP/1.1 spec (RFC 2068) (hobbs, tils) + +2001-08-23 (new feature) added QNX-6 build support (loverso) + +2001-08-23 (bug fix) corrected handling of spaces in path name passed to +[exec] on Windows (kenpoole) + +2001-08-24 (bug fix) corrected [package forget] stopping on non-existent +package (porter) + +2001-08-24 (bug fix) corrected construction of script library search path +relative to executable (porter) + +2001-08-24 (bug fix) [auto_import] now matches patterns like +[namespace import], not like [string match] (porter) + **** POTENTIAL INCOMPATABILITY **** + +2001-08-27 (new feature) added Tcl_SetMainLoop() to enable loading Tk as a +true package (hobbs) + +2001-08-30 (bug fix) build support for Crays (andreasen) + +2001-09-01 (bug fix) rewrite of Tcl_Async* APIs to better manage thread +cleanup (gravereaux) + +2001-09-06 (new feature) http 2.4: honor the Content-encoding and charset +parameters; add -binary switch for forcing the issue (hobbs, saoukhi, orwell) + +2001-09-06 (speed improvement) rewrite of file I/O flush management on +Windows. Approximately 100x speedup for some operations. (kupries, traum) + +2001-09-10 (bug fix) corrected finalization error in TclInExit (darley) + +2001-09-10 (bug fix) protect against alias loops (hobbs) + +2001-09-12 (bug fix) added missing #include in tclLoadShl.c (techentin) + +2001-09-12 (bug fix) script library path construction on Windows no longer +uses registry, nor adds the current working directory to the path (porter) + +2001-09-12 (bug fix) correct bugs in compatibility strtod() (porter) + +2001-09-13 (bug fix) Tcl_UtfPrev now returns the proper location when the +middle of a UTF-8 byte is passed in (hobbs) + +2001-09-19 (bug fix) [format] and [scan] corrected for 64-bit machines (rmax) + +2001-09-19 (new feature) --enable-64-bit support for HP-11. (hobbs) + +2001-09-19 (new feature) native memory allocator now default on Windows +(hobbs) + +2001-09-20 (new feature) WIN64 support and extra processor definitions +(hobbs, mstacy) + +2001-09-26 (bug fix) corrected potential deadlock in channels that do not +provide a BlockModeProc (kupries, kogorman) + +2001-10-03 (new feature) WIN64 build support (hobbs) + +2001-10-03 (bug fix) correction in thread finalization (rbrunner) + +2001-10-04 (new feature) updated encodings with latest mappings from +www.unicode.org (hobbs) + +2001-10-11 (bug fix) corrected cleanup of self-referential bytecodes at +interpreter deletion (sofer, rbrunner) + +2001-10-16 (new feature) config support for MacOSX / Darwin (steffen) + +2001-10-16 (new feature, Mac) change in binary extension format from MachO +bundles to standard .dylib dynamic libraries like on other unices. + **POTENTIAL INCOMPATIBILITY*** + +2001-10-18 (bug fix) corrected off-by-one-day error in clock scan with +relative months and years during swing hours. (lavana) + +--- Released 8.3.4, October 19, 2001 --- See ChangeLog for details --- + diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/compat/CVS/Entries b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..c475a6ed1ad264109ff592067c3c6ff425bc61aa --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/CVS/Entries @@ -0,0 +1,24 @@ +/README/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/dirent.h/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/dirent2.h/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/dlfcn.h/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/fixstrtod.c/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/float.h/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/gettod.c/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/license.terms/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/limits.h/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/memcmp.c/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/opendir.c/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/stdlib.h/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/strftime.c/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/string.h/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/strncasecmp.c/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/strstr.c/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/strtod.c/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/strtol.c/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/strtoul.c/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/tclErrno.h/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/tmpnam.c/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/unistd.h/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/waitpid.c/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +D diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/compat/CVS/Repository b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..635f87cf64c95bc34a6e4525376f9a840fa0d6e7 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/modtcl/tcl8.3.4/compat diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/compat/CVS/Root b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/compat/CVS/Tag b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/compat/README b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/README new file mode 100644 index 0000000000000000000000000000000000000000..7b655834dc484796021ae53e26f859ca8ed9772c --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/README @@ -0,0 +1,8 @@ +This directory contains various header and code files that are +used make Tcl compatible with various releases of UNIX and UNIX-like +systems. Typically, files from this directory are used to compile +Tcl when a system doesn't contain the corresponding files or when +they are known to be incorrect. When the whole world becomes POSIX- +compliant this directory should be unnecessary. + +RCS: @(#) $Id: README,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/compat/dirent.h b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/dirent.h new file mode 100644 index 0000000000000000000000000000000000000000..1a4a91241210ff52a46a961036fa5f0a7d3438d7 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/dirent.h @@ -0,0 +1,23 @@ +/* + * dirent.h -- + * + * This file is a replacement for in systems that + * support the old BSD-style with a "struct direct". + * + * Copyright (c) 1991 The Regents of the University of California. + * Copyright (c) 1994 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: dirent.h,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ + */ + +#ifndef _DIRENT +#define _DIRENT + +#include + +#define dirent direct + +#endif /* _DIRENT */ diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/compat/dirent2.h b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/dirent2.h new file mode 100644 index 0000000000000000000000000000000000000000..54e192cc685b6bb8af690d1fa780afe940cc1eeb --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/dirent2.h @@ -0,0 +1,59 @@ +/* + * dirent.h -- + * + * Declarations of a library of directory-reading procedures + * in the POSIX style ("struct dirent"). + * + * Copyright (c) 1991 The Regents of the University of California. + * Copyright (c) 1994 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: dirent2.h,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ + */ + +#ifndef _DIRENT +#define _DIRENT + +#ifndef _TCL +#include +#endif + +/* + * Dirent structure, which holds information about a single + * directory entry. + */ + +#define MAXNAMLEN 255 +#define DIRBLKSIZ 512 + +struct dirent { + long d_ino; /* Inode number of entry */ + short d_reclen; /* Length of this record */ + short d_namlen; /* Length of string in d_name */ + char d_name[MAXNAMLEN + 1]; /* Name must be no longer than this */ +}; + +/* + * State that keeps track of the reading of a directory (clients + * should never look inside this structure; the fields should + * only be accessed by the library procedures). + */ + +typedef struct _dirdesc { + int dd_fd; + long dd_loc; + long dd_size; + char dd_buf[DIRBLKSIZ]; +} DIR; + +/* + * Procedures defined for reading directories: + */ + +extern void closedir _ANSI_ARGS_((DIR *dirp)); +extern DIR * opendir _ANSI_ARGS_((char *name)); +extern struct dirent * readdir _ANSI_ARGS_((DIR *dirp)); + +#endif /* _DIRENT */ diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/compat/dlfcn.h b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/dlfcn.h new file mode 100644 index 0000000000000000000000000000000000000000..a7a364f884bd8d3c3b2d7ed723d9764a25069aca --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/dlfcn.h @@ -0,0 +1,65 @@ +/* + * dlfcn.h -- + * + * This file provides a replacement for the header file "dlfcn.h" + * on systems where dlfcn.h is missing. It's primary use is for + * AIX, where Tcl emulates the dl library. + * + * This file is subject to the following copyright notice, which is + * different from the notice used elsewhere in Tcl but rougly + * equivalent in meaning. + * + * Copyright (c) 1992,1993,1995,1996, Jens-Uwe Mager, Helios Software GmbH + * Not derived from licensed software. + * + * Permission is granted to freely use, copy, modify, and redistribute + * this software, provided that the author is not construed to be liable + * for any results of using the software, alterations are clearly marked + * as such, and this notice is not modified. + * + * RCS: @(#) $Id: dlfcn.h,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ + */ + +/* + * @(#)dlfcn.h 1.4 revision of 95/04/25 09:36:52 + * This is an unpublished work copyright (c) 1992 HELIOS Software GmbH + * 30159 Hannover, Germany + */ + +#ifndef __dlfcn_h__ +#define __dlfcn_h__ + +#ifndef _TCL +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Mode flags for the dlopen routine. + */ +#define RTLD_LAZY 1 /* lazy function call binding */ +#define RTLD_NOW 2 /* immediate function call binding */ +#define RTLD_GLOBAL 0x100 /* allow symbols to be global */ + +/* + * To be able to intialize, a library may provide a dl_info structure + * that contains functions to be called to initialize and terminate. + */ +struct dl_info { + void (*init) _ANSI_ARGS_((void)); + void (*fini) _ANSI_ARGS_((void)); +}; + +VOID *dlopen _ANSI_ARGS_((const char *path, int mode)); +VOID *dlsym _ANSI_ARGS_((void *handle, const char *symbol)); +char *dlerror _ANSI_ARGS_((void)); +int dlclose _ANSI_ARGS_((void *handle)); + +#ifdef __cplusplus +} +#endif + +#endif /* __dlfcn_h__ */ diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/compat/fixstrtod.c b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/fixstrtod.c new file mode 100644 index 0000000000000000000000000000000000000000..a068b65a3640fb7e30b0bc7da2b4b100d801fcf0 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/fixstrtod.c @@ -0,0 +1,38 @@ +/* + * fixstrtod.c -- + * + * Source code for the "fixstrtod" procedure. This procedure is + * used in place of strtod under Solaris 2.4, in order to fix + * a bug where the "end" pointer gets set incorrectly. + * + * Copyright (c) 1995 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: fixstrtod.c,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ + */ + +#include + +#undef strtod + +/* + * Declare strtod explicitly rather than including stdlib.h, since in + * somes systems (e.g. SunOS 4.1.4) stdlib.h doesn't declare strtod. + */ + +extern double strtod(); + +double +fixstrtod(string, endPtr) + char *string; + char **endPtr; +{ + double d; + d = strtod(string, endPtr); + if ((endPtr != NULL) && (*endPtr != string) && ((*endPtr)[-1] == 0)) { + *endPtr -= 1; + } + return d; +} diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/compat/float.h b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/float.h new file mode 100644 index 0000000000000000000000000000000000000000..bf0705bd2186c3266059f64c3ddf86c43dbf6627 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/float.h @@ -0,0 +1,16 @@ +/* + * float.h -- + * + * This is a dummy header file to #include in Tcl when there + * is no float.h in /usr/include. Right now this file is empty: + * Tcl contains #ifdefs to deal with the lack of definitions; + * all it needs is for the #include statement to work. + * + * Copyright (c) 1993 The Regents of the University of California. + * Copyright (c) 1994 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: float.h,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ + */ diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/compat/gettod.c b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/gettod.c new file mode 100644 index 0000000000000000000000000000000000000000..bee7c3dc4d4f7ea9ec1258f31816aca1b8ebe014 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/gettod.c @@ -0,0 +1,32 @@ +/* + * gettod.c -- + * + * This file provides the gettimeofday function on systems + * that only have the System V ftime function. + * + * Copyright (c) 1995 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: gettod.c,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ + */ + +#include "tcl.h" +#include "tclPort.h" +#include + +#undef timezone + +int +gettimeofday(tp, tz) +struct timeval *tp; +struct timezone *tz; +{ + struct timeb t; + ftime(&t); + tp->tv_sec = t.time; + tp->tv_usec = t. millitm * 1000; + return 0; +} + diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/compat/license.terms b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/license.terms new file mode 100644 index 0000000000000000000000000000000000000000..9df3e600352c50b7526dc4cb90758689d16ecee2 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/license.terms @@ -0,0 +1,39 @@ +This software is copyrighted by the Regents of the University of +California, Sun Microsystems, Inc., Scriptics Corporation, +and other parties. The following terms apply to all files associated +with the software unless explicitly disclaimed in individual files. + +The authors hereby grant permission to use, copy, modify, distribute, +and license this software and its documentation for any purpose, provided +that existing copyright notices are retained in all copies and that this +notice is included verbatim in any distributions. No written agreement, +license, or royalty fee is required for any of the authorized uses. +Modifications to this software may be copyrighted by their authors +and need not follow the licensing terms described here, provided that +the new terms are clearly indicated on the first page of each file where +they apply. + +IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY +FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES +ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY +DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE +IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE +NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR +MODIFICATIONS. + +GOVERNMENT USE: If you are acquiring this software on behalf of the +U.S. government, the Government shall have only "Restricted Rights" +in the software and related documentation as defined in the Federal +Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you +are acquiring the software on behalf of the Department of Defense, the +software shall be classified as "Commercial Computer Software" and the +Government shall have only "Restricted Rights" as defined in Clause +252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the +authors grant the U.S. Government and others acting in its behalf +permission to use and distribute the software in accordance with the +terms specified in this license. diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/compat/limits.h b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/limits.h new file mode 100644 index 0000000000000000000000000000000000000000..0ae75eab5eef474ff0e791aafec216cdc7b7f6a7 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/limits.h @@ -0,0 +1,24 @@ +/* + * limits.h -- + * + * This is a dummy header file to #include in Tcl when there + * is no limits.h in /usr/include. There are only a few + * definitions here; also see tclPort.h, which already + * #defines some of the things here if they're not arleady + * defined. + * + * Copyright (c) 1991 The Regents of the University of California. + * Copyright (c) 1994 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: limits.h,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ + */ + +#define LONG_MIN 0x80000000 +#define LONG_MAX 0x7fffffff +#define INT_MIN 0x80000000 +#define INT_MAX 0x7fffffff +#define SHRT_MIN 0x8000 +#define SHRT_MAX 0x7fff diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/compat/memcmp.c b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/memcmp.c new file mode 100644 index 0000000000000000000000000000000000000000..09a572424363a1ead58f2eb8f754d58d796bfb93 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/memcmp.c @@ -0,0 +1,61 @@ +/* + * memcmp.c -- + * + * Source code for the "memcmp" library routine. + * + * Copyright (c) 1998 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * SCCS: @(#) memcmp.c 1.2 98/01/19 10:48:58 + */ + +#include "tcl.h" +#include "tclPort.h" + +/* + * Here is the prototype just in case it is not included + * in tclPort.h. + */ + +int memcmp _ANSI_ARGS_((CONST VOID *s1, + CONST VOID *s2, size_t n)); + +/* + *---------------------------------------------------------------------- + * + * memcmp -- + * + * Compares two bytes sequences. + * + * Results: + * compares its arguments, looking at the first n + * bytes (each interpreted as an unsigned char), and returns + * an integer less than, equal to, or greater than 0, accord- + * ing as s1 is less than, equal to, or + * greater than s2 when taken to be unsigned 8 bit numbers. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +memcmp(s1, s2, n) + CONST VOID *s1; /* First string. */ + CONST VOID *s2; /* Second string. */ + size_t n; /* Length to compare. */ +{ + unsigned char u1, u2; + + for ( ; n-- ; s1++, s2++) { + u1 = * (unsigned char *) s1; + u2 = * (unsigned char *) s2; + if ( u1 != u2) { + return (u1-u2); + } + } + return 0; +} diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/compat/opendir.c b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/opendir.c new file mode 100644 index 0000000000000000000000000000000000000000..c49c8d8bc2095776c997e29c12d739b7c15748a3 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/opendir.c @@ -0,0 +1,108 @@ +/* + * opendir.c -- + * + * This file provides dirent-style directory-reading procedures + * for V7 Unix systems that don't have such procedures. The + * origin of this code is unclear, but it seems to have come + * originally from Larry Wall. + * + * + * RCS: @(#) $Id: opendir.c,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ + */ + +#include "tclInt.h" +#include "tclPort.h" + +#undef DIRSIZ +#define DIRSIZ(dp) \ + ((sizeof (struct dirent) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3)) + +/* + * open a directory. + */ +DIR * +opendir(name) +char *name; +{ + register DIR *dirp; + register int fd; + char *myname; + + myname = ((*name == '\0') ? "." : name); + if ((fd = open(myname, 0, 0)) == -1) + return NULL; + if ((dirp = (DIR *)ckalloc(sizeof(DIR))) == NULL) { + close (fd); + return NULL; + } + dirp->dd_fd = fd; + dirp->dd_loc = 0; + return dirp; +} + +/* + * read an old style directory entry and present it as a new one + */ +#ifndef pyr +#define ODIRSIZ 14 + +struct olddirect { + ino_t od_ino; + char od_name[ODIRSIZ]; +}; +#else /* a Pyramid in the ATT universe */ +#define ODIRSIZ 248 + +struct olddirect { + long od_ino; + short od_fill1, od_fill2; + char od_name[ODIRSIZ]; +}; +#endif + +/* + * get next entry in a directory. + */ +struct dirent * +readdir(dirp) +register DIR *dirp; +{ + register struct olddirect *dp; + static struct dirent dir; + + for (;;) { + if (dirp->dd_loc == 0) { + dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, + DIRBLKSIZ); + if (dirp->dd_size <= 0) + return NULL; + } + if (dirp->dd_loc >= dirp->dd_size) { + dirp->dd_loc = 0; + continue; + } + dp = (struct olddirect *)(dirp->dd_buf + dirp->dd_loc); + dirp->dd_loc += sizeof(struct olddirect); + if (dp->od_ino == 0) + continue; + dir.d_ino = dp->od_ino; + strncpy(dir.d_name, dp->od_name, ODIRSIZ); + dir.d_name[ODIRSIZ] = '\0'; /* insure null termination */ + dir.d_namlen = strlen(dir.d_name); + dir.d_reclen = DIRSIZ(&dir); + return (&dir); + } +} + +/* + * close a directory. + */ +void +closedir(dirp) +register DIR *dirp; +{ + close(dirp->dd_fd); + dirp->dd_fd = -1; + dirp->dd_loc = 0; + ckfree((char *) dirp); +} diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/compat/stdlib.h b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/stdlib.h new file mode 100644 index 0000000000000000000000000000000000000000..42ea64017a5062d80e9303997c794c6d459e97b7 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/stdlib.h @@ -0,0 +1,45 @@ +/* + * stdlib.h -- + * + * Declares facilities exported by the "stdlib" portion of + * the C library. This file isn't complete in the ANSI-C + * sense; it only declares things that are needed by Tcl. + * This file is needed even on many systems with their own + * stdlib.h (e.g. SunOS) because not all stdlib.h files + * declare all the procedures needed here (such as strtod). + * + * Copyright (c) 1991 The Regents of the University of California. + * Copyright (c) 1994-1998 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: stdlib.h,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ + */ + +#ifndef _STDLIB +#define _STDLIB + +#include + +extern void abort _ANSI_ARGS_((void)); +extern double atof _ANSI_ARGS_((CONST char *string)); +extern int atoi _ANSI_ARGS_((CONST char *string)); +extern long atol _ANSI_ARGS_((CONST char *string)); +extern char * calloc _ANSI_ARGS_((unsigned int numElements, + unsigned int size)); +extern void exit _ANSI_ARGS_((int status)); +extern int free _ANSI_ARGS_((char *blockPtr)); +extern char * getenv _ANSI_ARGS_((CONST char *name)); +extern char * malloc _ANSI_ARGS_((unsigned int numBytes)); +extern void qsort _ANSI_ARGS_((VOID *base, int n, int size, + int (*compar)(CONST VOID *element1, CONST VOID + *element2))); +extern char * realloc _ANSI_ARGS_((char *ptr, unsigned int numBytes)); +extern double strtod _ANSI_ARGS_((CONST char *string, char **endPtr)); +extern long strtol _ANSI_ARGS_((CONST char *string, char **endPtr, + int base)); +extern unsigned long strtoul _ANSI_ARGS_((CONST char *string, + char **endPtr, int base)); + +#endif /* _STDLIB */ diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/compat/strftime.c b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/strftime.c new file mode 100644 index 0000000000000000000000000000000000000000..caff1ca29fc2ed7b9446436ab3aab9217c8c040f --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/strftime.c @@ -0,0 +1,393 @@ +/* + * strftime.c -- + * + * This file contains a modified version of the BSD 4.4 strftime + * function. + * + * This file is a modified version of the strftime.c file from the BSD 4.4 + * source. See the copyright notice below for details on redistribution + * restrictions. The "license.terms" file does not apply to this file. + * + * RCS: @(#) $Id: strftime.c,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ + */ + +/* + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 THE REGENTS 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. + */ + +#if defined(LIBC_SCCS) +static char *rcsid = "$Id: strftime.c,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $"; +#endif /* LIBC_SCCS */ + +#include +#include +#include +#include "tclInt.h" +#include "tclPort.h" + +#define TM_YEAR_BASE 1900 +#define IsLeapYear(x) ((x % 4 == 0) && (x % 100 != 0 || x % 400 == 0)) + +typedef struct { + const char *abday[7]; + const char *day[7]; + const char *abmon[12]; + const char *mon[12]; + const char *am_pm[2]; + const char *d_t_fmt; + const char *d_fmt; + const char *t_fmt; + const char *t_fmt_ampm; +} _TimeLocale; + +static const _TimeLocale _DefaultTimeLocale = +{ + { + "Sun","Mon","Tue","Wed","Thu","Fri","Sat", + }, + { + "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", + "Friday", "Saturday" + }, + { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" + }, + { + "January", "February", "March", "April", "May", "June", "July", + "August", "September", "October", "November", "December" + }, + { + "AM", "PM" + }, + "%a %b %d %H:%M:%S %Y", + "%m/%d/%y", + "%H:%M:%S", + "%I:%M:%S %p" +}; + +static const _TimeLocale *_CurrentTimeLocale = &_DefaultTimeLocale; + +static size_t gsize; +static char *pt; +static int _add _ANSI_ARGS_((const char* str)); +static int _conv _ANSI_ARGS_((int n, int digits, int pad)); +static int _secs _ANSI_ARGS_((const struct tm *t)); +static size_t _fmt _ANSI_ARGS_((const char *format, + const struct tm *t)); + +size_t +TclpStrftime(s, maxsize, format, t) + char *s; + size_t maxsize; + const char *format; + const struct tm *t; +{ + if (format[0] == '%' && format[1] == 'Q') { + /* Format as a stardate */ + sprintf(s, "Stardate %2d%03d.%01d", + (((t->tm_year + TM_YEAR_BASE) + 377) - 2323), + (((t->tm_yday + 1) * 1000) / + (365 + IsLeapYear((t->tm_year + TM_YEAR_BASE)))), + (((t->tm_hour * 60) + t->tm_min)/144)); + return(strlen(s)); + } + + tzset(); + + pt = s; + if ((gsize = maxsize) < 1) + return(0); + if (_fmt(format, t)) { + *pt = '\0'; + return(maxsize - gsize); + } + return(0); +} + +#define SUN_WEEK(t) (((t)->tm_yday + 7 - \ + ((t)->tm_wday)) / 7) +#define MON_WEEK(t) (((t)->tm_yday + 7 - \ + ((t)->tm_wday ? (t)->tm_wday - 1 : 6)) / 7) + +static size_t +_fmt(format, t) + const char *format; + const struct tm *t; +{ + for (; *format; ++format) { + if (*format == '%') { + ++format; + if (*format == 'E') { + /* Alternate Era */ + ++format; + } else if (*format == 'O') { + /* Alternate numeric symbols */ + ++format; + } + switch(*format) { + case '\0': + --format; + break; + case 'A': + if (t->tm_wday < 0 || t->tm_wday > 6) + return(0); + if (!_add(_CurrentTimeLocale->day[t->tm_wday])) + return(0); + continue; + case 'a': + if (t->tm_wday < 0 || t->tm_wday > 6) + return(0); + if (!_add(_CurrentTimeLocale->abday[t->tm_wday])) + return(0); + continue; + case 'B': + if (t->tm_mon < 0 || t->tm_mon > 11) + return(0); + if (!_add(_CurrentTimeLocale->mon[t->tm_mon])) + return(0); + continue; + case 'b': + case 'h': + if (t->tm_mon < 0 || t->tm_mon > 11) + return(0); + if (!_add(_CurrentTimeLocale->abmon[t->tm_mon])) + return(0); + continue; + case 'C': + if (!_conv((t->tm_year + TM_YEAR_BASE) / 100, + 2, '0')) + return(0); + continue; + case 'c': + if (!_fmt(_CurrentTimeLocale->d_t_fmt, t)) + return(0); + continue; + case 'D': + if (!_fmt("%m/%d/%y", t)) + return(0); + continue; + case 'd': + if (!_conv(t->tm_mday, 2, '0')) + return(0); + continue; + case 'e': + if (!_conv(t->tm_mday, 2, ' ')) + return(0); + continue; + case 'H': + if (!_conv(t->tm_hour, 2, '0')) + return(0); + continue; + case 'I': + if (!_conv(t->tm_hour % 12 ? + t->tm_hour % 12 : 12, 2, '0')) + return(0); + continue; + case 'j': + if (!_conv(t->tm_yday + 1, 3, '0')) + return(0); + continue; + case 'k': + if (!_conv(t->tm_hour, 2, ' ')) + return(0); + continue; + case 'l': + if (!_conv(t->tm_hour % 12 ? + t->tm_hour % 12: 12, 2, ' ')) + return(0); + continue; + case 'M': + if (!_conv(t->tm_min, 2, '0')) + return(0); + continue; + case 'm': + if (!_conv(t->tm_mon + 1, 2, '0')) + return(0); + continue; + case 'n': + if (!_add("\n")) + return(0); + continue; + case 'p': + if (!_add(_CurrentTimeLocale->am_pm[t->tm_hour >= 12])) + return(0); + continue; + case 'R': + if (!_fmt("%H:%M", t)) + return(0); + continue; + case 'r': + if (!_fmt(_CurrentTimeLocale->t_fmt_ampm, t)) + return(0); + continue; + case 'S': + if (!_conv(t->tm_sec, 2, '0')) + return(0); + continue; + case 's': + if (!_secs(t)) + return(0); + continue; + case 'T': + if (!_fmt("%H:%M:%S", t)) + return(0); + continue; + case 't': + if (!_add("\t")) + return(0); + continue; + case 'U': + if (!_conv(SUN_WEEK(t), 2, '0')) + return(0); + continue; + case 'u': + if (!_conv(t->tm_wday ? t->tm_wday : 7, 1, '0')) + return(0); + continue; + case 'V': + { + /* ISO 8601 Week Of Year: + If the week (Monday - Sunday) containing + January 1 has four or more days in the new + year, then it is week 1; otherwise it is + week 53 of the previous year and the next + week is week one. */ + + int week = MON_WEEK(t); + + int days = (((t)->tm_yday + 7 - \ + ((t)->tm_wday ? (t)->tm_wday - 1 : 6)) % 7); + + + if (days >= 4) { + week++; + } else if (week == 0) { + week = 53; + } + + if (!_conv(week, 2, '0')) + return(0); + continue; + } + case 'W': + if (!_conv(MON_WEEK(t), 2, '0')) + return(0); + continue; + case 'w': + if (!_conv(t->tm_wday, 1, '0')) + return(0); + continue; + case 'x': + if (!_fmt(_CurrentTimeLocale->d_fmt, t)) + return(0); + continue; + case 'X': + if (!_fmt(_CurrentTimeLocale->t_fmt, t)) + return(0); + continue; + case 'y': + if (!_conv((t->tm_year + TM_YEAR_BASE) % 100, + 2, '0')) + return(0); + continue; + case 'Y': + if (!_conv((t->tm_year + TM_YEAR_BASE), 4, '0')) + return(0); + continue; + case 'Z': { + char *name = TclpGetTZName(t->tm_isdst); + if (name && !_add(name)) { + return 0; + } + continue; + } + case '%': + /* + * X311J/88-090 (4.12.3.5): if conversion char is + * undefined, behavior is undefined. Print out the + * character itself as printf(3) does. + */ + default: + break; + } + } + if (!gsize--) + return(0); + *pt++ = *format; + } + return(gsize); +} + +static int +_secs(t) + const struct tm *t; +{ + static char buf[15]; + register time_t s; + register char *p; + struct tm tmp; + + /* Make a copy, mktime(3) modifies the tm struct. */ + tmp = *t; + s = mktime(&tmp); + for (p = buf + sizeof(buf) - 2; s > 0 && p > buf; s /= 10) + *p-- = (char)(s % 10 + '0'); + return(_add(++p)); +} + +static int +_conv(n, digits, pad) + int n, digits; + int pad; +{ + static char buf[10]; + register char *p; + + for (p = buf + sizeof(buf) - 2; n > 0 && p > buf; n /= 10, --digits) + *p-- = (char)(n % 10 + '0'); + while (p > buf && digits-- > 0) + *p-- = (char) pad; + return(_add(++p)); +} + +static int +_add(str) + const char *str; +{ + for (;; ++pt, --gsize) { + if (!gsize) + return(0); + if (!(*pt = *str++)) + return(1); + } +} diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/compat/string.h b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/string.h new file mode 100644 index 0000000000000000000000000000000000000000..7eed98c7a426e085cdbc5eb6607d01c3a71b90b2 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/string.h @@ -0,0 +1,71 @@ +/* + * string.h -- + * + * Declarations of ANSI C library procedures for string handling. + * + * Copyright (c) 1991-1993 The Regents of the University of California. + * Copyright (c) 1994-1996 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: string.h,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ + */ + +#ifndef _STRING +#define _STRING + +#include + +/* + * The following #include is needed to define size_t. (This used to + * include sys/stdtypes.h but that doesn't exist on older versions + * of SunOS, e.g. 4.0.2, so I'm trying sys/types.h now.... hopefully + * it exists everywhere) + */ + +#ifndef MAC_TCL +#include +#endif + +extern char * memchr _ANSI_ARGS_((CONST VOID *s, int c, size_t n)); +extern int memcmp _ANSI_ARGS_((CONST VOID *s1, CONST VOID *s2, + size_t n)); +extern char * memcpy _ANSI_ARGS_((VOID *t, CONST VOID *f, size_t n)); +#ifdef NO_MEMMOVE +#define memmove(d, s, n) bcopy ((s), (d), (n)) +#else +extern char * memmove _ANSI_ARGS_((VOID *t, CONST VOID *f, + size_t n)); +#endif +extern char * memset _ANSI_ARGS_((VOID *s, int c, size_t n)); + +extern int strcasecmp _ANSI_ARGS_((CONST char *s1, + CONST char *s2)); +extern char * strcat _ANSI_ARGS_((char *dst, CONST char *src)); +extern char * strchr _ANSI_ARGS_((CONST char *string, int c)); +extern int strcmp _ANSI_ARGS_((CONST char *s1, CONST char *s2)); +extern char * strcpy _ANSI_ARGS_((char *dst, CONST char *src)); +extern size_t strcspn _ANSI_ARGS_((CONST char *string, + CONST char *chars)); +extern char * strdup _ANSI_ARGS_((CONST char *string)); +extern char * strerror _ANSI_ARGS_((int error)); +extern size_t strlen _ANSI_ARGS_((CONST char *string)); +extern int strncasecmp _ANSI_ARGS_((CONST char *s1, + CONST char *s2, size_t n)); +extern char * strncat _ANSI_ARGS_((char *dst, CONST char *src, + size_t numChars)); +extern int strncmp _ANSI_ARGS_((CONST char *s1, CONST char *s2, + size_t nChars)); +extern char * strncpy _ANSI_ARGS_((char *dst, CONST char *src, + size_t numChars)); +extern char * strpbrk _ANSI_ARGS_((CONST char *string, + CONST char *chars)); +extern char * strrchr _ANSI_ARGS_((CONST char *string, int c)); +extern size_t strspn _ANSI_ARGS_((CONST char *string, + CONST char *chars)); +extern char * strstr _ANSI_ARGS_((CONST char *string, + CONST char *substring)); +extern char * strtok _ANSI_ARGS_((char *s, CONST char *delim)); + +#endif /* _STRING */ diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/compat/strncasecmp.c b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/strncasecmp.c new file mode 100644 index 0000000000000000000000000000000000000000..4dc16b2b26751dc41666e9a21832d3367827440c --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/strncasecmp.c @@ -0,0 +1,142 @@ +/* + * strncasecmp.c -- + * + * Source code for the "strncasecmp" library routine. + * + * Copyright (c) 1988-1993 The Regents of the University of California. + * Copyright (c) 1995-1996 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: strncasecmp.c,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ + */ + +#include "tclPort.h" + +/* + * This array is designed for mapping upper and lower case letter + * together for a case independent comparison. The mappings are + * based upon ASCII character sequences. + */ + +static unsigned char charmap[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xe1, 0xe2, 0xe3, 0xe4, 0xc5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, +}; + +/* + * Here are the prototypes just in case they are not included + * in tclPort.h. + */ +int strncasecmp _ANSI_ARGS_((CONST char *s1, + CONST char *s2, size_t n)); + +int strcasecmp _ANSI_ARGS_((CONST char *s1, + CONST char *s2)); + +/* + *---------------------------------------------------------------------- + * + * strcasecmp -- + * + * Compares two strings, ignoring case differences. + * + * Results: + * Compares two null-terminated strings s1 and s2, returning -1, 0, + * or 1 if s1 is lexicographically less than, equal to, or greater + * than s2. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +strcasecmp(s1, s2) + CONST char *s1; /* First string. */ + CONST char *s2; /* Second string. */ +{ + unsigned char u1, u2; + + for ( ; ; s1++, s2++) { + u1 = (unsigned char) *s1; + u2 = (unsigned char) *s2; + if ((u1 == '\0') || (charmap[u1] != charmap[u2])) { + break; + } + } + return charmap[u1] - charmap[u2]; +} + +/* + *---------------------------------------------------------------------- + * + * strncasecmp -- + * + * Compares two strings, ignoring case differences. + * + * Results: + * Compares up to length chars of s1 and s2, returning -1, 0, or 1 + * if s1 is lexicographically less than, equal to, or greater + * than s2 over those characters. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +strncasecmp(s1, s2, length) + CONST char *s1; /* First string. */ + CONST char *s2; /* Second string. */ + size_t length; /* Maximum number of characters to compare + * (stop earlier if the end of either string + * is reached). */ +{ + unsigned char u1, u2; + + for (; length != 0; length--, s1++, s2++) { + u1 = (unsigned char) *s1; + u2 = (unsigned char) *s2; + if (charmap[u1] != charmap[u2]) { + return charmap[u1] - charmap[u2]; + } + if (u1 == '\0') { + return 0; + } + } + return 0; +} diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/compat/strstr.c b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/strstr.c new file mode 100644 index 0000000000000000000000000000000000000000..7284a2d281431ce0545de51bb5eaf4ee885fa537 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/strstr.c @@ -0,0 +1,68 @@ +/* + * strstr.c -- + * + * Source code for the "strstr" library routine. + * + * Copyright (c) 1988-1993 The Regents of the University of California. + * Copyright (c) 1994 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: strstr.c,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ + */ + +/* + *---------------------------------------------------------------------- + * + * strstr -- + * + * Locate the first instance of a substring in a string. + * + * Results: + * If string contains substring, the return value is the + * location of the first matching instance of substring + * in string. If string doesn't contain substring, the + * return value is 0. Matching is done on an exact + * character-for-character basis with no wildcards or special + * characters. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +char * +strstr(string, substring) + register char *string; /* String to search. */ + char *substring; /* Substring to try to find in string. */ +{ + register char *a, *b; + + /* First scan quickly through the two strings looking for a + * single-character match. When it's found, then compare the + * rest of the substring. + */ + + b = substring; + if (*b == 0) { + return string; + } + for ( ; *string != 0; string += 1) { + if (*string != *b) { + continue; + } + a = string; + while (1) { + if (*b == 0) { + return string; + } + if (*a++ != *b++) { + break; + } + } + b = substring; + } + return (char *) 0; +} diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/compat/strtod.c b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/strtod.c new file mode 100644 index 0000000000000000000000000000000000000000..9c308ee4535b1532fd8e07a2e346170eb0dc2f94 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/strtod.c @@ -0,0 +1,263 @@ +/* + * strtod.c -- + * + * Source code for the "strtod" library procedure. + * + * Copyright (c) 1988-1993 The Regents of the University of California. + * Copyright (c) 1994 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: strtod.c,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ + */ + +#include "tcl.h" +#ifdef NO_STDLIB_H +# include "../compat/stdlib.h" +#else +# include +#endif +#include +#include "tclPort.h" + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif +#ifndef NULL +#define NULL 0 +#endif + +static int maxExponent = 511; /* Largest possible base 10 exponent. Any + * exponent larger than this will already + * produce underflow or overflow, so there's + * no need to worry about additional digits. + */ +static double powersOf10[] = { /* Table giving binary powers of 10. Entry */ + 10., /* is 10^2^i. Used to convert decimal */ + 100., /* exponents into floating-point numbers. */ + 1.0e4, + 1.0e8, + 1.0e16, + 1.0e32, + 1.0e64, + 1.0e128, + 1.0e256 +}; + +/* + *---------------------------------------------------------------------- + * + * strtod -- + * + * This procedure converts a floating-point number from an ASCII + * decimal representation to internal double-precision format. + * + * Results: + * The return value is the double-precision floating-point + * representation of the characters in string. If endPtr isn't + * NULL, then *endPtr is filled in with the address of the + * next character after the last one that was part of the + * floating-point number. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +double +strtod(string, endPtr) + CONST char *string; /* A decimal ASCII floating-point number, + * optionally preceded by white space. + * Must have form "-I.FE-X", where I is the + * integer part of the mantissa, F is the + * fractional part of the mantissa, and X + * is the exponent. Either of the signs + * may be "+", "-", or omitted. Either I + * or F may be omitted, or both. The decimal + * point isn't necessary unless F is present. + * The "E" may actually be an "e". E and X + * may both be omitted (but not just one). + */ + char **endPtr; /* If non-NULL, store terminating character's + * address here. */ +{ + int sign, expSign = FALSE; + double fraction, dblExp, *d; + register CONST char *p; + register int c; + int exp = 0; /* Exponent read from "EX" field. */ + int fracExp = 0; /* Exponent that derives from the fractional + * part. Under normal circumstatnces, it is + * the negative of the number of digits in F. + * However, if I is very long, the last digits + * of I get dropped (otherwise a long I with a + * large negative exponent could cause an + * unnecessary overflow on I alone). In this + * case, fracExp is incremented one for each + * dropped digit. */ + int mantSize; /* Number of digits in mantissa. */ + int decPt; /* Number of mantissa digits BEFORE decimal + * point. */ + CONST char *pExp; /* Temporarily holds location of exponent + * in string. */ + + /* + * Strip off leading blanks and check for a sign. + */ + + p = string; + while (isspace(*p)) { + p += 1; + } + if (*p == '-') { + sign = TRUE; + p += 1; + } else { + if (*p == '+') { + p += 1; + } + sign = FALSE; + } + + /* + * Count the number of digits in the mantissa (including the decimal + * point), and also locate the decimal point. + */ + + decPt = -1; + for (mantSize = 0; ; mantSize += 1) + { + c = *p; + if (!isdigit(c)) { + if ((c != '.') || (decPt >= 0)) { + break; + } + decPt = mantSize; + } + p += 1; + } + + /* + * Now suck up the digits in the mantissa. Use two integers to + * collect 9 digits each (this is faster than using floating-point). + * If the mantissa has more than 18 digits, ignore the extras, since + * they can't affect the value anyway. + */ + + pExp = p; + p -= mantSize; + if (decPt < 0) { + decPt = mantSize; + } else { + mantSize -= 1; /* One of the digits was the point. */ + } + if (mantSize > 18) { + fracExp = decPt - 18; + mantSize = 18; + } else { + fracExp = decPt - mantSize; + } + if (mantSize == 0) { + fraction = 0.0; + p = string; + goto done; + } else { + int frac1, frac2; + frac1 = 0; + for ( ; mantSize > 9; mantSize -= 1) + { + c = *p; + p += 1; + if (c == '.') { + c = *p; + p += 1; + } + frac1 = 10*frac1 + (c - '0'); + } + frac2 = 0; + for (; mantSize > 0; mantSize -= 1) + { + c = *p; + p += 1; + if (c == '.') { + c = *p; + p += 1; + } + frac2 = 10*frac2 + (c - '0'); + } + fraction = (1.0e9 * frac1) + frac2; + } + + /* + * Skim off the exponent. + */ + + p = pExp; + if ((*p == 'E') || (*p == 'e')) { + p += 1; + if (*p == '-') { + expSign = TRUE; + p += 1; + } else { + if (*p == '+') { + p += 1; + } + expSign = FALSE; + } + if (!isdigit(*p)) { + p = pExp; + goto done; + } + while (isdigit(*p)) { + exp = exp * 10 + (*p - '0'); + p += 1; + } + } + if (expSign) { + exp = fracExp - exp; + } else { + exp = fracExp + exp; + } + + /* + * Generate a floating-point number that represents the exponent. + * Do this by processing the exponent one bit at a time to combine + * many powers of 2 of 10. Then combine the exponent with the + * fraction. + */ + + if (exp < 0) { + expSign = TRUE; + exp = -exp; + } else { + expSign = FALSE; + } + if (exp > maxExponent) { + exp = maxExponent; + errno = ERANGE; + } + dblExp = 1.0; + for (d = powersOf10; exp != 0; exp >>= 1, d += 1) { + if (exp & 01) { + dblExp *= *d; + } + } + if (expSign) { + fraction /= dblExp; + } else { + fraction *= dblExp; + } + +done: + if (endPtr != NULL) { + *endPtr = (char *) p; + } + + if (sign) { + return -fraction; + } + return fraction; +} diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/compat/strtol.c b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/strtol.c new file mode 100644 index 0000000000000000000000000000000000000000..c56dc19fe19116521b9f268c9e3d5d3690aa6385 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/strtol.c @@ -0,0 +1,83 @@ +/* + * strtol.c -- + * + * Source code for the "strtol" library procedure. + * + * Copyright (c) 1988 The Regents of the University of California. + * Copyright (c) 1994 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: strtol.c,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ + */ + +#include + + +/* + *---------------------------------------------------------------------- + * + * strtol -- + * + * Convert an ASCII string into an integer. + * + * Results: + * The return value is the integer equivalent of string. If endPtr + * is non-NULL, then *endPtr is filled in with the character + * after the last one that was part of the integer. If string + * doesn't contain a valid integer value, then zero is returned + * and *endPtr is set to string. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +long int +strtol(string, endPtr, base) + char *string; /* String of ASCII digits, possibly + * preceded by white space. For bases + * greater than 10, either lower- or + * upper-case digits may be used. + */ + char **endPtr; /* Where to store address of terminating + * character, or NULL. */ + int base; /* Base for conversion. Must be less + * than 37. If 0, then the base is chosen + * from the leading characters of string: + * "0x" means hex, "0" means octal, anything + * else means decimal. + */ +{ + register char *p; + int result; + + /* + * Skip any leading blanks. + */ + + p = string; + while (isspace(*p)) { + p += 1; + } + + /* + * Check for a sign. + */ + + if (*p == '-') { + p += 1; + result = -(strtoul(p, endPtr, base)); + } else { + if (*p == '+') { + p += 1; + } + result = strtoul(p, endPtr, base); + } + if ((result == 0) && (endPtr != 0) && (*endPtr == p)) { + *endPtr = string; + } + return result; +} diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/compat/strtoul.c b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/strtoul.c new file mode 100644 index 0000000000000000000000000000000000000000..6115aff34720c705b651d0adf3fa69ba470b4159 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/strtoul.c @@ -0,0 +1,183 @@ +/* + * strtoul.c -- + * + * Source code for the "strtoul" library procedure. + * + * Copyright (c) 1988 The Regents of the University of California. + * Copyright (c) 1994 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: strtoul.c,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ + */ + +#include + +/* + * The table below is used to convert from ASCII digits to a + * numerical equivalent. It maps from '0' through 'z' to integers + * (100 for non-digit characters). + */ + +static char cvtIn[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* '0' - '9' */ + 100, 100, 100, 100, 100, 100, 100, /* punctuation */ + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, /* 'A' - 'Z' */ + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, + 100, 100, 100, 100, 100, 100, /* punctuation */ + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, /* 'a' - 'z' */ + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35}; + +/* + *---------------------------------------------------------------------- + * + * strtoul -- + * + * Convert an ASCII string into an integer. + * + * Results: + * The return value is the integer equivalent of string. If endPtr + * is non-NULL, then *endPtr is filled in with the character + * after the last one that was part of the integer. If string + * doesn't contain a valid integer value, then zero is returned + * and *endPtr is set to string. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +unsigned long int +strtoul(string, endPtr, base) + char *string; /* String of ASCII digits, possibly + * preceded by white space. For bases + * greater than 10, either lower- or + * upper-case digits may be used. + */ + char **endPtr; /* Where to store address of terminating + * character, or NULL. */ + int base; /* Base for conversion. Must be less + * than 37. If 0, then the base is chosen + * from the leading characters of string: + * "0x" means hex, "0" means octal, anything + * else means decimal. + */ +{ + register char *p; + register unsigned long int result = 0; + register unsigned digit; + int anyDigits = 0; + + /* + * Skip any leading blanks. + */ + + p = string; + while (isspace(*p)) { + p += 1; + } + + /* + * If no base was provided, pick one from the leading characters + * of the string. + */ + + if (base == 0) + { + if (*p == '0') { + p += 1; + if (*p == 'x') { + p += 1; + base = 16; + } else { + + /* + * Must set anyDigits here, otherwise "0" produces a + * "no digits" error. + */ + + anyDigits = 1; + base = 8; + } + } + else base = 10; + } else if (base == 16) { + + /* + * Skip a leading "0x" from hex numbers. + */ + + if ((p[0] == '0') && (p[1] == 'x')) { + p += 2; + } + } + + /* + * Sorry this code is so messy, but speed seems important. Do + * different things for base 8, 10, 16, and other. + */ + + if (base == 8) { + for ( ; ; p += 1) { + digit = *p - '0'; + if (digit > 7) { + break; + } + result = (result << 3) + digit; + anyDigits = 1; + } + } else if (base == 10) { + for ( ; ; p += 1) { + digit = *p - '0'; + if (digit > 9) { + break; + } + result = (10*result) + digit; + anyDigits = 1; + } + } else if (base == 16) { + for ( ; ; p += 1) { + digit = *p - '0'; + if (digit > ('z' - '0')) { + break; + } + digit = cvtIn[digit]; + if (digit > 15) { + break; + } + result = (result << 4) + digit; + anyDigits = 1; + } + } else { + for ( ; ; p += 1) { + digit = *p - '0'; + if (digit > ('z' - '0')) { + break; + } + digit = cvtIn[digit]; + if (digit >= base) { + break; + } + result = result*base + digit; + anyDigits = 1; + } + } + + /* + * See if there were any digits at all. + */ + + if (!anyDigits) { + p = string; + } + + if (endPtr != 0) { + *endPtr = p; + } + + return result; +} diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/compat/tclErrno.h b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/tclErrno.h new file mode 100644 index 0000000000000000000000000000000000000000..52298470b8f7d4fa4ddcd03d7469ca910ca4c259 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/tclErrno.h @@ -0,0 +1,100 @@ +/* + * tclErrno.h -- + * + * This header file contains the various POSIX errno definitions that + * are used by Tcl. This file is derived from the spec POSIX 2.4 and + * previous implementations for Berkeley UNIX. + * + * Copyright (c) 1982, 1986, 1989 Regents of the University of California. + * Copyright (c) 1996 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tclErrno.h,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ + */ + +extern int errno; /* global error number */ + +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* Input/output error */ +#define ENXIO 6 /* Device not configured */ +#define E2BIG 7 /* Argument list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file descriptor */ +#define ECHILD 10 /* No child processes */ +#define EDEADLK 11 /* Resource deadlock avoided */ + /* 11 was EAGAIN */ +#define ENOMEM 12 /* Cannot allocate memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENOTBLK 15 /* Block device required */ +#define EBUSY 16 /* Device busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* Operation not supported by device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* Too many open files in system */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Inappropriate ioctl for device */ +#define ETXTBSY 26 /* Text file busy */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only file system */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ +#define EDOM 33 /* Numerical argument out of domain */ +#define ERANGE 34 /* Result too large */ +#define EAGAIN 35 /* Resource temporarily unavailable */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#define EINPROGRESS 36 /* Operation now in progress */ +#define EALREADY 37 /* Operation already in progress */ +#define ENOTSOCK 38 /* Socket operation on non-socket */ +#define EDESTADDRREQ 39 /* Destination address required */ +#define EMSGSIZE 40 /* Message too long */ +#define EPROTOTYPE 41 /* Protocol wrong type for socket */ +#define ENOPROTOOPT 42 /* Protocol not available */ +#define EPROTONOSUPPORT 43 /* Protocol not supported */ +#define ESOCKTNOSUPPORT 44 /* Socket type not supported */ +#define EOPNOTSUPP 45 /* Operation not supported on socket */ +#define EPFNOSUPPORT 46 /* Protocol family not supported */ +#define EAFNOSUPPORT 47 /* Address family not supported by protocol family */ +#define EADDRINUSE 48 /* Address already in use */ +#define EADDRNOTAVAIL 49 /* Can't assign requested address */ +#define ENETDOWN 50 /* Network is down */ +#define ENETUNREACH 51 /* Network is unreachable */ +#define ENETRESET 52 /* Network dropped connection on reset */ +#define ECONNABORTED 53 /* Software caused connection abort */ +#define ECONNRESET 54 /* Connection reset by peer */ +#define ENOBUFS 55 /* No buffer space available */ +#define EISCONN 56 /* Socket is already connected */ +#define ENOTCONN 57 /* Socket is not connected */ +#define ESHUTDOWN 58 /* Can't send after socket shutdown */ +#define ETOOMANYREFS 59 /* Too many references: can't splice */ +#define ETIMEDOUT 60 /* Connection timed out */ +#define ECONNREFUSED 61 /* Connection refused */ +#define ELOOP 62 /* Too many levels of symbolic links */ +#define ENAMETOOLONG 63 /* File name too long */ +#define EHOSTDOWN 64 /* Host is down */ +#define EHOSTUNREACH 65 /* No route to host */ +#define ENOTEMPTY 66 /* Directory not empty */ +#define EPROCLIM 67 /* Too many processes */ +#define EUSERS 68 /* Too many users */ +#define EDQUOT 69 /* Disc quota exceeded */ +#define ESTALE 70 /* Stale NFS file handle */ +#define EREMOTE 71 /* Too many levels of remote in path */ +#define EBADRPC 72 /* RPC struct is bad */ +#define ERPCMISMATCH 73 /* RPC version wrong */ +#define EPROGUNAVAIL 74 /* RPC prog. not avail */ +#define EPROGMISMATCH 75 /* Program version wrong */ +#define EPROCUNAVAIL 76 /* Bad procedure for program */ +#define ENOLCK 77 /* No locks available */ +#define ENOSYS 78 /* Function not implemented */ +#define EFTYPE 79 /* Inappropriate file type or format */ + diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/compat/tmpnam.c b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/tmpnam.c new file mode 100644 index 0000000000000000000000000000000000000000..d3922694b8c748d4751d62210e4af9fc1b03414f --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/tmpnam.c @@ -0,0 +1,42 @@ +/* + * Copyright (c) 1988 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that this notice is preserved and that due credit is given + * to the University of California at Berkeley. The name of the University + * may not be used to endorse or promote products derived from this + * software without specific written prior permission. This software + * is provided ``as is'' without express or implied warranty. + * + * RCS: @(#) $Id: tmpnam.c,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ + */ + +#include +#include +#include +#include + +/* + * Use /tmp instead of /usr/tmp, because L_tmpname is only 14 chars + * on some machines (like NeXT machines) and /usr/tmp will cause + * buffer overflows. + */ + +#ifdef P_tmpdir +# undef P_tmpdir +#endif +#define P_tmpdir "/tmp" + +char * +tmpnam(s) + char *s; +{ + static char name[50]; + char *mktemp(); + + if (!s) + s = name; + (void)sprintf(s, "%s/XXXXXX", P_tmpdir); + return(mktemp(s)); +} diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/compat/unistd.h b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/unistd.h new file mode 100644 index 0000000000000000000000000000000000000000..c59a68d1b2b7c6ecaa091c8c5be764f5ba6b4bae --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/unistd.h @@ -0,0 +1,84 @@ +/* + * unistd.h -- + * + * Macros, CONSTants and prototypes for Posix conformance. + * + * Copyright 1989 Regents of the University of California + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies. The University of California + * makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without + * express or implied warranty. + * + * RCS: @(#) $Id: unistd.h,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ + */ + +#ifndef _UNISTD +#define _UNISTD + +#include +#ifndef _TCL +# include "tcl.h" +#endif + +#ifndef NULL +#define NULL 0 +#endif + +/* + * Strict POSIX stuff goes here. Extensions go down below, in the + * ifndef _POSIX_SOURCE section. + */ + +extern void _exit _ANSI_ARGS_((int status)); +extern int access _ANSI_ARGS_((CONST char *path, int mode)); +extern int chdir _ANSI_ARGS_((CONST char *path)); +extern int chown _ANSI_ARGS_((CONST char *path, uid_t owner, gid_t group)); +extern int close _ANSI_ARGS_((int fd)); +extern int dup _ANSI_ARGS_((int oldfd)); +extern int dup2 _ANSI_ARGS_((int oldfd, int newfd)); +extern int execl _ANSI_ARGS_((CONST char *path, ...)); +extern int execle _ANSI_ARGS_((CONST char *path, ...)); +extern int execlp _ANSI_ARGS_((CONST char *file, ...)); +extern int execv _ANSI_ARGS_((CONST char *path, char **argv)); +extern int execve _ANSI_ARGS_((CONST char *path, char **argv, char **envp)); +extern int execvp _ANSI_ARGS_((CONST char *file, char **argv)); +extern pid_t fork _ANSI_ARGS_((void)); +extern char *getcwd _ANSI_ARGS_((char *buf, size_t size)); +extern gid_t getegid _ANSI_ARGS_((void)); +extern uid_t geteuid _ANSI_ARGS_((void)); +extern gid_t getgid _ANSI_ARGS_((void)); +extern int getgroups _ANSI_ARGS_((int bufSize, int *buffer)); +extern pid_t getpid _ANSI_ARGS_((void)); +extern uid_t getuid _ANSI_ARGS_((void)); +extern int isatty _ANSI_ARGS_((int fd)); +extern long lseek _ANSI_ARGS_((int fd, long offset, int whence)); +extern int pipe _ANSI_ARGS_((int *fildes)); +extern int read _ANSI_ARGS_((int fd, char *buf, size_t size)); +extern int setgid _ANSI_ARGS_((gid_t group)); +extern int setuid _ANSI_ARGS_((uid_t user)); +extern unsigned sleep _ANSI_ARGS_ ((unsigned seconds)); +extern char *ttyname _ANSI_ARGS_((int fd)); +extern int unlink _ANSI_ARGS_((CONST char *path)); +extern int write _ANSI_ARGS_((int fd, CONST char *buf, size_t size)); + +#ifndef _POSIX_SOURCE +extern char *crypt _ANSI_ARGS_((CONST char *, CONST char *)); +extern int fchown _ANSI_ARGS_((int fd, uid_t owner, gid_t group)); +extern int flock _ANSI_ARGS_((int fd, int operation)); +extern int ftruncate _ANSI_ARGS_((int fd, unsigned long length)); +extern int ioctl _ANSI_ARGS_((int fd, int request, ...)); +extern int readlink _ANSI_ARGS_((CONST char *path, char *buf, int bufsize)); +extern int setegid _ANSI_ARGS_((gid_t group)); +extern int seteuid _ANSI_ARGS_((uid_t user)); +extern int setreuid _ANSI_ARGS_((int ruid, int euid)); +extern int symlink _ANSI_ARGS_((CONST char *, CONST char *)); +extern int ttyslot _ANSI_ARGS_((void)); +extern int truncate _ANSI_ARGS_((CONST char *path, unsigned long length)); +extern int vfork _ANSI_ARGS_((void)); +#endif /* _POSIX_SOURCE */ + +#endif /* _UNISTD */ + diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/compat/waitpid.c b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/waitpid.c new file mode 100644 index 0000000000000000000000000000000000000000..74852a51dde54ece4bcd46268d5c66954c48d05a --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/compat/waitpid.c @@ -0,0 +1,174 @@ +/* + * waitpid.c -- + * + * This procedure emulates the POSIX waitpid kernel call on + * BSD systems that don't have waitpid but do have wait3. + * This code is based on a prototype version written by + * Mark Diekhans and Karl Lehenbauer. + * + * Copyright (c) 1993 The Regents of the University of California. + * Copyright (c) 1994 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: waitpid.c,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ + */ + +#include "tclInt.h" +#include "tclPort.h" + +#ifndef pid_t +#define pid_t int +#endif + +/* + * A linked list of the following structures is used to keep track + * of processes for which we received notification from the kernel, + * but the application hasn't waited for them yet (this can happen + * because wait may not return the process we really want). We + * save the information here until the application finally does + * wait for the process. + */ + +typedef struct WaitInfo { + pid_t pid; /* Pid of process that exited. */ + WAIT_STATUS_TYPE status; /* Status returned when child exited + * or suspended. */ + struct WaitInfo *nextPtr; /* Next in list of exited processes. */ +} WaitInfo; + +static WaitInfo *deadList = NULL; /* First in list of all dead + * processes. */ + +/* + *---------------------------------------------------------------------- + * + * waitpid -- + * + * This procedure emulates the functionality of the POSIX + * waitpid kernel call, using the BSD wait3 kernel call. + * Note: it doesn't emulate absolutely all of the waitpid + * functionality, in that it doesn't support pid's of 0 + * or < -1. + * + * Results: + * -1 is returned if there is an error in the wait kernel call. + * Otherwise the pid of an exited or suspended process is + * returned and *statusPtr is set to the status value of the + * process. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +#ifdef waitpid +# undef waitpid +#endif + +pid_t +waitpid(pid, statusPtr, options) + pid_t pid; /* The pid to wait on. Must be -1 or + * greater than zero. */ + int *statusPtr; /* Where to store wait status for the + * process. */ + int options; /* OR'ed combination of WNOHANG and + * WUNTRACED. */ +{ + register WaitInfo *waitPtr, *prevPtr; + pid_t result; + WAIT_STATUS_TYPE status; + + if ((pid < -1) || (pid == 0)) { + errno = EINVAL; + return -1; + } + + /* + * See if there's a suitable process that has already stopped or + * exited. If so, remove it from the list of exited processes and + * return its information. + */ + + for (waitPtr = deadList, prevPtr = NULL; waitPtr != NULL; + prevPtr = waitPtr, waitPtr = waitPtr->nextPtr) { + if ((pid != waitPtr->pid) && (pid != -1)) { + continue; + } + if (!(options & WUNTRACED) && (WIFSTOPPED(waitPtr->status))) { + continue; + } + result = waitPtr->pid; + *statusPtr = *((int *) &waitPtr->status); + if (prevPtr == NULL) { + deadList = waitPtr->nextPtr; + } else { + prevPtr->nextPtr = waitPtr->nextPtr; + } + ckfree((char *) waitPtr); + return result; + } + + /* + * Wait for any process to stop or exit. If it's an acceptable one + * then return it to the caller; otherwise store information about it + * in the list of exited processes and try again. On systems that + * have only wait but not wait3, there are several situations we can't + * handle, but we do the best we can (e.g. can still handle some + * combinations of options by invoking wait instead of wait3). + */ + + while (1) { +#if NO_WAIT3 + if (options & WNOHANG) { + return 0; + } + if (options != 0) { + errno = EINVAL; + return -1; + } + result = wait(&status); +#else + result = wait3(&status, options, 0); +#endif + if ((result == -1) && (errno == EINTR)) { + continue; + } + if (result <= 0) { + return result; + } + + if ((pid != result) && (pid != -1)) { + goto saveInfo; + } + if (!(options & WUNTRACED) && (WIFSTOPPED(status))) { + goto saveInfo; + } + *statusPtr = *((int *) &status); + return result; + + /* + * Can't return this info to caller. Save it in the list of + * stopped or exited processes. Tricky point: first check for + * an existing entry for the process and overwrite it if it + * exists (e.g. a previously stopped process might now be dead). + */ + + saveInfo: + for (waitPtr = deadList; waitPtr != NULL; waitPtr = waitPtr->nextPtr) { + if (waitPtr->pid == result) { + waitPtr->status = status; + goto waitAgain; + } + } + waitPtr = (WaitInfo *) ckalloc(sizeof(WaitInfo)); + waitPtr->pid = result; + waitPtr->status = status; + waitPtr->nextPtr = deadList; + deadList = waitPtr; + + waitAgain: continue; + } +} diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Access.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Access.3 new file mode 100644 index 0000000000000000000000000000000000000000..b326959d16b8603b69876a861b60e2c7d848058b --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Access.3 @@ -0,0 +1,71 @@ +'\" +'\" Copyright (c) 1998-1999 Scriptics Corportation +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: Access.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_Access 3 8.1 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_Access, Tcl_Stat \- check file permissions and other attributes +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +int +\fBTcl_Access\fR(\fIpath\fR, \fImode\fR) +.sp +int +\fBTcl_Stat\fR(\fIpath\fR, \fIstatPtr\fR) +.SH ARGUMENTS +.AS stat *statPtr in +.AP char *path in +Native name of the file to check the attributes of. +.AP int mode in +Mask consisting of one or more of R_OK, W_OK, X_OK and F_OK. R_OK, +W_OK and X_OK request checking whether the file exists and has read, +write and execute permissions, respectively. F_OK just requests +checking for the existence of the file. +.AP stat *statPtr out +The structure that contains the result. +.BE + +.SH DESCRIPTION +.PP +There are two reasons for calling \fBTcl_Access\fR and \fBTcl_Stat\fR +rather than calling system level functions \fBaccess\fR and \fBstat\fR +directly. First, the Windows implementation of both functions fixes +some bugs in the system level calls. Second, both \fBTcl_Access\fR +and \fBTcl_Stat\fR (as well as \fBTcl_OpenFileChannelProc\fR) hook +into a linked list of functions. This allows the possibity to reroute +file access to alternative media or access methods. +.PP +\fBTcl_Access\fR checks whether the process would be allowed to read, +write or test for existence of the file (or other file system object) +whose name is pathname. If pathname is a symbolic link on Unix, +then permissions of the file referred by this symbolic link are +tested. +.PP +On success (all requested permissions granted), zero is returned. On +error (at least one bit in mode asked for a permission that is denied, +or some other error occurred), -1 is returned. +.PP +\fBTcl_Stat\fR fills the stat structure \fIstatPtr\fR with information +about the specified file. You do not need any access rights to the +file to get this information but you need search rights to all +directories named in the path leading to the file. The stat structure +includes info regarding device, inode (always 0 on Windows), +priviledge mode, nlink (always 1 on Windows), user id (always 0 on +Windows), group id (always 0 on Windows), rdev (same as device on +Windows), size, last access time, last modification time, and creation +time. +.PP +If \fIpath\fR exists, \fBTcl_Stat\fR returns 0 and the stat structure +is filled with data. Otherwise, -1 is returned, and no stat info is +given. + +.SH KEYWORDS +stat access diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/AddErrInfo.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/AddErrInfo.3 new file mode 100644 index 0000000000000000000000000000000000000000..e4c30c7107909c895f08099de1ec9786932aecf0 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/AddErrInfo.3 @@ -0,0 +1,191 @@ +'\" +'\" Copyright (c) 1989-1993 The Regents of the University of California. +'\" Copyright (c) 1994-1997 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: AddErrInfo.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_AddErrorInfo 3 8.0 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_AddObjErrorInfo, Tcl_AddErrorInfo, Tcl_SetObjErrorCode, Tcl_SetErrorCode, Tcl_SetErrorCodeVA, Tcl_PosixError, Tcl_LogCommandInfo \- record information about errors +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +\fBTcl_AddObjErrorInfo\fR(\fIinterp, message, length\fR) +.sp +\fBTcl_AddErrorInfo\fR(\fIinterp, message\fR) +.sp +\fBTcl_SetObjErrorCode\fR(\fIinterp, errorObjPtr\fR) +.sp +\fBTcl_SetErrorCode\fR(\fIinterp, element, element, ... \fB(char *) NULL\fR) +.sp +\fBTcl_SetErrorCodeVA\fR(\fIinterp, argList\fR) +.sp +char * +\fBTcl_PosixError\fR(\fIinterp\fR) +.sp +void +\fBTcl_LogCommandInfo\fR(\fIinterp, script, command, commandLength\fR) +.SH ARGUMENTS +.AS Tcl_Interp *message +.AP Tcl_Interp *interp in +Interpreter in which to record information. +.AP char *message in +For \fBTcl_AddObjErrorInfo\fR, +this points to the first byte of an array of bytes +containing a string to record in the \fBerrorInfo\fR variable. +This byte array may contain embedded null bytes +unless \fIlength\fR is negative. +For \fBTcl_AddErrorInfo\fR, +this is a conventional C string to record in the \fBerrorInfo\fR variable. +.AP int length in +The number of bytes to copy from \fImessage\fR when +setting the \fBerrorInfo\fR variable. +If negative, all bytes up to the first null byte are used. +.AP Tcl_Obj *errorObjPtr in +This variable \fBerrorCode\fR will be set to this value. +.AP char *element in +String to record as one element of \fBerrorCode\fR variable. +Last \fIelement\fR argument must be NULL. +.AP va_list argList in +An argument list which must have been initialised using +\fBTCL_VARARGS_START\fR, and cleared using \fBva_end\fR. +.AP char *script in +Pointer to first character in script containing command (must be <= command) +.AP char *command in +Pointer to first character in command that generated the error +.AP int commandLength in +Number of bytes in command; -1 means use all bytes up to first NULL byte +.BE + +.SH DESCRIPTION +.PP +These procedures are used to manipulate two Tcl global variables +that hold information about errors. +The variable \fBerrorInfo\fR holds a stack trace of the +operations that were in progress when an error occurred, +and is intended to be human-readable. +The variable \fBerrorCode\fR holds a list of items that +are intended to be machine-readable. +The first item in \fBerrorCode\fR identifies the class of +error that occurred +(e.g. POSIX means an error occurred in a POSIX system call) +and additional elements in \fBerrorCode\fR hold additional pieces +of information that depend on the class. +See the Tcl overview manual entry for details on the various +formats for \fBerrorCode\fR. +.PP +The \fBerrorInfo\fR variable is gradually built up as an +error unwinds through the nested operations. +Each time an error code is returned to \fBTcl_EvalObjEx\fR +(or \fBTcl_Eval\fR, which calls \fBTcl_EvalObjEx\fR) +it calls the procedure \fBTcl_AddObjErrorInfo\fR to add +additional text to \fBerrorInfo\fR describing the +command that was being executed when the error occurred. +By the time the error has been passed all the way back +to the application, it will contain a complete trace +of the activity in progress when the error occurred. +.PP +It is sometimes useful to add additional information to +\fBerrorInfo\fR beyond what can be supplied automatically +by \fBTcl_EvalObjEx\fR. +\fBTcl_AddObjErrorInfo\fR may be used for this purpose: +its \fImessage\fR and \fIlength\fR arguments describe an additional +string to be appended to \fBerrorInfo\fR. +For example, the \fBsource\fR command calls \fBTcl_AddObjErrorInfo\fR +to record the name of the file being processed and the +line number on which the error occurred; +for Tcl procedures, the procedure name and line number +within the procedure are recorded, and so on. +The best time to call \fBTcl_AddObjErrorInfo\fR is just after +\fBTcl_EvalObjEx\fR has returned \fBTCL_ERROR\fR. +In calling \fBTcl_AddObjErrorInfo\fR, you may find it useful to +use the \fBerrorLine\fR field of the interpreter (see the +\fBTcl_Interp\fR manual entry for details). +.PP +\fBTcl_AddErrorInfo\fR resembles \fBTcl_AddObjErrorInfo\fR +but differs in initializing \fBerrorInfo\fR from the string +value of the interpreter's result +if the error is just starting to be logged. +It does not use the result as a Tcl object +so any embedded null characters in the result +will cause information to be lost. +It also takes a conventional C string in \fImessage\fR +instead of \fBTcl_AddObjErrorInfo\fR's counted string. +.PP +The procedure \fBTcl_SetObjErrorCode\fR is used to set the +\fBerrorCode\fR variable. \fIerrorObjPtr\fR contains a list object +built up by the caller. \fBerrorCode\fR is set to this +value. \fBTcl_SetObjErrorCode\fR is typically invoked just +before returning an error in an object command. If an error is +returned without calling \fBTcl_SetObjErrorCode\fR or +\fBTcl_SetErrorCode\fR the Tcl interpreter automatically sets +\fBerrorCode\fR to \fBNONE\fR. +.PP +The procedure \fBTcl_SetErrorCode\fR is also used to set the +\fBerrorCode\fR variable. However, it takes one or more strings to +record instead of an object. Otherwise, it is similar to +\fBTcl_SetObjErrorCode\fR in behavior. +.PP +\fBTcl_SetErrorCodeVA\fR is the same as \fBTcl_SetErrorCode\fR except that +instead of taking a variable number of arguments it takes an argument list. +.PP +\fBTcl_PosixError\fR +sets the \fBerrorCode\fR variable after an error in a POSIX kernel call. +It reads the value of the \fBerrno\fR C variable and calls +\fBTcl_SetErrorCode\fR to set \fBerrorCode\fR in the \fBPOSIX\fR format. +The caller must previously have called \fBTcl_SetErrno\fR to set +\fBerrno\fR; this is necessary on some platforms (e.g. Windows) where Tcl +is linked into an application as a shared library, or when the error +occurs in a dynamically loaded extension. See the manual entry for +\fBTcl_SetErrno\fR for more information. +.PP +\fBTcl_PosixError\fR returns a human-readable diagnostic message +for the error +(this is the same value that will appear as the third element +in \fBerrorCode\fR). +It may be convenient to include this string as part of the +error message returned to the application in +the interpreter's result. +.PP +\fBTcl_LogCommandInfo\fR is invoked after an error occurs in an +interpreter. It adds information about the command that was being +executed when the error occured to the \fBerrorInfo\fR variable, and +the line number stored internally in the interpreter is set. On the +first call to \fBTcl_LogCommandInfo\fR or \fBTcl_AddObjErrorInfo\fR +since an error occurred, the old information in \fBerrorInfo\fR is +deleted. +.PP +It is important to call the procedures described here rather than +setting \fBerrorInfo\fR or \fBerrorCode\fR directly with +\fBTcl_ObjSetVar2\fR. +The reason for this is that the Tcl interpreter keeps information +about whether these procedures have been called. +For example, the first time \fBTcl_AddObjErrorInfo\fR is called +for an error, it clears the existing value of \fBerrorInfo\fR +and adds the error message in the interpreter's result to the variable +before appending \fImessage\fR; +in subsequent calls, it just appends the new \fImessage\fR. +When \fBTcl_SetErrorCode\fR is called, it sets a flag indicating +that \fBerrorCode\fR has been set; +this allows the Tcl interpreter to set \fBerrorCode\fR to \fBNONE\fR +if it receives an error return +when \fBTcl_SetErrorCode\fR hasn't been called. +.PP +If the procedure \fBTcl_ResetResult\fR is called, +it clears all of the state associated with +\fBerrorInfo\fR and \fBerrorCode\fR +(but it doesn't actually modify the variables). +If an error had occurred, this will clear the error state to +make it appear as if no error had occurred after all. + +.SH "SEE ALSO" +Tcl_DecrRefCount, Tcl_IncrRefCount, Tcl_Interp, Tcl_ResetResult, Tcl_SetErrno + +.SH KEYWORDS +error, object, object result, stack, trace, variable diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Alloc.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Alloc.3 new file mode 100644 index 0000000000000000000000000000000000000000..df3636674d9212f38eb9214be316b6b6d3172f47 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Alloc.3 @@ -0,0 +1,52 @@ +'\" +'\" Copyright (c) 1995-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: Alloc.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_Alloc 3 7.5 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_Alloc, Tcl_Free, Tcl_Realloc \- allocate or free heap memory +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +char * +\fBTcl_Alloc\fR(\fIsize\fR) +.sp +\fBTcl_Free\fR(\fIptr\fR) +.sp +char * +\fBTcl_Realloc\fR(\fIptr, size\fR) +.SH ARGUMENTS +.AS char *size +.AP int size in +Size in bytes of the memory block to allocate. +.AP char *ptr in +Pointer to memory block to free or realloc. +.BE + +.SH DESCRIPTION +.PP +These procedures provide a platform and compiler independent interface +for memory allocation. Programs that need to transfer ownership of +memory blocks between Tcl and other modules should use these routines +rather than the native \fBmalloc()\fR and \fBfree()\fR routines +provided by the C run-time library. +.PP +\fBTcl_Alloc\fR returns a pointer to a block of at least \fIsize\fR +bytes suitably aligned for any use. +.PP +\fBTcl_Free\fR makes the space referred to by \fIptr\fR available for +further allocation. +.PP +\fBTcl_Realloc\fR changes the size of the block pointed to by +\fIptr\fR to \fIsize\fR bytes and returns a pointer to the new block. +The contents will be unchanged up to the lesser of the new and old +sizes. The returned location may be different from \fIptr\fR. +.SH KEYWORDS +alloc, allocation, free, malloc, memory, realloc diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/AllowExc.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/AllowExc.3 new file mode 100644 index 0000000000000000000000000000000000000000..a2b55d7c33f71c1eefc0d88c31705051732d083f --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/AllowExc.3 @@ -0,0 +1,42 @@ +'\" +'\" Copyright (c) 1989-1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: AllowExc.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_AllowExceptions 3 7.4 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_AllowExceptions \- allow all exceptions in next script evaluation +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +\fBTcl_AllowExceptions\fR(\fIinterp\fR) +.SH ARGUMENTS +.AS Tcl_Interp *doublePtr +.AP Tcl_Interp *interp in +Interpreter in which script will be evaluated. +.BE + +.SH DESCRIPTION +.PP +If a script is evaluated at top-level (i.e. no other scripts are +pending evaluation when the script is invoked), and if the script +terminates with a completion code other than TCL_OK, TCL_CONTINUE +or TCL_RETURN, then Tcl normally converts this into a TCL_ERROR +return with an appropriate message. +.PP +However, if \fBTcl_AllowExceptions\fR is invoked immediately before +calling a procedure such as \fBTcl_Eval\fR, then arbitrary completion +codes are permitted from the script, and they are returned without +modification. +This is useful in cases where the caller can deal with exceptions +such as TCL_BREAK or TCL_CONTINUE in a meaningful way. + +.SH KEYWORDS +continue, break, exception, interpreter diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/AppInit.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/AppInit.3 new file mode 100644 index 0000000000000000000000000000000000000000..a3c3a5a9613e8626975153aea830230aedf8a721 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/AppInit.3 @@ -0,0 +1,73 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: AppInit.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_AppInit 3 7.0 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_AppInit \- perform application-specific initialization +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +int +\fBTcl_AppInit\fR(\fIinterp\fR) +.SH ARGUMENTS +.AS Tcl_Interp *interp +.AP Tcl_Interp *interp in +Interpreter for the application. +.BE + +.SH DESCRIPTION +.PP +\fBTcl_AppInit\fR is a ``hook'' procedure that is invoked by +the main programs for Tcl applications such as \fBtclsh\fR and \fBwish\fR. +Its purpose is to allow new Tcl applications to be created without +modifying the main programs provided as part of Tcl and Tk. +To create a new application you write a new version of +\fBTcl_AppInit\fR to replace the default version provided by Tcl, +then link your new \fBTcl_AppInit\fR with the Tcl library. +.PP +\fBTcl_AppInit\fR is invoked after by \fBTcl_Main\fR and \fBTk_Main\fR +after their own initialization and before entering the main loop +to process commands. +Here are some examples of things that \fBTcl_AppInit\fR might do: +.IP [1] +Call initialization procedures for various packages used by +the application. +Each initialization procedure adds new commands to \fIinterp\fR +for its package and performs other package-specific initialization. +.IP [2] +Process command-line arguments, which can be accessed from the +Tcl variables \fBargv\fR and \fBargv0\fR in \fIinterp\fR. +.IP [3] +Invoke a startup script to initialize the application. +.LP +\fBTcl_AppInit\fR returns TCL_OK or TCL_ERROR. +If it returns TCL_ERROR then it must leave an error message in +for the interpreter's result; otherwise the result is ignored. +.PP +In addition to \fBTcl_AppInit\fR, your application should also contain +a procedure \fBmain\fR that calls \fBTcl_Main\fR as follows: +.CS +Tcl_Main(argc, argv, Tcl_AppInit); +.CE +The third argument to \fBTcl_Main\fR gives the address of the +application-specific initialization procedure to invoke. +This means that you don't have to use the name \fBTcl_AppInit\fR +for the procedure, but in practice the name is nearly always +\fBTcl_AppInit\fR (in versions before Tcl 7.4 the name \fBTcl_AppInit\fR +was implicit; there was no way to specify the procedure explicitly). +The best way to get started is to make a copy of the file +\fBtclAppInit.c\fR from the Tcl library or source directory. +It already contains a \fBmain\fR procedure and a template for +\fBTcl_AppInit\fR that you can modify for your application. + +.SH KEYWORDS +application, argument, command, initialization, interpreter diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/AssocData.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/AssocData.3 new file mode 100644 index 0000000000000000000000000000000000000000..a98c56e96c7f5fb4200725e0315f8194503a0585 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/AssocData.3 @@ -0,0 +1,89 @@ +'\" +'\" Copyright (c) 1995-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" +'\" RCS: @(#) $Id: AssocData.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +.so man.macros +.TH Tcl_SetAssocData 3 7.5 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_GetAssocData, Tcl_SetAssocData, Tcl_DeleteAssocData \- manage +associations of string keys and user specified data with Tcl +interpreters. +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +ClientData +\fBTcl_GetAssocData\fR(\fIinterp, key, delProcPtr\fR) +.sp +\fBTcl_SetAssocData\fR(\fIinterp, key, delProc, clientData\fR) +.sp +\fBTcl_DeleteAssocData\fR(\fIinterp, key\fR) +.SH ARGUMENTS +.AS Tcl_InterpDeleteProc *delProcPtr +.AP Tcl_Interp *interp in +Interpreter in which to execute the specified command. +.AP char *key in +Key for association with which to store data or from which to delete or +retrieve data. Typically the module prefix for a package. +.AP Tcl_InterpDeleteProc *delProc in +Procedure to call when \fIinterp\fR is deleted. +.AP Tcl_InterpDeleteProc **delProcPtr in +Pointer to location in which to store address of current deletion procedure +for association. Ignored if NULL. +.AP ClientData clientData in +Arbitrary one-word value associated with the given key in this +interpreter. This data is owned by the caller. +.BE + +.SH DESCRIPTION +.PP +These procedures allow extensions to associate their own data with +a Tcl interpreter. +An association consists of a string key, typically the name of +the extension, and a one-word value, which is typically a pointer +to a data structure holding data specific to the extension. +Tcl makes no interpretation of either the key or the value for +an association. +.PP +Storage management is facilitated by storing with each association a +procedure to call when the interpreter is deleted. This +procedure can dispose of the storage occupied by the client's data in any +way it sees fit. +.PP +\fBTcl_SetAssocData\fR creates an association between a string +key and a user specified datum in the given interpreter. +If there is already an association with the given \fIkey\fR, +\fBTcl_SetAssocData\fR overwrites it with the new information. +It is up to callers to organize their use of names to avoid conflicts, +for example, by using package names as the keys. +If the \fIdeleteProc\fR argument is non-NULL it specifies the address of a +procedure to invoke if the interpreter is deleted before the association +is deleted. \fIDeleteProc\fR should have arguments and result that match +the type \fBTcl_InterpDeleteProc\fR: +.CS +typedef void Tcl_InterpDeleteProc( + ClientData \fIclientData\fR, + Tcl_Interp *\fIinterp\fR); +.CE +When \fIdeleteProc\fR is invoked the \fIclientData\fR and \fIinterp\fR +arguments will be the same as the corresponding arguments passed to +\fBTcl_SetAssocData\fR. +The deletion procedure will \fInot\fR be invoked if the association +is deleted before the interpreter is deleted. +.PP +\fBTcl_GetAssocData\fR returns the datum stored in the association with the +specified key in the given interpreter, and if the \fIdelProcPtr\fR field +is non-\fBNULL\fR, the address indicated by it gets the address of the +delete procedure stored with this association. If no association with the +specified key exists in the given interpreter \fBTcl_GetAssocData\fR +returns \fBNULL\fR. +.PP +\fBTcl_DeleteAssocData\fR deletes an association with a specified key in +the given interpreter. Then it calls the deletion procedure. +.SH KEYWORDS +association, data, deletion procedure, interpreter, key diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Async.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Async.3 new file mode 100644 index 0000000000000000000000000000000000000000..ee835ec8d8d3ada892e73fe3d6f004405487d6cf --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Async.3 @@ -0,0 +1,163 @@ +'\" +'\" Copyright (c) 1989-1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: Async.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_AsyncCreate 3 7.0 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_AsyncCreate, Tcl_AsyncMark, Tcl_AsyncInvoke, Tcl_AsyncDelete, Tcl_AsyncReady \- handle asynchronous events +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +Tcl_AsyncHandler +\fBTcl_AsyncCreate\fR(\fIproc, clientData\fR) +.sp +\fBTcl_AsyncMark\fR(\fIasync\fR) +.sp +int +\fBTcl_AsyncInvoke\fR(\fIinterp, code\fR) +.sp +\fBTcl_AsyncDelete\fR(\fIasync\fR) +.sp +int +\fBTcl_AsyncReady\fR() +.SH ARGUMENTS +.AS Tcl_AsyncHandler clientData +.AP Tcl_AsyncProc *proc in +Procedure to invoke to handle an asynchronous event. +.AP ClientData clientData in +One-word value to pass to \fIproc\fR. +.AP Tcl_AsyncHandler async in +Token for asynchronous event handler. +.AP Tcl_Interp *interp in +Tcl interpreter in which command was being evaluated when handler was +invoked, or NULL if handler was invoked when there was no interpreter +active. +.AP int code in +Completion code from command that just completed in \fIinterp\fR, +or 0 if \fIinterp\fR is NULL. +.BE + +.SH DESCRIPTION +.PP +These procedures provide a safe mechanism for dealing with +asynchronous events such as signals. +If an event such as a signal occurs while a Tcl script is being +evaluated then it isn't safe to take any substantive action to +process the event. +For example, it isn't safe to evaluate a Tcl script since the +interpreter may already be in the middle of evaluating a script; +it may not even be safe to allocate memory, since a memory +allocation could have been in progress when the event occurred. +The only safe approach is to set a flag indicating that the event +occurred, then handle the event later when the world has returned +to a clean state, such as after the current Tcl command completes. +.PP +\fBTcl_AsyncCreate\fR, \fBTcl_AsyncDelete\fR, and \fBTcl_AsyncReady\fR +are thread sensitive. They access and/or set a thread-specific data +structure in the event of an --enable-thread built core. The token +created by Tcl_AsyncCreate contains the needed thread information it +was called from so that calling Tcl_AsyncMark(token) will only yield +the origin thread into the AsyncProc. +.PP +\fBTcl_AsyncCreate\fR creates an asynchronous handler and returns +a token for it. +The asynchronous handler must be created before +any occurrences of the asynchronous event that it is intended +to handle (it is not safe to create a handler at the time of +an event). +When an asynchronous event occurs the code that detects the event +(such as a signal handler) should call \fBTcl_AsyncMark\fR with the +token for the handler. +\fBTcl_AsyncMark\fR will mark the handler as ready to execute, but it +will not invoke the handler immediately. +Tcl will call the \fIproc\fR associated with the handler later, when +the world is in a safe state, and \fIproc\fR can then carry out +the actions associated with the asynchronous event. +\fIProc\fR should have arguments and result that match the +type \fBTcl_AsyncProc\fR: +.CS +typedef int Tcl_AsyncProc( + ClientData \fIclientData\fR, + Tcl_Interp *\fIinterp\fR, + int \fIcode\fR); +.CE +The \fIclientData\fR will be the same as the \fIclientData\fR +argument passed to \fBTcl_AsyncCreate\fR when the handler was +created. +If \fIproc\fR is invoked just after a command has completed +execution in an interpreter, then \fIinterp\fR will identify +the interpreter in which the command was evaluated and +\fIcode\fR will be the completion code returned by that +command. +The command's result will be present in the interpreter's result. +When \fIproc\fR returns, whatever it leaves in the interpreter's result +will be returned as the result of the command and the integer +value returned by \fIproc\fR will be used as the new completion +code for the command. +.PP +It is also possible for \fIproc\fR to be invoked when no interpreter +is active. +This can happen, for example, if an asynchronous event occurs while +the application is waiting for interactive input or an X event. +In this case \fIinterp\fR will be NULL and \fIcode\fR will be +0, and the return value from \fIproc\fR will be ignored. +.PP +The procedure \fBTcl_AsyncInvoke\fR is called to invoke all of the +handlers that are ready. +The procedure \fBTcl_AsyncReady\fR will return non-zero whenever any +asynchronous handlers are ready; it can be checked to avoid calls +to \fBTcl_AsyncInvoke\fR when there are no ready handlers. +Tcl calls \fBTcl_AsyncReady\fR after each command is evaluated +and calls \fBTcl_AsyncInvoke\fR if needed. +Applications may also call \fBTcl_AsyncInvoke\fR at interesting +times for that application. +For example, Tcl's event handler calls \fBTcl_AsyncReady\fR +after each event and calls \fBTcl_AsyncInvoke\fR if needed. +The \fIinterp\fR and \fIcode\fR arguments to \fBTcl_AsyncInvoke\fR +have the same meaning as for \fIproc\fR: they identify the active +interpreter, if any, and the completion code from the command +that just completed. +.PP +\fBTcl_AsyncDelete\fR removes an asynchronous handler so that +its \fIproc\fR will never be invoked again. +A handler can be deleted even when ready, and it will still +not be invoked. +.PP +If multiple handlers become active at the same time, the +handlers are invoked in the order they were created (oldest +handler first). +The \fIcode\fR and the interpreter's result for later handlers +reflect the values returned by earlier handlers, so that +the most recently created handler has last say about +the interpreter's result and completion code. +If new handlers become ready while handlers are executing, +\fBTcl_AsyncInvoke\fR will invoke them all; at each point it +invokes the highest-priority (oldest) ready handler, repeating +this over and over until there are no longer any ready handlers. + +.SH WARNING +.PP +It is almost always a bad idea for an asynchronous event +handler to modify the interpreter's result or return a code different +from its \fIcode\fR argument. +This sort of behavior can disrupt the execution of scripts in +subtle ways and result in bugs that are extremely difficult +to track down. +If an asynchronous event handler needs to evaluate Tcl scripts +then it should first save the interpreter's result plus the values +of the variables \fBerrorInfo\fR and \fBerrorCode\fR (this can +be done, for example, by storing them in dynamic strings). +When the asynchronous handler is finished it should restore +the interpreter's result, \fBerrorInfo\fR, and \fBerrorCode\fR, +and return the \fIcode\fR argument. + +.SH KEYWORDS +asynchronous event, handler, signal diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/BackgdErr.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/BackgdErr.3 new file mode 100644 index 0000000000000000000000000000000000000000..d80d6ee51e1c9bf2f03d9a6aae1d081aaf8a0933 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/BackgdErr.3 @@ -0,0 +1,58 @@ +'\" +'\" Copyright (c) 1992-1994 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: BackgdErr.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_BackgroundError 3 7.5 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_BackgroundError \- report Tcl error that occurred in background processing +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +\fBTcl_BackgroundError\fR(\fIinterp\fR) +.SH ARGUMENTS +.AS Tcl_Interp *interp +.AP Tcl_Interp *interp in +Interpreter in which the error occurred. +.BE + +.SH DESCRIPTION +.PP +This procedure is typically invoked when a Tcl error occurs during +``background processing'' such as executing an event handler. +When such an error occurs, the error condition is reported to Tcl +or to a widget or some other C code, and there is not usually any +obvious way for that code to report the error to the user. +In these cases the code calls \fBTcl_BackgroundError\fR with an +\fIinterp\fR argument identifying the interpreter in which the +error occurred. At the time \fBTcl_BackgroundError\fR is invoked, +the interpreter's result is expected to contain an error message. +\fBTcl_BackgroundError\fR will invoke the \fBbgerror\fR +Tcl command to report the error in an application-specific fashion. +If no \fBbgerror\fR command exists, or if it returns with an error condition, +then \fBTcl_BackgroundError\fR reports the error itself by printing +a message on the standard error file. +.PP +\fBTcl_BackgroundError\fR does not invoke \fBbgerror\fR immediately +because this could potentially interfere with scripts that are in process +at the time the error occurred. +Instead, it invokes \fBbgerror\fR later as an idle callback. +\fBTcl_BackgroundError\fR saves the values of the \fBerrorInfo\fR and +\fBerrorCode\fR variables and restores these values just before +invoking \fBbgerror\fR. +.PP +It is possible for many background errors to accumulate before +\fBbgerror\fR is invoked. When this happens, each of the errors +is processed in order. However, if \fBbgerror\fR returns a +break exception, then all remaining error reports for the +interpreter are skipped. + +.SH KEYWORDS +background, bgerror, error diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Backslash.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Backslash.3 new file mode 100644 index 0000000000000000000000000000000000000000..48128abf63e39e17cafec4002b03438777e567e4 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Backslash.3 @@ -0,0 +1,53 @@ +'\" +'\" Copyright (c) 1989-1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: Backslash.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_Backslash 3 "8.1" Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_Backslash \- parse a backslash sequence +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +char +\fBTcl_Backslash\fR(\fIsrc, countPtr\fR) +.SH ARGUMENTS +.AS char *countPtr +.AP char *src in +Pointer to a string starting with a backslash. +.AP int *countPtr out +If \fIcountPtr\fR isn't NULL, \fI*countPtr\fR gets filled +in with number of characters in the backslash sequence, including +the backslash character. +.BE + +.SH DESCRIPTION +.PP +.VS 8.1 +The use of \fBTcl_Backslash\fR is deprecated in favor of +\fBTcl_UtfBackslash\fR. +.PP +This is a utility procedure provided for backwards compatibilty with +non-internationalized Tcl extensions. It parses a backslash sequence and +returns the low byte of the Unicode character corresponding to the sequence. +.VE +\fBTcl_Backslash\fR modifies \fI*countPtr\fR to contain the number of +characters in the backslash sequence. +.PP +See the Tcl manual entry for information on the valid backslash sequences. +All of the sequences described in the Tcl manual entry are supported by +\fBTcl_Backslash\fR. +.VS 8.1 br +.SH "SEE ALSO" +Tcl(n), Tcl_UtfBackslash(3) +.VE + +.SH KEYWORDS +backslash, parse diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/BoolObj.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/BoolObj.3 new file mode 100644 index 0000000000000000000000000000000000000000..b8524aab65ee7ceb4af284f01b7d7ae607e7c7b2 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/BoolObj.3 @@ -0,0 +1,83 @@ +'\" +'\" Copyright (c) 1996-1997 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: BoolObj.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_BooleanObj 3 8.0 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_NewBooleanObj, Tcl_SetBooleanObj, Tcl_GetBooleanFromObj \- manipulate Tcl objects as boolean values +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +Tcl_Obj * +\fBTcl_NewBooleanObj\fR(\fIboolValue\fR) +.sp +\fBTcl_SetBooleanObj\fR(\fIobjPtr, boolValue\fR) +.sp +int +\fBTcl_GetBooleanFromObj\fR(\fIinterp, objPtr, boolPtr\fR) +.SH ARGUMENTS +.AS Tcl_Interp *interp +.AP int boolValue in +Integer value used to initialize or set a boolean object. +If the integer is nonzero, the boolean object is set to 1; +otherwise the boolean object is set to 0. +.AP Tcl_Obj *objPtr in/out +For \fBTcl_SetBooleanObj\fR, this points to the object to be converted +to boolean type. +For \fBTcl_GetBooleanFromObj\fR, this refers to the object +from which to get a boolean value; +if \fIobjPtr\fR does not already point to a boolean object, +an attempt will be made to convert it to one. +.AP Tcl_Interp *interp in/out +If an error occurs during conversion, +an error message is left in the interpreter's result object +unless \fIinterp\fR is NULL. +.AP int *boolPtr out +Points to place where \fBTcl_GetBooleanFromObj\fR +stores the boolean value (0 or 1) obtained from \fIobjPtr\fR. +.BE + +.SH DESCRIPTION +.PP +These procedures are used to create, modify, and read +boolean Tcl objects from C code. +\fBTcl_NewBooleanObj\fR and \fBTcl_SetBooleanObj\fR +will create a new object of boolean type +or modify an existing object to have boolean type. +Both of these procedures set the object to have the +boolean value (0 or 1) specified by \fIboolValue\fR; +if \fIboolValue\fR is nonzero, the object is set to 1, +otherwise to 0. +\fBTcl_NewBooleanObj\fR returns a pointer to a newly created object +with reference count zero. +Both procedures set the object's type to be boolean +and assign the boolean value to the object's internal representation +\fIlongValue\fR member. +\fBTcl_SetBooleanObj\fR invalidates any old string representation +and, if the object is not already a boolean object, +frees any old internal representation. +.PP +\fBTcl_GetBooleanFromObj\fR attempts to return a boolean value +from the Tcl object \fIobjPtr\fR. +If the object is not already a boolean object, +it will attempt to convert it to one. +If an error occurs during conversion, it returns \fBTCL_ERROR\fR +and leaves an error message in the interpreter's result object +unless \fIinterp\fR is NULL. +Otherwise, \fBTcl_GetBooleanFromObj\fR returns \fBTCL_OK\fR +and stores the boolean value in the address given by \fIboolPtr\fR. +If the object is not already a boolean object, +the conversion will free any old internal representation. + +.SH "SEE ALSO" +Tcl_NewObj, Tcl_DecrRefCount, Tcl_IncrRefCount, Tcl_GetObjResult + +.SH KEYWORDS +boolean, boolean object, boolean type, internal representation, object, object type, string representation diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/ByteArrObj.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/ByteArrObj.3 new file mode 100644 index 0000000000000000000000000000000000000000..5a366adcac42a18b670889f78faab6aa9c670d3f --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/ByteArrObj.3 @@ -0,0 +1,91 @@ +'\" +'\" Copyright (c) 1997 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: ByteArrObj.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_ByteArrayObj 3 8.1 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_NewByteArrayObj, Tcl_SetByteArrayObj, Tcl_GetByteArrayFromObj, Tcl_SetByteArrayLength \- manipulate Tcl objects as a arrays of bytes +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +Tcl_Obj * +\fBTcl_NewByteArrayObj\fR(\fIbytes, length\fR) +.sp +void +\fBTcl_SetByteArrayObj\fR(\fIobjPtr, bytes, length\fR) +.sp +unsigned char * +\fBTcl_GetByteArrayFromObj\fR(\fIobjPtr, lengthPtr\fR) +.sp +unsigned char * +\fBTcl_SetByteArrayLength\fR(\fIobjPtr, length\fR) +.SH ARGUMENTS +.AS "unsigned char" *lengthPtr in/out +.AP "unsigned char" *bytes in +The array of bytes used to initialize or set a byte-array object. +.AP int length in +The length of the array of bytes. It must be >= 0. +.AP Tcl_Obj *objPtr in/out +For \fBTcl_SetByteArrayObj\fR, this points to the object to be converted to +byte-array type. For \fBTcl_GetByteArrayFromObj\fR and +\fBTcl_SetByteArrayLength\fR, this points to the object from which to get +the byte-array value; if \fIobjPtr\fR does not already point to a byte-array +object, it will be converted to one. +.AP int *lengthPtr out +If non-NULL, filled with the length of the array of bytes in the object. +.BE + +.SH DESCRIPTION +.PP +These procedures are used to create, modify, and read Tcl byte-array objects +from C code. Byte-array objects are typically used to hold the +results of binary IO operations or data structures created with the +\fBbinary\fR command. In Tcl, an array of bytes is not equivalent to a +string. Conceptually, a string is an array of Unicode characters, while a +byte-array is an array of 8-bit quantities with no implicit meaning. +Accesser functions are provided to get the string representation of a +byte-array or to convert an arbitrary object to a byte-array. Obtaining the +string representation of a byte-array object (by calling +\fBTcl_GetStringFromObj\fR) produces a properly formed UTF-8 sequence with a +one-to-one mapping between the bytes in the internal representation and the +UTF-8 characters in the string representation. +.PP +\fBTcl_NewByteArrayObj\fR and \fBTcl_SetByteArrayObj\fR will +create a new object of byte-array type or modify an existing object to have a +byte-array type. Both of these procedures set the object's type to be +byte-array and set the object's internal representation to a copy of the +array of bytes given by \fIbytes\fR. \fBTcl_NewByteArrayObj\fR returns a +pointer to a newly allocated object with a reference count of zero. +\fBTcl_SetByteArrayObj\fR invalidates any old string representation and, if +the object is not already a byte-array object, frees any old internal +representation. +.PP +\fBTcl_GetByteArrayFromObj\fR converts a Tcl object to byte-array type and +returns a pointer to the object's new internal representation as an array of +bytes. The length of this array is stored in \fIlengthPtr\fR if +\fIlengthPtr\fR is non-NULL. The storage for the array of bytes is owned by +the object and should not be freed. The contents of the array may be +modified by the caller only if the object is not shared and the caller +invalidates the string representation. +.PP +\fBTcl_SetByteArrayLength\fR converts the Tcl object to byte-array type +and changes the length of the object's internal representation as an +array of bytes. If \fIlength\fR is greater than the space currently +allocated for the array, the array is reallocated to the new length; the +newly allocated bytes at the end of the array have arbitrary values. If +\fIlength\fR is less than the space currently allocated for the array, +the length of array is reduced to the new length. The return value is a +pointer to the object's new array of bytes. + +.SH "SEE ALSO" +Tcl_GetStringFromObj, Tcl_NewObj, Tcl_IncrRefCount, Tcl_DecrRefCount + +.SH KEYWORDS +object, byte array, utf, unicode, internationalization diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CVS/Entries b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CVS/Entries new file mode 100644 index 0000000000000000000000000000000000000000..5226806ecff82e544fc1acdea41645f6a55c3a42 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CVS/Entries @@ -0,0 +1,184 @@ +/Access.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/AddErrInfo.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/Alloc.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/AllowExc.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/AppInit.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/AssocData.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/Async.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/BackgdErr.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/Backslash.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/BoolObj.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/ByteArrObj.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/CallDel.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/ChnlStack.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/CmdCmplt.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/Concat.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/CrtChannel.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/CrtChnlHdlr.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/CrtCloseHdlr.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/CrtCommand.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/CrtFileHdlr.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/CrtInterp.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/CrtMathFnc.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/CrtObjCmd.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/CrtSlave.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/CrtTimerHdlr.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/CrtTrace.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/DString.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/DetachPids.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/DoOneEvent.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/DoWhenIdle.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/DoubleObj.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/DumpActiveMemory.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/Encoding.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/Eval.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/Exit.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/ExprLong.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/ExprLongObj.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/FindExec.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/GetCwd.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/GetHostName.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/GetIndex.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/GetInt.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/GetOpnFl.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/GetStdChan.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/GetVersion.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/Hash.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/Init.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/InitStubs.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/IntObj.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/Interp.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/LinkVar.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/ListObj.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/Notifier.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/Object.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/ObjectType.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/OpenFileChnl.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/OpenTcp.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/ParseCmd.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/PkgRequire.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/Preserve.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/PrintDbl.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/RecEvalObj.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/RecordEval.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/RegExp.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/SaveResult.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/SetErrno.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/SetRecLmt.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/SetResult.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/SetVar.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/Sleep.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/SourceRCFile.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/SplitList.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/SplitPath.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/StaticPkg.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/StrMatch.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/StringObj.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/TCL_MEM_DEBUG.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/Tcl.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/Tcl_Main.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/Thread.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/ToUpper.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/TraceVar.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/Translate.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/UpVar.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/Utf.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/WrongNumArgs.3/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/after.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/append.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/array.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/bgerror.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/binary.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/break.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/case.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/catch.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/cd.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/clock.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/close.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/concat.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/continue.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/dde.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/encoding.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/eof.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/error.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/eval.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/exec.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/exit.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/expr.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/fblocked.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/fconfigure.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/fcopy.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/file.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/fileevent.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/filename.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/flush.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/for.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/foreach.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/format.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/gets.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/glob.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/global.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/history.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/http.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/if.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/incr.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/info.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/interp.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/join.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/lappend.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/library.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/license.terms/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/lindex.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/linsert.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/list.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/llength.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/load.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/lrange.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/lreplace.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/lsearch.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/lsort.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/man.macros/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/memory.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/msgcat.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/namespace.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/open.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/package.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/packagens.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/pid.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/pkgMkIndex.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/proc.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/puts.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/pwd.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/re_syntax.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/read.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/regexp.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/registry.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/regsub.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/rename.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/resource.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/return.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/safe.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/scan.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/seek.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/set.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/socket.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/source.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/split.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/string.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/subst.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/switch.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/tclsh.1/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/tcltest.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/tclvars.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/tell.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/time.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/trace.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/unknown.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/unset.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/update.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/uplevel.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/upvar.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/variable.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/vwait.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +/while.n/1.1.1.1/Wed Oct 29 20:29:11 2003//Tmk4_mod6_rc2 +D diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CVS/Repository b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CVS/Repository new file mode 100644 index 0000000000000000000000000000000000000000..c4c67d702076191990d81f9ea8d8f21db314df6e --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CVS/Repository @@ -0,0 +1 @@ +/san01/cvs/ashpool/csrc/modtcl/tcl8.3.4/doc diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CVS/Root b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CVS/Root new file mode 100644 index 0000000000000000000000000000000000000000..8f34465cf151aad19d76338c0c55fd294f700914 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CVS/Root @@ -0,0 +1 @@ +/san01/cvs/ashpool diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CVS/Tag b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CVS/Tag new file mode 100644 index 0000000000000000000000000000000000000000..5a4cb4556b17e03a003bb14693afc211950469e9 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CVS/Tag @@ -0,0 +1 @@ +Nmk4_mod6_rc2 diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CallDel.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CallDel.3 new file mode 100644 index 0000000000000000000000000000000000000000..ce93ef762874f39db7951d38e7799f956e74b509 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CallDel.3 @@ -0,0 +1,63 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: CallDel.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_CallWhenDeleted 3 7.0 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_CallWhenDeleted, Tcl_DontCallWhenDeleted \- Arrange for callback when interpreter is deleted +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +\fBTcl_CallWhenDeleted\fR(\fIinterp\fR, \fIproc\fR, \fIclientData\fR) +.sp +\fBTcl_DontCallWhenDeleted\fR(\fIinterp\fR, \fIproc\fR, \fIclientData\fR) +.SH ARGUMENTS +.AS Tcl_InterpDeleteProc clientData +.AP Tcl_Interp *interp in +Interpreter with which to associated callback. +.AP Tcl_InterpDeleteProc *proc in +Procedure to call when \fIinterp\fR is deleted. +.AP ClientData clientData in +Arbitrary one-word value to pass to \fIproc\fR. +.BE + +.SH DESCRIPTION +.PP +\fBTcl_CallWhenDeleted\fR arranges for \fIproc\fR to be called by +\fBTcl_DeleteInterp\fR if/when \fIinterp\fR is deleted at some future +time. \fIProc\fR will be invoked just before the interpreter +is deleted, but the interpreter will still be valid at the +time of the call. +\fIProc\fR should have arguments and result that match the +type \fBTcl_InterpDeleteProc\fR: +.CS +typedef void Tcl_InterpDeleteProc( + ClientData \fIclientData\fR, + Tcl_Interp *\fIinterp\fR); +.CE +The \fIclientData\fR and \fIinterp\fR parameters are +copies of the \fIclientData\fR and \fIinterp\fR arguments given +to \fBTcl_CallWhenDeleted\fR. +Typically, \fIclientData\fR points to an application-specific +data structure that \fIproc\fR uses to perform cleanup when an +interpreter is about to go away. +\fIProc\fR does not return a value. +.PP +\fBTcl_DontCallWhenDeleted\fR cancels a previous call to +\fBTcl_CallWhenDeleted\fR with the same arguments, so that +\fIproc\fR won't be called after all when \fIinterp\fR is +deleted. +If there is no deletion callback that matches \fIinterp\fR, +\fIproc\fR, and \fIclientData\fR then the call to +\fBTcl_DontCallWhenDeleted\fR has no effect. + +.SH KEYWORDS +callback, delete, interpreter diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/ChnlStack.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/ChnlStack.3 new file mode 100644 index 0000000000000000000000000000000000000000..5c82dd2c0b4cd2c0fd8ed2c75e22278bcba16ff9 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/ChnlStack.3 @@ -0,0 +1,90 @@ +'\" +'\" Copyright (c) 1999-2000 Ajuba Solutions. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: ChnlStack.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +.so man.macros +.TH Tcl_StackChannel 3 8.3 Tcl "Tcl Library Procedures" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +Tcl_StackChannel, Tcl_UnstackChannel, Tcl_GetStackedChannel \- stack an I/O channel on top of another, and undo it +.SH SYNOPSIS +.nf +.nf +\fB#include \fR +.sp +Tcl_Channel +\fBTcl_StackChannel\fR(\fIinterp, typePtr, clientData, mask, channel\fR) +.sp +int +\fBTcl_UnstackChannel\fR(\fIinterp, channel\fR) +.sp +Tcl_Channel +\fBTcl_GetStackedChannel\fR(\fIchannel\fR) +.sp +.SH ARGUMENTS +.AS Tcl_ChannelType +.AP Tcl_Interp *interp in +Interpreter for error reporting - can be NULL. +.AP Tcl_ChannelType *typePtr in +The new channel I/O procedures to use for \fIchannel\fP. +.AP ClientData clientData in +Arbitrary one-word value to pass to channel I/O procedures. +.AP int mask in +Conditions under which \fIchannel\fR will be used: OR-ed combination of +\fBTCL_READABLE\fR, \fBTCL_WRITABLE\fR and \fBTCL_EXCEPTION\fR. +This can be a subset of the operations currently allowed on \fIchannel\fP. +.AP Tcl_Channel channel in +An existing Tcl channel such as returned by \fBTcl_CreateChannel\fR. +.BE + +.SH DESCRIPTION +.PP +These functions are for use by extensions that add processing layers to Tcl +I/O channels. Examples include compression and encryption modules. These +functions transparently stack and unstack a new channel on top of an +existing one. Any number of channels can be stacked together. +.PP +The implementation of the Tcl channel code was rewritten in 8.3.2 to +correct some problems with the previous implementation with regard to +stacked channels. Anyone using stacked channels or creating stacked +channel drivers should update to the new \fBTCL_CHANNEL_VERSION_2\fR +\fBTcl_ChannelType\fR structure. See \fBTcl_CreateChannel\fR for details. +.PP +\fBTcl_StackChannel\fR stacks a new \fIchannel\fP on an existing channel +with the same name that was registered for \fIchannel\fP by +\fBTcl_RegisterChannel\fP. +.PP +\fBTcl_StackChannel\fR works by creating a new channel structure and +placing itself on top of the channel stack. EOL translation, encoding and +buffering options are shared between all channels in the stack. The hidden +channel does no buffering, newline translations, or character set encoding. +Instead, the buffering, newline translations, and encoding functions all +remain at the top of the channel stack. A pointer to the new top channel +structure is returned. If an error occurs when stacking the channel, NULL +is returned instead. +.PP +The \fImask\fP parameter specifies the operations that are allowed on the +new channel. These can be a subset of the operations allowed on the +original channel. For example, a read-write channel may become read-only +after the \fBTcl_StackChannel\fR call. +.PP +Closing a channel closes the channels stacked below it. The close of +stacked channels is executed in a way that allows buffered data to be +properly flushed. +.PP +\fBTcl_UnstackChannel\fP reverses the process. The old channel is +associated with the channel name, and the processing module added by +\fBTcl_StackChannel\fR is destroyed. If there is no old channel, then +\fBTcl_UnstackChannel\fP is equivalent to \fBTcl_Close\fP. If an error +occurs unstacking the channel, \fBTCL_ERROR\fR is returned, otherwise +\fBTCL_OK\fR is returned. + +.SH "SEE ALSO" +Notifier(3), Tcl_CreateChannel(3), Tcl_OpenFileChannel(3), vwait(n). + +.SH KEYWORDS +channel, compression diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CmdCmplt.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CmdCmplt.3 new file mode 100644 index 0000000000000000000000000000000000000000..948391458935e6a56411010a08da7112b514dca7 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CmdCmplt.3 @@ -0,0 +1,36 @@ +'\" +'\" Copyright (c) 1989-1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: CmdCmplt.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_CommandComplete 3 "" Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_CommandComplete \- Check for unmatched braces in a Tcl command +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +int +\fBTcl_CommandComplete\fR(\fIcmd\fR) +.SH ARGUMENTS +.AS char *cmd +.AP char *cmd in +Command string to test for completeness. +.BE + +.SH DESCRIPTION +.PP +\fBTcl_CommandComplete\fR takes a Tcl command string +as argument and determines whether it contains one or more +complete commands (i.e. there are no unclosed quotes, braces, +brackets, or variable references). +If the command string is complete then it returns 1; otherwise it returns 0. + +.SH KEYWORDS +complete command, partial command diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Concat.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Concat.3 new file mode 100644 index 0000000000000000000000000000000000000000..99a925517a0130ef8525ae6427833fb94cb18a84 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Concat.3 @@ -0,0 +1,55 @@ +'\" +'\" Copyright (c) 1989-1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: Concat.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_Concat 3 7.5 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_Concat \- concatenate a collection of strings +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +char * +\fBTcl_Concat\fR(\fIargc, argv\fR) +.SH ARGUMENTS +.AP int argc in +Number of strings. +.AP char *argv[] in +Array of strings to concatenate. Must have \fIargc\fR entries. +.BE + +.SH DESCRIPTION +.PP +\fBTcl_Concat\fR is a utility procedure used by several of the +Tcl commands. Given a collection of strings, it concatenates +them together into a single string, with the original strings +separated by spaces. This procedure behaves differently than +\fBTcl_Merge\fR, in that the arguments are simply concatenated: +no effort is made to ensure proper list structure. +However, in most common usage the arguments will all be proper +lists themselves; if this is true, then the result will also have +proper list structure. +.PP +\fBTcl_Concat\fR eliminates leading and trailing white space as it +copies strings from \fBargv\fR to the result. If an element of +\fBargv\fR consists of nothing but white space, then that string +is ignored entirely. This white-space removal was added to make +the output of the \fBconcat\fR command cleaner-looking. +.PP +.VS +The result string is dynamically allocated +using \fBTcl_Alloc\fR; the caller must eventually release the space +by calling \fBTcl_Free\fR. +.VE +.VS +.SH "SEE ALSO" +Tcl_ConcatObj +.SH KEYWORDS +concatenate, strings diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CrtChannel.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CrtChannel.3 new file mode 100644 index 0000000000000000000000000000000000000000..a32ecf9c6538b6acad668ba5dee79cbd29336618 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CrtChannel.3 @@ -0,0 +1,760 @@ +'\" +'\" Copyright (c) 1996-1997 Sun Microsystems, Inc. +'\" Copyright (c) 1997-2000 Ajuba Solutions. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: CrtChannel.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +.so man.macros +.TH Tcl_CreateChannel 3 8.3 Tcl "Tcl Library Procedures" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +Tcl_CreateChannel, Tcl_GetChannelInstanceData, Tcl_GetChannelType, Tcl_GetChannelName, Tcl_GetChannelHandle, Tcl_GetChannelMode, Tcl_GetChannelBufferSize, Tcl_SetChannelBufferSize, Tcl_NotifyChannel, Tcl_BadChannelOption, Tcl_ChannelName, Tcl_ChannelVersion, Tcl_ChannelBlockModeProc, Tcl_ChannelCloseProc, Tcl_ChannelClose2Proc, Tcl_ChannelInputProc, Tcl_ChannelOutputProc, Tcl_ChannelSeekProc, Tcl_ChannelSetOptionProc, Tcl_ChannelGetOptionProc, Tcl_ChannelWatchProc, Tcl_ChannelGetHandleProc, Tcl_ChannelFlushProc, Tcl_ChannelHandlerProc, \- procedures for creating and manipulating channels +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +Tcl_Channel +\fBTcl_CreateChannel\fR(\fItypePtr, channelName, instanceData, mask\fR) +.sp +ClientData +\fBTcl_GetChannelInstanceData\fR(\fIchannel\fR) +.sp +Tcl_ChannelType * +\fBTcl_GetChannelType\fR(\fIchannel\fR) +.sp +char * +\fBTcl_GetChannelName\fR(\fIchannel\fR) +.sp +int +\fBTcl_GetChannelHandle\fR(\fIchannel, direction, handlePtr\fR) +.sp +int +\fBTcl_GetChannelBufferSize\fR(\fIchannel\fR) +.sp +\fBTcl_SetChannelBufferSize\fR(\fIchannel, size\fR) +.sp +\fBTcl_NotifyChannel\fR(\fIchannel, mask\fR) +.sp +int +\fBTcl_BadChannelOption\fR(\fIinterp, optionName, optionList\fR) +.VS 8.3.2 +.sp +char * +\fBTcl_ChannelName\fR(\fItypePtr\fR) +.sp +Tcl_ChannelTypeVersion +\fBTcl_ChannelVersion\fR(\fItypePtr\fR) +.sp +Tcl_DriverBlockModeProc * +\fBTcl_ChannelBlockModeProc\fR(\fItypePtr\fR) +.sp +Tcl_DriverCloseProc * +\fBTcl_ChannelCloseProc\fR(\fItypePtr\fR) +.sp +Tcl_DriverClose2Proc * +\fBTcl_ChannelClose2Proc\fR(\fItypePtr\fR) +.sp +Tcl_DriverInputProc * +\fBTcl_ChannelInputProc\fR(\fItypePtr\fR) +.sp +Tcl_DriverOutputProc * +\fBTcl_ChannelOutputProc\fR(\fItypePtr\fR) +.sp +Tcl_DriverSeekProc * +\fBTcl_ChannelSeekProc\fR(\fItypePtr\fR) +.sp +Tcl_DriverSetOptionProc * +\fBTcl_ChannelSetOptionProc\fR(\fItypePtr\fR) +.sp +Tcl_DriverGetOptionProc * +\fBTcl_ChannelGetOptionProc\fR(\fItypePtr\fR) +.sp +Tcl_DriverWatchProc * +\fBTcl_ChannelWatchProc\fR(\fItypePtr\fR) +.sp +Tcl_DriverGetHandleProc * +\fBTcl_ChannelGetHandleProc\fR(\fItypePtr\fR) +.sp +Tcl_DriverFlushProc * +\fBTcl_ChannelFlushProc\fR(\fItypePtr\fR) +.sp +Tcl_DriverHandlerProc * +\fBTcl_ChannelHandlerProc\fR(\fItypePtr\fR) +.VE +.sp +.SH ARGUMENTS +.AS Tcl_EolTranslation *channelName in +.AP Tcl_ChannelType *typePtr in +Points to a structure containing the addresses of procedures that +can be called to perform I/O and other functions on the channel. +.AP char *channelName in +The name of this channel, such as \fBfile3\fR; must not be in use +by any other channel. Can be NULL, in which case the channel is +created without a name. +.AP ClientData instanceData in +Arbitrary one-word value to be associated with this channel. This +value is passed to procedures in \fItypePtr\fR when they are invoked. +.AP int mask in +OR-ed combination of \fBTCL_READABLE\fR and \fBTCL_WRITABLE\fR to indicate +whether a channel is readable and writable. +.AP Tcl_Channel channel in +The channel to operate on. +.AP int direction in +\fBTCL_READABLE\fR means the input handle is wanted; \fBTCL_WRITABLE\fR +means the output handle is wanted. +.AP ClientData *handlePtr out +Points to the location where the desired OS-specific handle should be +stored. +.AP Tcl_EolTranslation transMode in +The translation mode; one of the constants \fBTCL_TRANSLATE_AUTO\fR, +\fBTCL_TRANSLATE_CR\fR, \fBTCL_TRANSLATE_LF\fR and \fBTCL_TRANSLATE_CRLF\fR. +.AP int size in +The size, in bytes, of buffers to allocate in this channel. +.AP int mask in +An OR-ed combination of \fBTCL_READABLE\fR, \fBTCL_WRITABLE\fR +and \fBTCL_EXCEPTION\fR that indicates events that have occurred on +this channel. +.AP Tcl_Interp *interp in +Current interpreter. (can be NULL) +.AP char *optionName in +Name of the invalid option. +.AP char *optionList in +Specific options list (space separated words, without "-") +to append to the standard generic options list. +Can be NULL for generic options error message only. + +.BE + +.SH DESCRIPTION +.PP +Tcl uses a two-layered channel architecture. It provides a generic upper +layer to enable C and Tcl programs to perform input and output using the +same APIs for a variety of files, devices, sockets etc. The generic C APIs +are described in the manual entry for \fBTcl_OpenFileChannel\fR. +.PP +The lower layer provides type-specific channel drivers for each type +of device supported on each platform. This manual entry describes the +C APIs used to communicate between the generic layer and the +type-specific channel drivers. It also explains how new types of +channels can be added by providing new channel drivers. +.PP +Channel drivers consist of a number of components: First, each channel +driver provides a \fBTcl_ChannelType\fR structure containing pointers to +functions implementing the various operations used by the generic layer to +communicate with the channel driver. The \fBTcl_ChannelType\fR structure +and the functions referenced by it are described in the section +TCL_CHANNELTYPE, below. +.PP +Second, channel drivers usually provide a Tcl command to create +instances of that type of channel. For example, the Tcl \fBopen\fR +command creates channels that use the file and command channel +drivers, and the Tcl \fBsocket\fR command creates channels that use +TCP sockets for network communication. +.PP +Third, a channel driver optionally provides a C function to open +channel instances of that type. For example, \fBTcl_OpenFileChannel\fR +opens a channel that uses the file channel driver, and +\fBTcl_OpenTcpClient\fR opens a channel that uses the TCP network +protocol. These creation functions typically use +\fBTcl_CreateChannel\fR internally to open the channel. +.PP +To add a new type of channel you must implement a C API or a Tcl command +that opens a channel by invoking \fBTcl_CreateChannel\fR. +When your driver calls \fBTcl_CreateChannel\fR it passes in +a \fBTcl_ChannelType\fR structure describing the driver's I/O +procedures. +The generic layer will then invoke the functions referenced in that +structure to perform operations on the channel. +.PP +\fBTcl_CreateChannel\fR opens a new channel and associates the supplied +\fItypePtr\fR and \fIinstanceData\fR with it. The channel is opened in the +mode indicated by \fImask\fR. +For a discussion of channel drivers, their operations and the +\fBTcl_ChannelType\fR structure, see the section TCL_CHANNELTYPE, below. +.PP +\fBTcl_GetChannelInstanceData\fR returns the instance data associated with +the channel in \fIchannel\fR. This is the same as the \fIinstanceData\fR +argument in the call to \fBTcl_CreateChannel\fR that created this channel. +.PP +\fBTcl_GetChannelType\fR returns a pointer to the \fBTcl_ChannelType\fR +structure used by the channel in the \fIchannel\fR argument. This is +the same as the \fItypePtr\fR argument in the call to +\fBTcl_CreateChannel\fR that created this channel. +.PP +\fBTcl_GetChannelName\fR returns a string containing the name associated +with the channel, or NULL if the \fIchannelName\fR argument to +\fBTcl_CreateChannel\fR was NULL. +.PP +\fBTcl_GetChannelHandle\fR places the OS-specific device handle +associated with \fIchannel\fR for the given \fIdirection\fR in the +location specified by \fIhandlePtr\fR and returns \fBTCL_OK\fR. If +the channel does not have a device handle for the specified direction, +then \fBTCL_ERROR\fR is returned instead. Different channel drivers +will return different types of handle. Refer to the manual entries +for each driver to determine what type of handle is returned. +.PP +\fBTcl_GetChannelMode\fR returns an OR-ed combination of \fBTCL_READABLE\fR +and \fBTCL_WRITABLE\fR, indicating whether the channel is open for input +and output. +.PP + \fBTcl_GetChannelBufferSize\fR returns the size, in bytes, of buffers +allocated to store input or output in \fIchan\fR. If the value was not set +by a previous call to \fBTcl_SetChannelBufferSize\fR, described below, then +the default value of 4096 is returned. +.PP +\fBTcl_SetChannelBufferSize\fR sets the size, in bytes, of buffers that +will be allocated in subsequent operations on the channel to store input or +output. The \fIsize\fR argument should be between ten and one million, +allowing buffers of ten bytes to one million bytes. If \fIsize\fR is +outside this range, \fBTcl_SetChannelBufferSize\fR sets the buffer size to +4096. +.PP +\fBTcl_NotifyChannel\fR is called by a channel driver to indicate to +the generic layer that the events specified by \fImask\fR have +occurred on the channel. Channel drivers are responsible for invoking +this function whenever the channel handlers need to be called for the +channel. See \fBWATCHPROC\fR below for more details. +.PP +\fBTcl_BadChannelOption\fR is called from driver specific set or get option +procs to generate a complete error message. + +.SH TCL_CHANNELTYPE +.PP +A channel driver provides a \fBTcl_ChannelType\fR structure that contains +pointers to functions that implement the various operations on a channel; +these operations are invoked as needed by the generic layer. The structure +was versioned starting in Tcl 8.3.2/8.4 to correct a problem with stacked +channel drivers. See the \fBOLD_CHANNEL\fR section below for details about +the old structure. +.PP +The \fBTcl_ChannelType\fR structure contains the following fields: +.CS +typedef struct Tcl_ChannelType { + char *\fItypeName\fR; + Tcl_ChannelTypeVersion \fIversion\fR; + Tcl_DriverCloseProc *\fIcloseProc\fR; + Tcl_DriverInputProc *\fIinputProc\fR; + Tcl_DriverOutputProc *\fIoutputProc\fR; + Tcl_DriverSeekProc *\fIseekProc\fR; + Tcl_DriverSetOptionProc *\fIsetOptionProc\fR; + Tcl_DriverGetOptionProc *\fIgetOptionProc\fR; + Tcl_DriverWatchProc *\fIwatchProc\fR; + Tcl_DriverGetHandleProc *\fIgetHandleProc\fR; + Tcl_DriverClose2Proc *\fIclose2Proc\fR; + Tcl_DriverBlockModeProc *\fIblockModeProc\fR; + Tcl_DriverFlushProc *\fIflushProc\fR; + Tcl_DriverHandlerProc *\fIhandlerProc\fR; +} Tcl_ChannelType; +.CE +.PP +The driver must provide implementations for all functions except +\fIblockModeProc\fR, \fIseekProc\fR, \fIsetOptionProc\fR, +\fIgetOptionProc\fR, and \fIclose2Proc\fR, which may be specified as +NULL. Other functions that can not be implemented for this type of +device should return \fBEINVAL\fR when invoked to indicate that they +are not implemented, except in the case of \fIflushProc\fR and +\fIhandlerProc\fR, which should specified as NULL if not otherwise defined. +.PP +.VS 8.3.2 +The user should only use the above structure for \fBTcl_ChannelType\fR +instantiation. When referencing fields in a \fBTcl_ChannelType\fR +structure, the following functions should be used to obtain the values: +\fBTcl_ChannelName\fR, \fBTcl_ChannelVersion\fR, +\fBTcl_ChannelBlockModeProc\fR, \fBTcl_ChannelCloseProc\fR, +\fBTcl_ChannelClose2Proc\fR, \fBTcl_ChannelInputProc\fR, +\fBTcl_ChannelOutputProc\fR, \fBTcl_ChannelSeekProc\fR, +\fBTcl_ChannelSetOptionProc\fR, \fBTcl_ChannelGetOptionProc\fR, +\fBTcl_ChannelWatchProc\fR, \fBTcl_ChannelGetHandleProc\fR, +\fBTcl_ChannelFlushProc\fR, or \fBTcl_ChannelHandlerProc\fR. +.PP +The change to the structures was made in such a way that standard channel +types are binary compatible. However, channel types that use stacked +channels (ie: TLS, Trf) have new versions to correspond to the above change +since the previous code for stacked channels had problems. +.VE + +.SH TYPENAME +.PP +The \fItypeName\fR field contains a null-terminated string that +identifies the type of the device implemented by this driver, e.g. +\fBfile\fR or \fBsocket\fR. +.PP +.VS 8.3.2 +This value can be retrieved with \fBTcl_ChannelName\fR, which returns +a pointer to the string. +.VE + +.VS 8.3.2 +.SH VERSION +.PP +The \fIversion\fR field should be set to \fBTCL_CHANNEL_VERSION_2\fR. +If it is not set to this value \fBTCL_CHANNEL_VERSION_2\fR, then this +\fBTcl_ChannelType\fR is assumed to have the older structure. See +\fBOLD_CHANNEL\fR for more details. While Tcl will recognize and +function with either structure, stacked channels must be of the newer +style to function correctly. +.PP +This value can be retrieved with \fBTcl_ChannelVersion\fR, which returns +either \fBTCL_CHANNEL_VERSION_2\fR or \fBTCL_CHANNEL_VERSION_1\fR. +.VE + +.SH BLOCKMODEPROC +.PP +The \fIblockModeProc\fR field contains the address of a function called by +the generic layer to set blocking and nonblocking mode on the device. +\fIBlockModeProc\fR should match the following prototype: +.PP +.CS +typedef int Tcl_DriverBlockModeProc( + ClientData \fIinstanceData\fR, + int \fImode\fR); +.CE +.PP +The \fIinstanceData\fR is the same as the value passed to +\fBTcl_CreateChannel\fR when this channel was created. The \fImode\fR +argument is either \fBTCL_MODE_BLOCKING\fR or \fBTCL_MODE_NONBLOCKING\fR to +set the device into blocking or nonblocking mode. The function should +return zero if the operation was successful, or a nonzero POSIX error code +if the operation failed. +.PP +If the operation is successful, the function can modify the supplied +\fIinstanceData\fR to record that the channel entered blocking or +nonblocking mode and to implement the blocking or nonblocking behavior. +For some device types, the blocking and nonblocking behavior can be +implemented by the underlying operating system; for other device types, the +behavior must be emulated in the channel driver. +.PP +.VS 8.3.2 +This value can be retrieved with \fBTcl_ChannelBlockModeProc\fR, which returns +a pointer to the function. +.VE + +.SH "CLOSEPROC AND CLOSE2PROC" +.PP +The \fIcloseProc\fR field contains the address of a function called by the +generic layer to clean up driver-related information when the channel is +closed. \fICloseProc\fR must match the following prototype: +.PP +.CS +typedef int Tcl_DriverCloseProc( + ClientData \fIinstanceData\fR, + Tcl_Interp *\fIinterp\fR); +.CE +.PP +The \fIinstanceData\fR argument is the same as the value provided to +\fBTcl_CreateChannel\fR when the channel was created. The function should +release any storage maintained by the channel driver for this channel, and +close the input and output devices encapsulated by this channel. All queued +output will have been flushed to the device before this function is called, +and no further driver operations will be invoked on this instance after +calling the \fIcloseProc\fR. If the close operation is successful, the +procedure should return zero; otherwise it should return a nonzero POSIX +error code. In addition, if an error occurs and \fIinterp\fR is not NULL, +the procedure should store an error message in the interpreter's result. +.PP +Alternatively, channels that support closing the read and write sides +independently may set \fIcloseProc\fR to \fBTCL_CLOSE2PROC\fR and set +\fIclose2Proc\fR to the address of a function that matches the +following prototype: +.PP +.CS +typedef int Tcl_DriverClose2Proc( + ClientData \fIinstanceData\fR, + Tcl_Interp *\fIinterp\fR, + int \fIflags\fR); +.CE +.PP +The \fIclose2Proc\fR will be called with \fIflags\fR set to an OR'ed +combination of \fBTCL_CLOSE_READ\fR or \fBTCL_CLOSE_WRITE\fR to +indicate that the driver should close the read and/or write side of +the channel. The channel driver may be invoked to perform +additional operations on the channel after \fIclose2Proc\fR is +called to close one or both sides of the channel. If \fIflags\fR is +\fB0\fR (zero), the driver should close the channel in the manner +described above for \fIcloseProc\fR. No further operations will be +invoked on this instance after \fIclose2Proc\fR is called with all +flags cleared. In all cases, the \fIclose2Proc\fR function should +return zero if the close operation was successful; otherwise it should +return a nonzero POSIX error code. In addition, if an error occurs and +\fIinterp\fR is not NULL, the procedure should store an error message +in the interpreter's result. +.PP +.VS 8.3.2 +These value can be retrieved with \fBTcl_ChannelCloseProc\fR or +\fBTcl_ChannelClose2Proc\fR, which returns a pointer to the respective +function. +.VE + +.SH INPUTPROC +.PP +The \fIinputProc\fR field contains the address of a function called by the +generic layer to read data from the file or device and store it in an +internal buffer. \fIInputProc\fR must match the following prototype: +.PP +.CS +typedef int Tcl_DriverInputProc( + ClientData \fIinstanceData\fR, + char *\fIbuf\fR, + int \fIbufSize\fR, + int *\fIerrorCodePtr\fR); +.CE +.PP +\fIInstanceData\fR is the same as the value passed to +\fBTcl_CreateChannel\fR when the channel was created. The \fIbuf\fR +argument points to an array of bytes in which to store input from the +device, and the \fIbufSize\fR argument indicates how many bytes are +available at \fIbuf\fR. +.PP +The \fIerrorCodePtr\fR argument points to an integer variable provided by +the generic layer. If an error occurs, the function should set the variable +to a POSIX error code that identifies the error that occurred. +.PP +The function should read data from the input device encapsulated by the +channel and store it at \fIbuf\fR. On success, the function should return +a nonnegative integer indicating how many bytes were read from the input +device and stored at \fIbuf\fR. On error, the function should return -1. If +an error occurs after some data has been read from the device, that data is +lost. +.PP +If \fIinputProc\fR can determine that the input device has some data +available but less than requested by the \fIbufSize\fR argument, the +function should only attempt to read as much data as is available and +return without blocking. If the input device has no data available +whatsoever and the channel is in nonblocking mode, the function should +return an \fBEAGAIN\fR error. If the input device has no data available +whatsoever and the channel is in blocking mode, the function should block +for the shortest possible time until at least one byte of data can be read +from the device; then, it should return as much data as it can read without +blocking. +.PP +.VS 8.3.2 +This value can be retrieved with \fBTcl_ChannelInputProc\fR, which returns +a pointer to the function. +.VE + +.SH OUTPUTPROC +.PP +The \fIoutputProc\fR field contains the address of a function called by the +generic layer to transfer data from an internal buffer to the output device. +\fIOutputProc\fR must match the following prototype: +.PP +.CS +typedef int Tcl_DriverOutputProc( + ClientData \fIinstanceData\fR, + char *\fIbuf\fR, + int \fItoWrite\fR, + int *\fIerrorCodePtr\fR); +.CE +.PP +\fIInstanceData\fR is the same as the value passed to +\fBTcl_CreateChannel\fR when the channel was created. The \fIbuf\fR +argument contains an array of bytes to be written to the device, and the +\fItoWrite\fR argument indicates how many bytes are to be written from the +\fIbuf\fR argument. +.PP +The \fIerrorCodePtr\fR argument points to an integer variable provided by +the generic layer. If an error occurs, the function should set this +variable to a POSIX error code that identifies the error. +.PP +The function should write the data at \fIbuf\fR to the output device +encapsulated by the channel. On success, the function should return a +nonnegative integer indicating how many bytes were written to the output +device. The return value is normally the same as \fItoWrite\fR, but may be +less in some cases such as if the output operation is interrupted by a +signal. If an error occurs the function should return -1. In case of +error, some data may have been written to the device. +.PP +If the channel is nonblocking and the output device is unable to absorb any +data whatsoever, the function should return -1 with an \fBEAGAIN\fR error +without writing any data. +.PP +.VS 8.3.2 +This value can be retrieved with \fBTcl_ChannelOutputProc\fR, which returns +a pointer to the function. +.VE + +.SH SEEKPROC +.PP +The \fIseekProc\fR field contains the address of a function called by the +generic layer to move the access point at which subsequent input or output +operations will be applied. \fISeekProc\fR must match the following +prototype: +.PP +.CS +typedef int Tcl_DriverSeekProc( + ClientData \fIinstanceData\fR, + long \fIoffset\fR, + int \fIseekMode\fR, + int *\fIerrorCodePtr\fR); +.CE +.PP +The \fIinstanceData\fR argument is the same as the value given to +\fBTcl_CreateChannel\fR when this channel was created. \fIOffset\fR and +\fIseekMode\fR have the same meaning as for the \fBTcl_Seek\fR +procedure (described in the manual entry for \fBTcl_OpenFileChannel\fR). +.PP +The \fIerrorCodePtr\fR argument points to an integer variable provided by +the generic layer for returning \fBerrno\fR values from the function. The +function should set this variable to a POSIX error code if an error occurs. +The function should store an \fBEINVAL\fR error code if the channel type +does not implement seeking. +.PP +The return value is the new access point or -1 in case of error. If an +error occurred, the function should not move the access point. +.PP +.VS 8.3.2 +This value can be retrieved with \fBTcl_ChannelSeekProc\fR, which returns +a pointer to the function. +.VE + +.SH SETOPTIONPROC +.PP +The \fIsetOptionProc\fR field contains the address of a function called by +the generic layer to set a channel type specific option on a channel. +\fIsetOptionProc\fR must match the following prototype: +.PP +.CS +typedef int Tcl_DriverSetOptionProc( + ClientData \fIinstanceData\fR, + Tcl_Interp *\fIinterp\fR, + char *\fIoptionName\fR, + char *\fIoptionValue\fR); +.CE +.PP +\fIoptionName\fR is the name of an option to set, and \fIoptionValue\fR is +the new value for that option, as a string. The \fIinstanceData\fR is the +same as the value given to \fBTcl_CreateChannel\fR when this channel was +created. The function should do whatever channel type specific action is +required to implement the new value of the option. +.PP +Some options are handled by the generic code and this function is never +called to set them, e.g. \fB-blockmode\fR. Other options are specific to +each channel type and the \fIsetOptionProc\fR procedure of the channel +driver will get called to implement them. The \fIsetOptionProc\fR field can +be NULL, which indicates that this channel type supports no type specific +options. +.PP +If the option value is successfully modified to the new value, the function +returns \fBTCL_OK\fR. +It should call \fBTcl_BadChannelOption\fR which itself returns +\fBTCL_ERROR\fR if the \fIoptionName\fR is +unrecognized. +If \fIoptionValue\fR specifies a value for the option that +is not supported or if a system call error occurs, +the function should leave an error message in the +\fIresult\fR field of \fIinterp\fR if \fIinterp\fR is not NULL. The +function should also call \fBTcl_SetErrno\fR to store an appropriate POSIX +error code. +.PP +.VS 8.3.2 +This value can be retrieved with \fBTcl_ChannelSetOptionProc\fR, which returns +a pointer to the function. +.VE + +.SH GETOPTIONPROC +.PP +The \fIgetOptionProc\fR field contains the address of a function called by +the generic layer to get the value of a channel type specific option on a +channel. \fIgetOptionProc\fR must match the following prototype: +.PP +.CS +typedef int Tcl_DriverGetOptionProc( + ClientData \fIinstanceData\fR, + Tcl_Interp *\fIinterp\fR, + char *\fIoptionName\fR, + Tcl_DString *\fIdsPtr\fR); +.CE +.PP +\fIOptionName\fR is the name of an option supported by this type of +channel. If the option name is not NULL, the function stores its current +value, as a string, in the Tcl dynamic string \fIdsPtr\fR. +If \fIoptionName\fR is NULL, the function stores in \fIdsPtr\fR an +alternating list of all supported options and their current values. +On success, the function returns \fBTCL_OK\fR. +It should call \fBTcl_BadChannelOption\fR which itself returns +\fBTCL_ERROR\fR if the \fIoptionName\fR is +unrecognized. If a system call error occurs, +the function should leave an error message in the +\fIresult\fR field of \fIinterp\fR if \fIinterp\fR is not NULL. The +function should also call \fBTcl_SetErrno\fR to store an appropriate POSIX +error code. +.PP +Some options are handled by the generic code and this function is never +called to retrieve their value, e.g. \fB-blockmode\fR. Other options are +specific to each channel type and the \fIgetOptionProc\fR procedure of the +channel driver will get called to implement them. The \fIgetOptionProc\fR +field can be NULL, which indicates that this channel type supports no type +specific options. +.PP +.VS 8.3.2 +This value can be retrieved with \fBTcl_ChannelGetOptionProc\fR, which returns +a pointer to the function. +.VE + +.SH WATCHPROC +.PP +The \fIwatchProc\fR field contains the address of a function called +by the generic layer to initialize the event notification mechanism to +notice events of interest on this channel. +\fIWatchProc\fR should match the following prototype: +.PP +.CS +typedef void Tcl_DriverWatchProc( + ClientData \fIinstanceData\fR, + int \fImask\fR); +.CE +.PP +The \fIinstanceData\fR is the same as the value passed to +\fBTcl_CreateChannel\fR when this channel was created. The \fImask\fR +argument is an OR-ed combination of \fBTCL_READABLE\fR, \fBTCL_WRITABLE\fR +and \fBTCL_EXCEPTION\fR; it indicates events the caller is interested in +noticing on this channel. +.PP +The function should initialize device type specific mechanisms to +notice when an event of interest is present on the channel. When one +or more of the designated events occurs on the channel, the channel +driver is responsible for calling \fBTcl_NotifyChannel\fR to inform +the generic channel module. The driver should take care not to starve +other channel drivers or sources of callbacks by invoking +Tcl_NotifyChannel too frequently. Fairness can be insured by using +the Tcl event queue to allow the channel event to be scheduled in sequence +with other events. See the description of \fBTcl_QueueEvent\fR for +details on how to queue an event. +.PP +.VS 8.3.2 +This value can be retrieved with \fBTcl_ChannelWatchProc\fR, which returns +a pointer to the function. +.VE + +.SH GETHANDLEPROC +.PP +The \fIgetHandleProc\fR field contains the address of a function called by +the generic layer to retrieve a device-specific handle from the channel. +\fIGetHandleProc\fR should match the following prototype: +.PP +.CS +typedef int Tcl_DriverGetHandleProc( + ClientData \fIinstanceData\fR, + int \fIdirection\fR, + ClientData *\fIhandlePtr\fR); +.CE +.PP +\fIInstanceData\fR is the same as the value passed to +\fBTcl_CreateChannel\fR when this channel was created. The \fIdirection\fR +argument is either \fBTCL_READABLE\fR to retrieve the handle used +for input, or \fBTCL_WRITABLE\fR to retrieve the handle used for +output. +.PP +If the channel implementation has device-specific handles, the +function should retrieve the appropriate handle associated with the +channel, according the \fIdirection\fR argument. The handle should be +stored in the location referred to by \fIhandlePtr\fR, and +\fBTCL_OK\fR should be returned. If the channel is not open for the +specified direction, or if the channel implementation does not use +device handles, the function should return \fBTCL_ERROR\fR. +.PP +.VS 8.3.2 +This value can be retrieved with \fBTcl_ChannelGetHandleProc\fR, which returns +a pointer to the function. +.VE + +.VS 8.3.2 +.SH FLUSHPROC +.PP +The \fIflushProc\fR field is currently reserved for future use. +It should be set to NULL. +\fIFlushProc\fR should match the following prototype: +.PP +.CS +typedef int Tcl_DriverFlushProc( + ClientData \fIinstanceData\fR); +.CE +.PP +This value can be retrieved with \fBTcl_ChannelFlushProc\fR, which returns +a pointer to the function. + +.SH HANDLERPROC +.PP +The \fIhandlerProc\fR field contains the address of a function called by +the generic layer to notify the channel that an event occured. It should +be defined for stacked channel drivers that wish to be notified of events +that occur on the underlying (stacked) channel. +\fIHandlerProc\fR should match the following prototype: +.PP +.CS +typedef int Tcl_DriverHandlerProc( + ClientData \fIinstanceData\fR, + int \fIinterestMask\fR); +.CE +.PP +\fIInstanceData\fR is the same as the value passed to \fBTcl_CreateChannel\fR +when this channel was created. The \fIinterestMask\fR is an OR-ed +combination of \fBTCL_READABLE\fR or \fBTCL_WRITABLE\fR; it indicates what +type of event occured on this channel. +.PP +This value can be retrieved with \fBTcl_ChannelHandlerProc\fR, which returns +a pointer to the function. +.VE + +.SH TCL_BADCHANNELOPTION +.PP +This procedure generates a "bad option" error message in an +(optional) interpreter. It is used by channel drivers when +a invalid Set/Get option is requested. Its purpose is to concatenate +the generic options list to the specific ones and factorize +the generic options error message string. +.PP +It always return \fBTCL_ERROR\fR +.PP +An error message is generated in interp's result object to +indicate that a command was invoked with the a bad option +The message has the form +.CS + bad option "blah": should be one of + <...generic options...>+<...specific options...> +so you get for instance: + bad option "-blah": should be one of -blocking, + -buffering, -buffersize, -eofchar, -translation, + -peername, or -sockname +when called with optionList="peername sockname" +.CE +``blah'' is the optionName argument and ``'' +is a space separated list of specific option words. +The function takes good care of inserting minus signs before +each option, commas after, and an ``or'' before the last option. + +.SH OLD_CHANNEL + +The original (8.3.1 and below) \fBTcl_ChannelType\fR structure contains +the following fields: +.PP +.CS +typedef struct Tcl_ChannelType { + char *\fItypeName\fR; + Tcl_DriverBlockModeProc *\fIblockModeProc\fR; + Tcl_DriverCloseProc *\fIcloseProc\fR; + Tcl_DriverInputProc *\fIinputProc\fR; + Tcl_DriverOutputProc *\fIoutputProc\fR; + Tcl_DriverSeekProc *\fIseekProc\fR; + Tcl_DriverSetOptionProc *\fIsetOptionProc\fR; + Tcl_DriverGetOptionProc *\fIgetOptionProc\fR; + Tcl_DriverWatchProc *\fIwatchProc\fR; + Tcl_DriverGetHandleProc *\fIgetHandleProc\fR; + Tcl_DriverClose2Proc *\fIclose2Proc\fR; +} Tcl_ChannelType; +.CE +.PP +It is still possible to create channel with the above structure. The +internal channel code will determine the version. It is imperative to use +the new \fBTcl_ChannelType\fR structure if you are creating a stacked +channel driver, due to problems with the earlier stacked channel +implementation (in 8.2.0 to 8.3.1). + +.SH "SEE ALSO" +Tcl_Close(3), Tcl_OpenFileChannel(3), Tcl_SetErrno(3), Tcl_QueueEvent(3), Tcl_StackChannel(3) + +.SH KEYWORDS +blocking, channel driver, channel registration, channel type, nonblocking diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CrtChnlHdlr.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CrtChnlHdlr.3 new file mode 100644 index 0000000000000000000000000000000000000000..4a3ed63171f02fcf02a406ea3fe732e40c63d974 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CrtChnlHdlr.3 @@ -0,0 +1,92 @@ +'\" +'\" Copyright (c) 1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: CrtChnlHdlr.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +.so man.macros +.TH Tcl_CreateChannelHandler 3 7.5 Tcl "Tcl Library Procedures" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +Tcl_CreateChannelHandler, Tcl_DeleteChannelHandler \- call a procedure when a channel becomes readable or writable +.SH SYNOPSIS +.nf +.nf +\fB#include \fR +.sp +void +\fBTcl_CreateChannelHandler\fR(\fIchannel, mask, proc, clientData\fR) +.sp +void +\fBTcl_DeleteChannelHandler\fR(\fIchannel, proc, clientData\fR) +.sp +.SH ARGUMENTS +.AS Tcl_ChannelProc clientData +.AP Tcl_Channel channel in +Tcl channel such as returned by \fBTcl_CreateChannel\fR. +.AP int mask in +Conditions under which \fIproc\fR should be called: OR-ed combination of +\fBTCL_READABLE\fR, \fBTCL_WRITABLE\fR and \fBTCL_EXCEPTION\fR. Specify +a zero value to temporarily disable an existing handler. +.AP Tcl_FileProc *proc in +Procedure to invoke whenever the channel indicated by \fIchannel\fR meets +the conditions specified by \fImask\fR. +.AP ClientData clientData in +Arbitrary one-word value to pass to \fIproc\fR. +.BE + +.SH DESCRIPTION +.PP +\fBTcl_CreateChannelHandler\fR arranges for \fIproc\fR to be called in the +future whenever input or output becomes possible on the channel identified +by \fIchannel\fR, or whenever an exceptional condition exists for +\fIchannel\fR. The conditions of interest under which \fIproc\fR will be +invoked are specified by the \fImask\fR argument. +See the manual entry for \fBfileevent\fR for a precise description of +what it means for a channel to be readable or writable. +\fIProc\fR must conform to the following prototype: +.CS +typedef void Tcl_ChannelProc( + ClientData \fIclientData\fR, + int \fImask\fR); +.CE +.PP +The \fIclientData\fR argument is the same as the value passed to +\fBTcl_CreateChannelHandler\fR when the handler was created. Typically, +\fIclientData\fR points to a data structure containing application-specific +information about the channel. \fIMask\fR is an integer mask indicating +which of the requested conditions actually exists for the channel; it will +contain a subset of the bits from the \fImask\fR argument to +\fBTcl_CreateChannelHandler\fR when the handler was created. +.PP +Each channel handler is identified by a unique combination of \fIchannel\fR, +\fIproc\fR and \fIclientData\fR. +There may be many handlers for a given channel as long as they don't +have the same \fIchannel\fR, \fIproc\fR, and \fIclientData\fR. +If \fBTcl_CreateChannelHandler\fR is invoked when there is already a handler +for \fIchannel\fR, \fIproc\fR, and \fIclientData\fR, then no new +handler is created; instead, the \fImask\fR is changed for the +existing handler. +.PP +\fBTcl_DeleteChannelHandler\fR deletes a channel handler identified by +\fIchannel\fR, \fIproc\fR and \fIclientData\fR; if no such handler exists, +the call has no effect. +.PP +Channel handlers are invoked via the Tcl event mechanism, so they +are only useful in applications that are event-driven. +Note also that the conditions specified in the \fImask\fR argument +to \fIproc\fR may no longer exist when \fIproc\fR is invoked: for +example, if there are two handlers for \fBTCL_READABLE\fR on the same +channel, the first handler could consume all of the available input +so that the channel is no longer readable when the second handler +is invoked. +For this reason it may be useful to use nonblocking I/O on channels +for which there are event handlers. + +.SH "SEE ALSO" +Notifier(3), Tcl_CreateChannel(3), Tcl_OpenFileChannel(3), vwait(n). + +.SH KEYWORDS +blocking, callback, channel, events, handler, nonblocking. diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CrtCloseHdlr.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CrtCloseHdlr.3 new file mode 100644 index 0000000000000000000000000000000000000000..a67a71810a6ef037bcc957df5256b06e7e50aa31 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CrtCloseHdlr.3 @@ -0,0 +1,59 @@ +'\" +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: CrtCloseHdlr.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +.so man.macros +.TH Tcl_CreateCloseHandler 3 7.5 Tcl "Tcl Library Procedures" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +Tcl_CreateCloseHandler, Tcl_DeleteCloseHandler \- arrange for callbacks when channels are closed +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +void +\fBTcl_CreateCloseHandler\fR(\fIchannel, proc, clientData\fR) +.sp +void +\fBTcl_DeleteCloseHandler\fR(\fIchannel, proc, clientData\fR) +.sp +.SH ARGUMENTS +.AS Tcl_CloseProc callbackData in +.AP Tcl_Channel channel in +The channel for which to create or delete a close callback. +.AP Tcl_CloseProc *proc in +The procedure to call as the callback. +.AP ClientData clientData in +Arbitrary one-word value to pass to \fIproc\fR. +.BE + +.SH DESCRIPTION +.PP +\fBTcl_CreateCloseHandler\fR arranges for \fIproc\fR to be called when +\fIchannel\fR is closed with \fBTcl_Close\fR or +\fBTcl_UnregisterChannel\fR, or using the Tcl \fBclose\fR command. +\fIProc\fR should match the following prototype: +.PP +.CS +typedef void Tcl_CloseProc( + ClientData \fIclientData\fR); +.CE +.PP +The \fIclientData\fR is the same as the value provided in the call to +\fBTcl_CreateCloseHandler\fR. +.PP +\fBTcl_DeleteCloseHandler\fR removes a close callback for \fIchannel\fR. +The \fIproc\fR and \fIclientData\fR identify which close callback to +remove; \fBTcl_DeleteCloseHandler\fR does nothing if its \fIproc\fR and +\fIclientData\fR arguments do not match the \fIproc\fR and \fIclientData\fR +for a close handler for \fIchannel\fR. + +.SH "SEE ALSO" +close(n), Tcl_Close(3), Tcl_UnregisterChannel(3) + +.SH KEYWORDS +callback, channel closing diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CrtCommand.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CrtCommand.3 new file mode 100644 index 0000000000000000000000000000000000000000..ed8525ac3af7bce3c5a1574dd26668bacdbdaf14 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CrtCommand.3 @@ -0,0 +1,143 @@ +'\" +'\" Copyright (c) 1989-1993 The Regents of the University of California. +'\" Copyright (c) 1994-1997 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: CrtCommand.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_CreateCommand 3 "" Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_CreateCommand \- implement new commands in C +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +Tcl_Command +\fBTcl_CreateCommand\fR(\fIinterp, cmdName, proc, clientData, deleteProc\fR) +.SH ARGUMENTS +.AS Tcl_CmdDeleteProc **deleteProcPtr +.AP Tcl_Interp *interp in +Interpreter in which to create new command. +.AP char *cmdName in +Name of command. +.AP Tcl_CmdProc *proc in +Implementation of new command: \fIproc\fR will be called whenever +\fIcmdName\fR is invoked as a command. +.AP ClientData clientData in +Arbitrary one-word value to pass to \fIproc\fR and \fIdeleteProc\fR. +.AP Tcl_CmdDeleteProc *deleteProc in +Procedure to call before \fIcmdName\fR is deleted from the interpreter; +allows for command-specific cleanup. If NULL, then no procedure is +called before the command is deleted. +.BE + +.SH DESCRIPTION +.PP +\fBTcl_CreateCommand\fR defines a new command in \fIinterp\fR and associates +it with procedure \fIproc\fR such that whenever \fIcmdName\fR is +invoked as a Tcl command (via a call to \fBTcl_Eval\fR) the Tcl interpreter +will call \fIproc\fR to process the command. +It differs from \fBTcl_CreateObjCommand\fR in that a new string-based +command is defined; +that is, a command procedure is defined that takes an array of +argument strings instead of objects. +The object-based command procedures registered by \fBTcl_CreateObjCommand\fR +can execute significantly faster than the string-based command procedures +defined by \fBTcl_CreateCommand\fR. +This is because they take Tcl objects as arguments +and those objects can retain an internal representation that +can be manipulated more efficiently. +Also, Tcl's interpreter now uses objects internally. +In order to invoke a string-based command procedure +registered by \fBTcl_CreateCommand\fR, +it must generate and fetch a string representation +from each argument object before the call +and create a new Tcl object to hold the string result returned by the +string-based command procedure. +New commands should be defined using \fBTcl_CreateObjCommand\fR. +We support \fBTcl_CreateCommand\fR for backwards compatibility. +.PP +The procedures \fBTcl_DeleteCommand\fR, \fBTcl_GetCommandInfo\fR, +and \fBTcl_SetCommandInfo\fR are used in conjunction with +\fBTcl_CreateCommand\fR. +.PP +\fBTcl_CreateCommand\fR will delete an existing command \fIcmdName\fR, +if one is already associated with the interpreter. +It returns a token that may be used to refer +to the command in subsequent calls to \fBTcl_GetCommandName\fR. +If \fIcmdName\fR contains any \fB::\fR namespace qualifiers, +then the command is added to the specified namespace; +otherwise the command is added to the global namespace. +If \fBTcl_CreateCommand\fR is called for an interpreter that is in +the process of being deleted, then it does not create a new command +and it returns NULL. +\fIProc\fR should have arguments and result that match the type +\fBTcl_CmdProc\fR: +.CS +typedef int Tcl_CmdProc( + ClientData \fIclientData\fR, + Tcl_Interp *\fIinterp\fR, + int \fIargc\fR, + char *\fIargv\fR[]); +.CE +When \fIproc\fR is invoked the \fIclientData\fR and \fIinterp\fR +parameters will be copies of the \fIclientData\fR and \fIinterp\fR +arguments given to \fBTcl_CreateCommand\fR. +Typically, \fIclientData\fR points to an application-specific +data structure that describes what to do when the command procedure +is invoked. \fIArgc\fR and \fIargv\fR describe the arguments to +the command, \fIargc\fR giving the number of arguments (including +the command name) and \fIargv\fR giving the values of the arguments +as strings. The \fIargv\fR array will contain \fIargc\fR+1 values; +the first \fIargc\fR values point to the argument strings, and the +last value is NULL. +.VS +Note that the argument strings should not be modified as they may +point to constant strings or may be shared with other parts of the +interpreter. +.VE +.PP +\fIProc\fR must return an integer code that is either \fBTCL_OK\fR, \fBTCL_ERROR\fR, +\fBTCL_RETURN\fR, \fBTCL_BREAK\fR, or \fBTCL_CONTINUE\fR. See the Tcl overview man page +for details on what these codes mean. Most normal commands will only +return \fBTCL_OK\fR or \fBTCL_ERROR\fR. In addition, \fIproc\fR must set +the interpreter result to point to a string value; +in the case of a \fBTCL_OK\fR return code this gives the result +of the command, and in the case of \fBTCL_ERROR\fR it gives an error message. +The \fBTcl_SetResult\fR procedure provides an easy interface for setting +the return value; for complete details on how the the interpreter result +field is managed, see the \fBTcl_Interp\fR man page. +Before invoking a command procedure, +\fBTcl_Eval\fR sets the interpreter result to point to an empty string, +so simple commands can return an empty result by doing nothing at all. +.PP +The contents of the \fIargv\fR array belong to Tcl and are not +guaranteed to persist once \fIproc\fR returns: \fIproc\fR should +not modify them, nor should it set the interpreter result to point +anywhere within the \fIargv\fR values. +Call \fBTcl_SetResult\fR with status \fBTCL_VOLATILE\fR if you want +to return something from the \fIargv\fR array. +.PP +\fIDeleteProc\fR will be invoked when (if) \fIcmdName\fR is deleted. +This can occur through a call to \fBTcl_DeleteCommand\fR or \fBTcl_DeleteInterp\fR, +or by replacing \fIcmdName\fR in another call to \fBTcl_CreateCommand\fR. +\fIDeleteProc\fR is invoked before the command is deleted, and gives the +application an opportunity to release any structures associated +with the command. \fIDeleteProc\fR should have arguments and +result that match the type \fBTcl_CmdDeleteProc\fR: +.CS +typedef void Tcl_CmdDeleteProc(ClientData \fIclientData\fR); +.CE +The \fIclientData\fR argument will be the same as the \fIclientData\fR +argument passed to \fBTcl_CreateCommand\fR. +.PP + +.SH "SEE ALSO" +Tcl_CreateObjCommand, Tcl_DeleteCommand, Tcl_GetCommandInfo, Tcl_SetCommandInfo, Tcl_GetCommandName, Tcl_SetObjResult + +.SH KEYWORDS +bind, command, create, delete, interpreter, namespace diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CrtFileHdlr.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CrtFileHdlr.3 new file mode 100644 index 0000000000000000000000000000000000000000..033bb4a6551fcf81419db51d2c06a0a11b2ccd60 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CrtFileHdlr.3 @@ -0,0 +1,100 @@ +'\" +'\" Copyright (c) 1990-1994 The Regents of the University of California. +'\" Copyright (c) 1994-1997 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: CrtFileHdlr.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_CreateFileHandler 3 8.0 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_CreateFileHandler, Tcl_DeleteFileHandler \- associate procedure callbacks with files or devices (Unix only) +.SH SYNOPSIS +.nf +\fB#include \fR +.VS +.sp +\fBTcl_CreateFileHandler\fR(\fIfd, mask, proc, clientData\fR) +.sp +\fBTcl_DeleteFileHandler\fR(\fIfd\fR) +.VE +.SH ARGUMENTS +.AS Tcl_FileProc clientData +.VS +.AP int fd in +Unix file descriptor for an open file or device. +.VE +.AP int mask in +Conditions under which \fIproc\fR should be called: +OR-ed combination of \fBTCL_READABLE\fR, \fBTCL_WRITABLE\fR, +and \fBTCL_EXCEPTION\fR. May be set to 0 to temporarily disable +a handler. +.AP Tcl_FileProc *proc in +Procedure to invoke whenever the file or device indicated +by \fIfile\fR meets the conditions specified by \fImask\fR. +.AP ClientData clientData in +Arbitrary one-word value to pass to \fIproc\fR. +.BE + +.SH DESCRIPTION +.PP +.VS +\fBTcl_CreateFileHandler\fR arranges for \fIproc\fR to be +invoked in the future whenever I/O becomes possible on a file +or an exceptional condition exists for the file. The file +is indicated by \fIfd\fR, and the conditions of interest +.VE +are indicated by \fImask\fR. For example, if \fImask\fR +is \fBTCL_READABLE\fR, \fIproc\fR will be called when +the file is readable. +The callback to \fIproc\fR is made by \fBTcl_DoOneEvent\fR, so +\fBTcl_CreateFileHandler\fR is only useful in programs that dispatch +events through \fBTcl_DoOneEvent\fR or through Tcl commands such +as \fBvwait\fR. +.PP +\fIProc\fR should have arguments and result that match the +type \fBTcl_FileProc\fR: +.CS +typedef void Tcl_FileProc( + ClientData \fIclientData\fR, + int \fImask\fR); +.CE +The \fIclientData\fR parameter to \fIproc\fR is a copy +of the \fIclientData\fR +argument given to \fBTcl_CreateFileHandler\fR when the callback +was created. Typically, \fIclientData\fR points to a data +structure containing application-specific information about +the file. \fIMask\fR is an integer mask indicating which +of the requested conditions actually exists for the file; it +will contain a subset of the bits in the \fImask\fR argument +to \fBTcl_CreateFileHandler\fR. +.PP +.PP +There may exist only one handler for a given file at a given time. +If \fBTcl_CreateFileHandler\fR is called when a handler already +exists for \fIfd\fR, then the new callback replaces the information +that was previously recorded. +.PP +\fBTcl_DeleteFileHandler\fR may be called to delete the +file handler for \fIfd\fR; if no handler exists for the +file given by \fIfd\fR then the procedure has no effect. +.PP +The purpose of file handlers is to enable an application to respond to +events while waiting for files to become ready for I/O. For this to work +correctly, the application may need to use non-blocking I/O operations on +the files for which handlers are declared. Otherwise the application may +block if it reads or writes too much data; while waiting for the I/O to +complete the application won't be able to service other events. Use +\fBTcl_SetChannelOption\fR with \fB\-blocking\fR to set the channel into +blocking or nonblocking mode as required. +.PP +.VS +Note that these interfaces are only supported by the Unix +implementation of the Tcl notifier. +.VE + +.SH KEYWORDS +callback, file, handler diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CrtInterp.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CrtInterp.3 new file mode 100644 index 0000000000000000000000000000000000000000..f475a1d5b9f3a10650f3ac498446f270c31a4506 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CrtInterp.3 @@ -0,0 +1,131 @@ +'\" +'\" Copyright (c) 1989-1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: CrtInterp.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_CreateInterp 3 7.5 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_CreateInterp, Tcl_DeleteInterp, Tcl_InterpDeleted \- create and delete Tcl command interpreters +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +Tcl_Interp * +\fBTcl_CreateInterp\fR() +.sp +\fBTcl_DeleteInterp\fR(\fIinterp\fR) +.sp +int +\fBTcl_InterpDeleted\fR(\fIinterp\fR) +.SH ARGUMENTS +.AS Tcl_Interp *interp +.AP Tcl_Interp *interp in +Token for interpreter to be destroyed. +.BE + +.SH DESCRIPTION +.PP +\fBTcl_CreateInterp\fR creates a new interpreter structure and returns +a token for it. The token is required in calls to most other Tcl +procedures, such as \fBTcl_CreateCommand\fR, \fBTcl_Eval\fR, and +\fBTcl_DeleteInterp\fR. +Clients are only allowed to access a few of the fields of +Tcl_Interp structures; see the \fBTcl_Interp\fR +and \fBTcl_CreateCommand\fR man pages for details. +The new interpreter is initialized with no defined variables and only +the built-in Tcl commands. To bind in additional commands, call +\fBTcl_CreateCommand\fR. +.PP +\fBTcl_DeleteInterp\fR marks an interpreter as deleted; the interpreter +will eventually be deleted when all calls to \fBTcl_Preserve\fR for it have +been matched by calls to \fBTcl_Release\fR. At that time, all of the +resources associated with it, including variables, procedures, and +application-specific command bindings, will be deleted. After +\fBTcl_DeleteInterp\fR returns any attempt to use \fBTcl_Eval\fR on the +interpreter will fail and return \fBTCL_ERROR\fR. After the call to +\fBTcl_DeleteInterp\fR it is safe to examine the interpreter's result, +query or set the values of variables, define, undefine or retrieve +procedures, and examine the runtime evaluation stack. See below, in the +section \fBINTERPRETERS AND MEMORY MANAGEMENT\fR for details. +.PP +\fBTcl_InterpDeleted\fR returns nonzero if \fBTcl_DeleteInterp\fR was +called with \fIinterp\fR as its argument; this indicates that the +interpreter will eventually be deleted, when the last call to +\fBTcl_Preserve\fR for it is matched by a call to \fBTcl_Release\fR. If +nonzero is returned, further calls to \fBTcl_Eval\fR in this interpreter +will return \fBTCL_ERROR\fR. +.PP +\fBTcl_InterpDeleted\fR is useful in deletion callbacks to distinguish +between when only the memory the callback is responsible for is being +deleted and when the whole interpreter is being deleted. In the former case +the callback may recreate the data being deleted, but this would lead to an +infinite loop if the interpreter were being deleted. + +.SH "INTERPRETERS AND MEMORY MANAGEMENT" +.PP +\fBTcl_DeleteInterp\fR can be called at any time on an interpreter that may +be used by nested evaluations and C code in various extensions. Tcl +implements a simple mechanism that allows callers to use interpreters +without worrying about the interpreter being deleted in a nested call, and +without requiring special code to protect the interpreter, in most cases. +This mechanism ensures that nested uses of an interpreter can safely +continue using it even after \fBTcl_DeleteInterp\fR is called. +.PP +The mechanism relies on matching up calls to \fBTcl_Preserve\fR with calls +to \fBTcl_Release\fR. If \fBTcl_DeleteInterp\fR has been called, only when +the last call to \fBTcl_Preserve\fR is matched by a call to +\fBTcl_Release\fR, will the interpreter be freed. See the manual entry for +\fBTcl_Preserve\fR for a description of these functions. +.PP +The rules for when the user of an interpreter must call \fBTcl_Preserve\fR +and \fBTcl_Release\fR are simple: +.TP +Interpreters Passed As Arguments +Functions that are passed an interpreter as an argument can safely use the +interpreter without any special protection. Thus, when you write an +extension consisting of new Tcl commands, no special code is needed to +protect interpreters received as arguments. This covers the majority of all +uses. +.TP +Interpreter Creation And Deletion +When a new interpreter is created and used in a call to \fBTcl_Eval\fR, +\fBTcl_VarEval\fR, \fBTcl_GlobalEval\fR, \fBTcl_SetVar\fR, or +\fBTcl_GetVar\fR, a pair of calls to \fBTcl_Preserve\fR and +\fBTcl_Release\fR should be wrapped around all uses of the interpreter. +Remember that it is unsafe to use the interpreter once \fBTcl_Release\fR +has been called. To ensure that the interpreter is properly deleted when +it is no longer needed, call \fBTcl_InterpDeleted\fR to test if some other +code already called \fBTcl_DeleteInterp\fR; if not, call +\fBTcl_DeleteInterp\fR before calling \fBTcl_Release\fR in your own code. +Do not call \fBTcl_DeleteInterp\fR on an interpreter for which +\fBTcl_InterpDeleted\fR returns nonzero. +.TP +Retrieving An Interpreter From A Data Structure +When an interpreter is retrieved from a data structure (e.g. the client +data of a callback) for use in \fBTcl_Eval\fR, \fBTcl_VarEval\fR, +\fBTcl_GlobalEval\fR, \fBTcl_SetVar\fR, or \fBTcl_GetVar\fR, a pair of +calls to \fBTcl_Preserve\fR and \fBTcl_Release\fR should be wrapped around +all uses of the interpreter; it is unsafe to reuse the interpreter once +\fBTcl_Release\fR has been called. If an interpreter is stored inside a +callback data structure, an appropriate deletion cleanup mechanism should +be set up by the code that creates the data structure so that the +interpreter is removed from the data structure (e.g. by setting the field +to NULL) when the interpreter is deleted. Otherwise, you may be using an +interpreter that has been freed and whose memory may already have been +reused. +.PP +All uses of interpreters in Tcl and Tk have already been protected. +Extension writers should ensure that their code also properly protects any +additional interpreters used, as described above. + +.SH "SEE ALSO" +Tcl_Preserve(3), Tcl_Release(3) + +.SH KEYWORDS +command, create, delete, interpreter diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CrtMathFnc.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CrtMathFnc.3 new file mode 100644 index 0000000000000000000000000000000000000000..5e6233386d977002ddc199302ee2268e7bc896f3 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CrtMathFnc.3 @@ -0,0 +1,93 @@ +'\" +'\" Copyright (c) 1989-1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: CrtMathFnc.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_CreateMathFunc 3 7.0 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_CreateMathFunc \- Define a new math function for expressions +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +\fBTcl_CreateMathFunc\fR(\fIinterp, name, numArgs, argTypes, proc, clientData\fR) +.SH ARGUMENTS +.AS Tcl_ValueType clientData +.AP Tcl_Interp *interp in +Interpreter in which new function will be defined. +.AP char *name in +Name for new function. +.AP int numArgs in +Number of arguments to new function; also gives size of \fIargTypes\fR array. +.AP Tcl_ValueType *argTypes in +Points to an array giving the permissible types for each argument to +function. +.AP Tcl_MathProc *proc in +Procedure that implements the function. +.AP ClientData clientData in +Arbitrary one-word value to pass to \fIproc\fR when it is invoked. +.BE + +.SH DESCRIPTION +.PP +Tcl allows a number of mathematical functions to be used in +expressions, such as \fBsin\fR, \fBcos\fR, and \fBhypot\fR. +\fBTcl_CreateMathFunc\fR allows applications to add additional functions +to those already provided by Tcl or to replace existing functions. +\fIName\fR is the name of the function as it will appear in expressions. +If \fIname\fR doesn't already exist as a function then a new function +is created. If it does exist, then the existing function is replaced. +\fINumArgs\fR and \fIargTypes\fR describe the arguments to the function. +Each entry in the \fIargTypes\fR array must be either TCL_INT, TCL_DOUBLE, +or TCL_EITHER to indicate whether the corresponding argument must be an +integer, a double-precision floating value, or either, respectively. +.PP +Whenever the function is invoked in an expression Tcl will invoke +\fIproc\fR. \fIProc\fR should have arguments and result that match +the type \fBTcl_MathProc\fR: +.CS +typedef int Tcl_MathProc( + ClientData \fIclientData\fR, + Tcl_Interp *\fIinterp\fR, + Tcl_Value *\fIargs\fR, + Tcl_Value *\fIresultPtr\fR); +.CE +.PP +When \fIproc\fR is invoked the \fIclientData\fR and \fIinterp\fR +arguments will be the same as those passed to \fBTcl_CreateMathFunc\fR. +\fIArgs\fR will point to an array of \fInumArgs\fR Tcl_Value structures, +which describe the actual arguments to the function: +.CS +typedef struct Tcl_Value { + Tcl_ValueType \fItype\fR; + long \fIintValue\fR; + double \fIdoubleValue\fR; +} Tcl_Value; +.CE +.PP +The \fItype\fR field indicates the type of the argument and is +either TCL_INT or TCL_DOUBLE. +It will match the \fIargTypes\fR value specified for the function unless +the \fIargTypes\fR value was TCL_EITHER. Tcl converts +the argument supplied in the expression to the type requested in +\fIargTypes\fR, if that is necessary. +Depending on the value of the \fItype\fR field, the \fIintValue\fR +or \fIdoubleValue\fR field will contain the actual value of the argument. +.PP +\fIProc\fR should compute its result and store it either as an integer +in \fIresultPtr->intValue\fR or as a floating value in +\fIresultPtr->doubleValue\fR. +It should set also \fIresultPtr->type\fR to either TCL_INT or TCL_DOUBLE +to indicate which value was set. +Under normal circumstances \fIproc\fR should return TCL_OK. +If an error occurs while executing the function, \fIproc\fR should +return TCL_ERROR and leave an error message in the interpreter's result. + +.SH KEYWORDS +expression, mathematical function diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CrtObjCmd.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CrtObjCmd.3 new file mode 100644 index 0000000000000000000000000000000000000000..5bb67d0b6f0744799fc2d704598ea443a3407e2b --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CrtObjCmd.3 @@ -0,0 +1,260 @@ +'\" +'\" Copyright (c) 1996-1997 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: CrtObjCmd.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_CreateObjCommand 3 8.0 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_CreateObjCommand, Tcl_DeleteCommand, Tcl_DeleteCommandFromToken, Tcl_GetCommandInfo, Tcl_SetCommandInfo, Tcl_GetCommandName \- implement new commands in C +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +Tcl_Command +\fBTcl_CreateObjCommand\fR(\fIinterp, cmdName, proc, clientData, deleteProc\fR) +.sp +int +\fBTcl_DeleteCommand\fR(\fIinterp, cmdName\fR) +.sp +int +\fBTcl_DeleteCommandFromToken\fR(\fIinterp, token\fR) +.sp +int +\fBTcl_GetCommandInfo\fR(\fIinterp, cmdName, infoPtr\fR) +.sp +int +\fBTcl_SetCommandInfo\fR(\fIinterp, cmdName, infoPtr\fR) +.sp +char * +\fBTcl_GetCommandName\fR(\fIinterp, token\fR) +.SH ARGUMENTS +.AS Tcl_ObjCmdProc *deleteProc in/out +.AP Tcl_Interp *interp in +Interpreter in which to create a new command or that contains a command. +.AP char *cmdName in +Name of command. +.AP Tcl_ObjCmdProc *proc in +Implementation of the new command: \fIproc\fR will be called whenever +\fIcmdName\fR is invoked as a command. +.AP ClientData clientData in +Arbitrary one-word value to pass to \fIproc\fR and \fIdeleteProc\fR. +.AP Tcl_CmdDeleteProc *deleteProc in +Procedure to call before \fIcmdName\fR is deleted from the interpreter; +allows for command-specific cleanup. If NULL, then no procedure is +called before the command is deleted. +.AP Tcl_Command token in +Token for command, returned by previous call to \fBTcl_CreateObjCommand\fR. +The command must not have been deleted. +.AP Tcl_CmdInfo *infoPtr in/out +Pointer to structure containing various information about a +Tcl command. +.BE +.SH DESCRIPTION +.PP +\fBTcl_CreateObjCommand\fR defines a new command in \fIinterp\fR +and associates it with procedure \fIproc\fR +such that whenever \fIname\fR is +invoked as a Tcl command (e.g., via a call to \fBTcl_EvalObjEx\fR) +the Tcl interpreter will call \fIproc\fR to process the command. +.PP +\fBTcl_CreateObjCommand\fR deletes any existing command +\fIname\fR already associated with the interpreter +(however see below for an exception where the existing command +is not deleted). +It returns a token that may be used to refer +to the command in subsequent calls to \fBTcl_GetCommandName\fR. +If \fIname\fR contains any \fB::\fR namespace qualifiers, +then the command is added to the specified namespace; +otherwise the command is added to the global namespace. +If \fBTcl_CreateObjCommand\fR is called for an interpreter that is in +the process of being deleted, then it does not create a new command +and it returns NULL. +\fIproc\fR should have arguments and result that match the type +\fBTcl_ObjCmdProc\fR: +.CS +typedef int Tcl_ObjCmdProc( + ClientData \fIclientData\fR, + Tcl_Interp *\fIinterp\fR, + int \fIobjc\fR, +.VS + Tcl_Obj *CONST \fIobjv\fR[]); +.CE +When \fIproc\fR is invoked, the \fIclientData\fR and \fIinterp\fR parameters +will be copies of the \fIclientData\fR and \fIinterp\fR arguments given to +\fBTcl_CreateObjCommand\fR. Typically, \fIclientData\fR points to an +application-specific data structure that describes what to do when the +command procedure is invoked. \fIObjc\fR and \fIobjv\fR describe the +arguments to the command, \fIobjc\fR giving the number of argument objects +(including the command name) and \fIobjv\fR giving the values of the +arguments. The \fIobjv\fR array will contain \fIobjc\fR values, pointing to +the argument objects. Unlike \fIargv\fR[\fIargv\fR] used in a +string-based command procedure, \fIobjv\fR[\fIobjc\fR] will not contain NULL. +.PP +Additionally, when \fIproc\fR is invoked, it must not modify the contents +of the \fIobjv\fR array by assigning new pointer values to any element of the +array (for example, \fIobjv\fR[\fB2\fR] = \fBNULL\fR) because this will +cause memory to be lost and the runtime stack to be corrupted. The +\fBCONST\fR in the declaration of \fIobjv\fR will cause ANSI-compliant +compilers to report any such attempted assignment as an error. However, +it is acceptable to modify the internal representation of any individual +object argument. For instance, the user may call +\fBTcl_GetIntFromObj\fR on \fIobjv\fR[\fB2\fR] to obtain the integer +representation of that object; that call may change the type of the object +that \fIobjv\fR[\fB2\fR] points at, but will not change where +\fIobjv\fR[\fB2\fR] points. +.VE +.PP +\fIproc\fR must return an integer code that is either \fBTCL_OK\fR, +\fBTCL_ERROR\fR, \fBTCL_RETURN\fR, \fBTCL_BREAK\fR, or \fBTCL_CONTINUE\fR. +See the Tcl overview man page +for details on what these codes mean. Most normal commands will only +return \fBTCL_OK\fR or \fBTCL_ERROR\fR. +In addition, if \fIproc\fR needs to return a non-empty result, +it can call \fBTcl_SetObjResult\fR to set the interpreter's result. +In the case of a \fBTCL_OK\fR return code this gives the result +of the command, +and in the case of \fBTCL_ERROR\fR this gives an error message. +Before invoking a command procedure, +\fBTcl_EvalObjEx\fR sets interpreter's result to +point to an object representing an empty string, so simple +commands can return an empty result by doing nothing at all. +.PP +The contents of the \fIobjv\fR array belong to Tcl and are not +guaranteed to persist once \fIproc\fR returns: \fIproc\fR should +not modify them. +Call \fBTcl_SetObjResult\fR if you want +to return something from the \fIobjv\fR array. +.PP +Ordinarily, \fBTcl_CreateObjCommand\fR deletes any existing command +\fIname\fR already associated with the interpreter. +However, if the existing command was created by a previous call to +\fBTcl_CreateCommand\fR, +\fBTcl_CreateObjCommand\fR does not delete the command +but instead arranges for the Tcl interpreter to call the +\fBTcl_ObjCmdProc\fR \fIproc\fR in the future. +The old string-based \fBTcl_CmdProc\fR associated with the command +is retained and its address can be obtained by subsequent +\fBTcl_GetCommandInfo\fR calls. This is done for backwards compatibility. +.PP +\fIDeleteProc\fR will be invoked when (if) \fIname\fR is deleted. +This can occur through a call to \fBTcl_DeleteCommand\fR, +\fBTcl_DeleteCommandFromToken\fR, or \fBTcl_DeleteInterp\fR, +or by replacing \fIname\fR in another call to \fBTcl_CreateObjCommand\fR. +\fIDeleteProc\fR is invoked before the command is deleted, and gives the +application an opportunity to release any structures associated +with the command. \fIDeleteProc\fR should have arguments and +result that match the type \fBTcl_CmdDeleteProc\fR: +.CS +typedef void Tcl_CmdDeleteProc(ClientData \fIclientData\fR); +.CE +The \fIclientData\fR argument will be the same as the \fIclientData\fR +argument passed to \fBTcl_CreateObjCommand\fR. +.PP +\fBTcl_DeleteCommand\fR deletes a command from a command interpreter. +Once the call completes, attempts to invoke \fIcmdName\fR in +\fIinterp\fR will result in errors. +If \fIcmdName\fR isn't bound as a command in \fIinterp\fR then +\fBTcl_DeleteCommand\fR does nothing and returns -1; otherwise +it returns 0. +There are no restrictions on \fIcmdName\fR: it may refer to +a built-in command, an application-specific command, or a Tcl procedure. +If \fIname\fR contains any \fB::\fR namespace qualifiers, +the command is deleted from the specified namespace. +.PP +Given a token returned by \fBTcl_CreateObjCommand\fR, +\fBTcl_DeleteCommandFromToken\fR deletes the command +from a command interpreter. +It will delete a command even if that command has been renamed. +Once the call completes, attempts to invoke the command in +\fIinterp\fR will result in errors. +If the command corresponding to \fItoken\fR +has already been deleted from \fIinterp\fR then +\fBTcl_DeleteCommand\fR does nothing and returns -1; +otherwise it returns 0. +.PP +\fBTcl_GetCommandInfo\fR checks to see whether its \fIcmdName\fR argument +exists as a command in \fIinterp\fR. +\fIcmdName\fR may include \fB::\fR namespace qualifiers +to identify a command in a particular namespace. +If the command is not found, then it returns 0. +Otherwise it places information about the command +in the \fBTcl_CmdInfo\fR structure +pointed to by \fIinfoPtr\fR and returns 1. +A \fBTcl_CmdInfo\fR structure has the following fields: +.CS +typedef struct Tcl_CmdInfo { + int isNativeObjectProc; + Tcl_ObjCmdProc *objProc; + ClientData objClientData; + Tcl_CmdProc *proc; + ClientData clientData; + Tcl_CmdDeleteProc *deleteProc; + ClientData deleteData; + Tcl_Namespace *namespacePtr; +} Tcl_CmdInfo; +.CE +The \fIisNativeObjectProc\fR field has the value 1 +if \fBTcl_CreateObjCommand\fR was called to register the command; +it is 0 if only \fBTcl_CreateCommand\fR was called. +It allows a program to determine whether it is faster to +call \fIobjProc\fR or \fIproc\fR: +\fIobjProc\fR is normally faster +if \fIisNativeObjectProc\fR has the value 1. +The fields \fIobjProc\fR and \fIobjClientData\fR +have the same meaning as the \fIproc\fR and \fIclientData\fR +arguments to \fBTcl_CreateObjCommand\fR; +they hold information about the object-based command procedure +that the Tcl interpreter calls to implement the command. +The fields \fIproc\fR and \fIclientData\fR +hold information about the string-based command procedure +that implements the command. +If \fBTcl_CreateCommand\fR was called for this command, +this is the procedure passed to it; +otherwise, this is a compatibility procedure +registered by \fBTcl_CreateObjCommand\fR +that simply calls the command's +object-based procedure after converting its string arguments to Tcl objects. +The field \fIdeleteData\fR is the ClientData value +to pass to \fIdeleteProc\fR; it is normally the same as +\fIclientData\fR but may be set independently using the +\fBTcl_SetCommandInfo\fR procedure. +The field \fInamespacePtr\fR holds a pointer to the +Tcl_Namespace that contains the command. +.PP +\fBTcl_SetCommandInfo\fR is used to modify the procedures and +ClientData values associated with a command. +Its \fIcmdName\fR argument is the name of a command in \fIinterp\fR. +\fIcmdName\fR may include \fB::\fR namespace qualifiers +to identify a command in a particular namespace. +If this command does not exist then \fBTcl_SetCommandInfo\fR returns 0. +Otherwise, it copies the information from \fI*infoPtr\fR to +Tcl's internal structure for the command and returns 1. +Note that this procedure allows the ClientData for a command's +deletion procedure to be given a different value than the ClientData +for its command procedure. +Note that \fBTcl_SetCmdInfo\fR will not change a command's namespace; +you must use \fBTcl_RenameCommand\fR to do that. +.PP +\fBTcl_GetCommandName\fR provides a mechanism for tracking commands +that have been renamed. +Given a token returned by \fBTcl_CreateObjCommand\fR +when the command was created, \fBTcl_GetCommandName\fR returns the +string name of the command. If the command has been renamed since it +was created, then \fBTcl_GetCommandName\fR returns the current name. +This name does not include any \fB::\fR namespace qualifiers. +The command corresponding to \fItoken\fR must not have been deleted. +The string returned by \fBTcl_GetCommandName\fR is in dynamic memory +owned by Tcl and is only guaranteed to retain its value as long as the +command isn't deleted or renamed; callers should copy the string if +they need to keep it for a long time. + +.SH "SEE ALSO" +Tcl_CreateCommand, Tcl_ResetResult, Tcl_SetObjResult + +.SH KEYWORDS +bind, command, create, delete, namespace, object diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CrtSlave.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CrtSlave.3 new file mode 100644 index 0000000000000000000000000000000000000000..c2b2e7199bae38cfabf77b843da6a81e4548fb22 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CrtSlave.3 @@ -0,0 +1,231 @@ +'\" +'\" Copyright (c) 1995-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: CrtSlave.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_CreateSlave 3 7.6 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_IsSafe, Tcl_MakeSafe, Tcl_CreateSlave, Tcl_GetSlave, Tcl_GetMaster, Tcl_GetInterpPath, Tcl_CreateAlias, Tcl_CreateAliasObj, Tcl_GetAlias, Tcl_GetAliasObj, Tcl_ExposeCommand, Tcl_HideCommand \- manage multiple Tcl interpreters, aliases and hidden commands. +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +int +\fBTcl_IsSafe\fR(\fIinterp\fR) +.sp +int +\fBTcl_MakeSafe\fR(\fIinterp\fR) +.sp +Tcl_Interp * +\fBTcl_CreateSlave\fR(\fIinterp, slaveName, isSafe\fR) +.sp +Tcl_Interp * +\fBTcl_GetSlave\fR(\fIinterp, slaveName\fR) +.sp +Tcl_Interp * +\fBTcl_GetMaster\fR(\fIinterp\fR) +.sp +int +\fBTcl_GetInterpPath\fR(\fIaskingInterp, slaveInterp\fR) +.sp +.VS +int +\fBTcl_CreateAlias\fR(\fIslaveInterp, srcCmd, targetInterp, targetCmd, argc, argv\fR) +.sp +int +\fBTcl_CreateAliasObj\fR(\fIslaveInterp, srcCmd, targetInterp, targetCmd, objc, objv\fR) +.VE +.sp +int +\fBTcl_GetAlias\fR(\fIinterp, srcCmd, targetInterpPtr, targetCmdPtr, argcPtr, argvPtr\fR) +.sp +.VS +int +\fBTcl_GetAliasObj\fR(\fIinterp, srcCmd, targetInterpPtr, targetCmdPtr, objcPtr, objvPtr\fR) +.sp +int +\fBTcl_ExposeCommand\fR(\fIinterp, hiddenCmdName, cmdName\fR) +.sp +int +\fBTcl_HideCommand\fR(\fIinterp, cmdName, hiddenCmdName\fR) +.SH ARGUMENTS +.AS Tcl_InterpDeleteProc **hiddenCmdName +.AP Tcl_Interp *interp in +Interpreter in which to execute the specified command. +.AP char *slaveName in +Name of slave interpreter to create or manipulate. +.AP int isSafe in +If non-zero, a ``safe'' slave that is suitable for running untrusted code +is created, otherwise a trusted slave is created. +.AP Tcl_Interp *slaveInterp in +Interpreter to use for creating the source command for an alias (see +below). +.AP char *srcCmd in +Name of source command for alias. +.AP Tcl_Interp *targetInterp in +Interpreter that contains the target command for an alias. +.AP char *targetCmd in +Name of target command for alias in \fItargetInterp\fR. +.AP int argc in +Count of additional arguments to pass to the alias command. +.AP char **argv in +Vector of strings, the additional arguments to pass to the alias command. +This storage is owned by the caller. +.AP int objc in +Count of additional object arguments to pass to the alias object command. +.AP Tcl_Object **objv in +Vector of Tcl_Obj structures, the additional object argumenst to pass to +the alias object command. +This storage is owned by the caller. +.AP Tcl_Interp **targetInterpPtr in +Pointer to location to store the address of the interpreter where a target +command is defined for an alias. +.AP char **targetCmdPtr out +Pointer to location to store the address of the name of the target command +for an alias. +.AP int *argcPtr out +Pointer to location to store count of additional arguments to be passed to +the alias. The location is in storage owned by the caller. +.AP char ***argvPtr out +Pointer to location to store a vector of strings, the additional arguments +to pass to an alias. The location is in storage owned by the caller, the +vector of strings is owned by the called function. +.AP int *objcPtr out +Pointer to location to store count of additional object arguments to be +passed to the alias. The location is in storage owned by the caller. +.AP Tcl_Obj ***objvPtr out +Pointer to location to store a vector of Tcl_Obj structures, the additional +arguments to pass to an object alias command. The location is in storage +owned by the caller, the vector of Tcl_Obj structures is owned by the +called function. +.VS +.AP char *cmdName in +Name of an exposed command to hide or create. +.AP char *hiddenCmdName in +Name under which a hidden command is stored and with which it can be +exposed or invoked. +.VE +.BE + +.SH DESCRIPTION +.PP +These procedures are intended for access to the multiple interpreter +facility from inside C programs. They enable managing multiple interpreters +in a hierarchical relationship, and the management of aliases, commands +that when invoked in one interpreter execute a command in another +interpreter. The return value for those procedures that return an \fBint\fR +is either \fBTCL_OK\fR or \fBTCL_ERROR\fR. If \fBTCL_ERROR\fR is returned +then the \fBresult\fR field of the interpreter contains an error message. +.PP +\fBTcl_CreateSlave\fR creates a new interpreter as a slave of \fIinterp\fR. +It also creates a slave command named \fIslaveName\fR in \fIinterp\fR which +allows \fIinterp\fR to manipulate the new slave. +If \fIisSafe\fR is zero, the command creates a trusted slave in which Tcl +code has access to all the Tcl commands. +If it is \fB1\fR, the command creates a ``safe'' slave in which Tcl code +has access only to set of Tcl commands defined as ``Safe Tcl''; see the +manual entry for the Tcl \fBinterp\fR command for details. +If the creation of the new slave interpreter failed, \fBNULL\fR is returned. +.PP +\fBTcl_IsSafe\fR returns \fB1\fR if \fIinterp\fR is ``safe'' (was created +with the \fBTCL_SAFE_INTERPRETER\fR flag specified), +\fB0\fR otherwise. +.PP +\fBTcl_MakeSafe\fR makes \fIinterp\fR ``safe'' by removing all +non-core and core unsafe functionality. Note that if you call this after +adding some extension to an interpreter, all traces of that extension will +be removed from the interpreter. +.PP +\fBTcl_GetSlave\fR returns a pointer to a slave interpreter of +\fIinterp\fR. The slave interpreter is identified by \fIslaveName\fR. +If no such slave interpreter exists, \fBNULL\fR is returned. +.PP +\fBTcl_GetMaster\fR returns a pointer to the master interpreter of +\fIinterp\fR. If \fIinterp\fR has no master (it is a +top-level interpreter) then \fBNULL\fR is returned. +.PP +\fBTcl_GetInterpPath\fR sets the \fIresult\fR field in \fIaskingInterp\fR +to the relative path between \fIaskingInterp\fR and \fIslaveInterp\fR; +\fIslaveInterp\fR must be a slave of \fIaskingInterp\fR. If the computation +of the relative path succeeds, \fBTCL_OK\fR is returned, else +\fBTCL_ERROR\fR is returned and the \fIresult\fR field in +\fIaskingInterp\fR contains the error message. +.PP +.VS +\fBTcl_CreateAlias\fR creates an object command named \fIsrcCmd\fR in +\fIslaveInterp\fR that when invoked, will cause the command \fItargetCmd\fR +to be invoked in \fItargetInterp\fR. The arguments specified by the strings +contained in \fIargv\fR are always prepended to any arguments supplied in the +invocation of \fIsrcCmd\fR and passed to \fItargetCmd\fR. +This operation returns \fBTCL_OK\fR if it succeeds, or \fBTCL_ERROR\fR if +it fails; in that case, an error message is left in the object result +of \fIslaveInterp\fR. +Note that there are no restrictions on the ancestry relationship (as +created by \fBTcl_CreateSlave\fR) between \fIslaveInterp\fR and +\fItargetInterp\fR. Any two interpreters can be used, without any +restrictions on how they are related. +.PP +\fBTcl_CreateAliasObj\fR is similar to \fBTcl_CreateAlias\fR except +that it takes a vector of objects to pass as additional arguments instead +of a vector of strings. +.VE +.PP +\fBTcl_GetAlias\fR returns information about an alias \fIaliasName\fR +in \fIinterp\fR. Any of the result fields can be \fBNULL\fR, in +which case the corresponding datum is not returned. If a result field is +non\-\fBNULL\fR, the address indicated is set to the corresponding datum. +For example, if \fItargetNamePtr\fR is non\-\fBNULL\fR it is set to a +pointer to the string containing the name of the target command. +.VS +.PP +\fBTcl_GetAliasObj\fR is similar to \fBTcl_GetAlias\fR except that it +returns a pointer to a vector of Tcl_Obj structures instead of a vector of +strings. +.PP +\fBTcl_ExposeCommand\fR moves the command named \fIhiddenCmdName\fR from +the set of hidden commands to the set of exposed commands, putting +it under the name +\fIcmdName\fR. +\fIHiddenCmdName\fR must be the name of an existing hidden +command, or the operation will return \fBTCL_ERROR\fR and leave an error +message in the \fIresult\fR field in \fIinterp\fR. +If an exposed command named \fIcmdName\fR already exists, +the operation returns \fBTCL_ERROR\fR and leaves an error message in the +object result of \fIinterp\fR. +If the operation succeeds, it returns \fBTCL_OK\fR. +After executing this command, attempts to use \fIcmdName\fR in a call to +\fBTcl_Eval\fR or with the Tcl \fBeval\fR command will again succeed. +.PP +\fBTcl_HideCommand\fR moves the command named \fIcmdName\fR from the set of +exposed commands to the set of hidden commands, under the name +\fIhiddenCmdName\fR. +\fICmdName\fR must be the name of an existing exposed +command, or the operation will return \fBTCL_ERROR\fR and leave an error +message in the object result of \fIinterp\fR. +Currently both \fIcmdName\fR and \fIhiddenCmdName\fR must not contain +namespace qualifiers, or the operation will return \fBTCL_ERROR\fR and +leave an error message in the object result of \fIinterp\fR. +The \fICmdName\fR will be looked up in the global namespace, and not +relative to the current namespace, even if the current namespace is not the +global one. +If a hidden command whose name is \fIhiddenCmdName\fR already +exists, the operation also returns \fBTCL_ERROR\fR and the \fIresult\fR +field in \fIinterp\fR contains an error message. +If the operation succeeds, it returns \fBTCL_OK\fR. +After executing this command, attempts to use \fIcmdName\fR in a call to +\fBTcl_Eval\fR or with the Tcl \fBeval\fR command will fail. +.PP +For a description of the Tcl interface to multiple interpreters, see +\fIinterp(n)\fR. +.SH "SEE ALSO" +interp + +.SH KEYWORDS +alias, command, exposed commands, hidden commands, interpreter, invoke, +master, slave, + diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CrtTimerHdlr.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CrtTimerHdlr.3 new file mode 100644 index 0000000000000000000000000000000000000000..557181850b532e51e82f819b3ad043df7db628c4 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CrtTimerHdlr.3 @@ -0,0 +1,76 @@ +'\" +'\" Copyright (c) 1990 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: CrtTimerHdlr.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_CreateTimerHandler 3 7.5 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_CreateTimerHandler, Tcl_DeleteTimerHandler \- call a procedure at a +given time +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +Tcl_TimerToken +\fBTcl_CreateTimerHandler\fR(\fImilliseconds, proc, clientData\fR) +.sp +\fBTcl_DeleteTimerHandler\fR(\fItoken\fR) +.SH ARGUMENTS +.AS Tcl_TimerToken milliseconds +.AP int milliseconds in +How many milliseconds to wait before invoking \fIproc\fR. +.AP Tcl_TimerProc *proc in +Procedure to invoke after \fImilliseconds\fR have elapsed. +.AP ClientData clientData in +Arbitrary one-word value to pass to \fIproc\fR. +.AP Tcl_TimerToken token in +Token for previously-created timer handler (the return value +from some previous call to \fBTcl_CreateTimerHandler\fR). +.BE + +.SH DESCRIPTION +.PP +\fBTcl_CreateTimerHandler\fR arranges for \fIproc\fR to be +invoked at a time \fImilliseconds\fR milliseconds in the +future. +The callback to \fIproc\fR will be made by \fBTcl_DoOneEvent\fR, +so \fBTcl_CreateTimerHandler\fR is only useful in programs that +dispatch events through \fBTcl_DoOneEvent\fR or through Tcl commands +such as \fBvwait\fR. +The call to \fIproc\fR may not be made at the exact time given by +\fImilliseconds\fR: it will be made at the next opportunity +after that time. For example, if \fBTcl_DoOneEvent\fR isn't +called until long after the time has elapsed, or if there +are other pending events to process before the call to +\fIproc\fR, then the call to \fIproc\fR will be delayed. +.PP +\fIProc\fR should have arguments and return value that match +the type \fBTcl_TimerProc\fR: +.CS +typedef void Tcl_TimerProc(ClientData \fIclientData\fR); +.CE +The \fIclientData\fR parameter to \fIproc\fR is a +copy of the \fIclientData\fR argument given to +\fBTcl_CreateTimerHandler\fR when the callback +was created. Typically, \fIclientData\fR points to a data +structure containing application-specific information about +what to do in \fIproc\fR. +.PP +\fBTcl_DeleteTimerHandler\fR may be called to delete a +previously-created timer handler. It deletes the handler +indicated by \fItoken\fR so that no call to \fIproc\fR +will be made; if that handler no longer exists +(e.g. because the time period has already elapsed and \fIproc\fR +has been invoked then \fBTcl_DeleteTimerHandler\fR does nothing. +The tokens returned by \fBTcl_CreateTimerHandler\fR never have +a value of NULL, so if NULL is passed to \fBTcl_DeleteTimerHandler\fR +then the procedure does nothing. + +.SH KEYWORDS +callback, clock, handler, timer diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CrtTrace.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CrtTrace.3 new file mode 100644 index 0000000000000000000000000000000000000000..cfb2e4ea321408be851909705c5b6805bc948bd7 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/CrtTrace.3 @@ -0,0 +1,106 @@ +'\" +'\" Copyright (c) 1989-1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: CrtTrace.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_CreateTrace 3 "" Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_CreateTrace, Tcl_DeleteTrace \- arrange for command execution to be traced +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +Tcl_Trace +\fBTcl_CreateTrace\fR(\fIinterp, level, proc, clientData\fR) +.sp +\fBTcl_DeleteTrace\fR(\fIinterp, trace\fR) +.SH ARGUMENTS +.AS Tcl_CmdTraceProc (clientData)() +.AP Tcl_Interp *interp in +Interpreter containing command to be traced or untraced. +.AP int level in +Only commands at or below this nesting level will be traced. 1 means +top-level commands only, 2 means top-level commands or those that are +invoked as immediate consequences of executing top-level commands +(procedure bodies, bracketed commands, etc.) and so on. +.AP Tcl_CmdTraceProc *proc in +Procedure to call for each command that's executed. See below for +details on the calling sequence. +.AP ClientData clientData in +Arbitrary one-word value to pass to \fIproc\fR. +.AP Tcl_Trace trace in +Token for trace to be removed (return value from previous call +to \fBTcl_CreateTrace\fR). +.BE + +.SH DESCRIPTION +.PP +\fBTcl_CreateTrace\fR arranges for command tracing. From now on, \fIproc\fR +will be invoked before Tcl calls command procedures to process +commands in \fIinterp\fR. The return value from +\fBTcl_CreateTrace\fR is a token for the trace, +which may be passed to \fBTcl_DeleteTrace\fR to remove the trace. There may +be many traces in effect simultaneously for the same command interpreter. +.PP +\fIProc\fR should have arguments and result that match the +type \fBTcl_CmdTraceProc\fR: +.CS +typedef void Tcl_CmdTraceProc( + ClientData \fIclientData\fR, + Tcl_Interp *\fIinterp\fR, + int \fIlevel\fR, + char *\fIcommand\fR, + Tcl_CmdProc *\fIcmdProc\fR, + ClientData \fIcmdClientData\fR, + int \fIargc\fR, + char *\fIargv\fR[]); +.CE +The \fIclientData\fR and \fIinterp\fR parameters are +copies of the corresponding arguments given to \fBTcl_CreateTrace\fR. +\fIClientData\fR typically points to an application-specific +data structure that describes what to do when \fIproc\fR +is invoked. \fILevel\fR gives the nesting level of the command +(1 for top-level commands passed to \fBTcl_Eval\fR by the application, +2 for the next-level commands passed to \fBTcl_Eval\fR as part of parsing +or interpreting level-1 commands, and so on). \fICommand\fR +points to a string containing the text of the +command, before any argument substitution. +\fICmdProc\fR contains the address of the command procedure that +will be called to process the command (i.e. the \fIproc\fR argument +of some previous call to \fBTcl_CreateCommand\fR) and \fIcmdClientData\fR +contains the associated client data for \fIcmdProc\fR (the \fIclientData\fR +value passed to \fBTcl_CreateCommand\fR). \fIArgc\fR and \fIargv\fR give +the final argument information that will be passed to \fIcmdProc\fR, after +command, variable, and backslash substitution. +\fIProc\fR must not modify the \fIcommand\fR or \fIargv\fR strings. +.PP +Tracing will only occur for commands at nesting level less than +or equal to the \fIlevel\fR parameter (i.e. the \fIlevel\fR +parameter to \fIproc\fR will always be less than or equal to the +\fIlevel\fR parameter to \fBTcl_CreateTrace\fR). +.PP +Calls to \fIproc\fR will be made by the Tcl parser immediately before +it calls the command procedure for the command (\fIcmdProc\fR). This +occurs after argument parsing and substitution, so tracing for +substituted commands occurs before tracing of the commands +containing the substitutions. If there is a syntax error in a +command, or if there is no command procedure associated with a +command name, then no tracing will occur for that command. If a +string passed to Tcl_Eval contains multiple commands (bracketed, or +on different lines) then multiple calls to \fIproc\fR will occur, +one for each command. The \fIcommand\fR string for each of these +trace calls will reflect only a single command, not the entire string +passed to Tcl_Eval. +.PP +\fBTcl_DeleteTrace\fR removes a trace, so that no future calls will be +made to the procedure associated with the trace. After \fBTcl_DeleteTrace\fR +returns, the caller should never again use the \fItrace\fR token. + +.SH KEYWORDS +command, create, delete, interpreter, trace diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/DString.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/DString.3 new file mode 100644 index 0000000000000000000000000000000000000000..9fb01f4c306eef61b123bb092efca1aae77839e0 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/DString.3 @@ -0,0 +1,151 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: DString.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_DString 3 7.4 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_DStringInit, Tcl_DStringAppend, Tcl_DStringAppendElement, Tcl_DStringStartSublist, Tcl_DStringEndSublist, Tcl_DStringLength, Tcl_DStringValue, Tcl_DStringSetLength, Tcl_DStringFree, Tcl_DStringResult, Tcl_DStringGetResult \- manipulate dynamic strings +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +\fBTcl_DStringInit\fR(\fIdsPtr\fR) +.sp +char * +\fBTcl_DStringAppend\fR(\fIdsPtr, string, length\fR) +.sp +char * +\fBTcl_DStringAppendElement\fR(\fIdsPtr, string\fR) +.sp +\fBTcl_DStringStartSublist\fR(\fIdsPtr\fR) +.sp +\fBTcl_DStringEndSublist\fR(\fIdsPtr\fR) +.sp +int +\fBTcl_DStringLength\fR(\fIdsPtr\fR) +.sp +char * +\fBTcl_DStringValue\fR(\fIdsPtr\fR) +.sp +\fBTcl_DStringSetLength\fR(\fIdsPtr, newLength\fR) +.sp +\fBTcl_DStringTrunc\fR(\fIdsPtr, newLength\fR) +.sp +\fBTcl_DStringFree\fR(\fIdsPtr\fR) +.sp +\fBTcl_DStringResult\fR(\fIinterp, dsPtr\fR) +.sp +\fBTcl_DStringGetResult\fR(\fIinterp, dsPtr\fR) +.SH ARGUMENTS +.AS Tcl_DString newLength +.AP Tcl_DString *dsPtr in/out +Pointer to structure that is used to manage a dynamic string. +.AP char *string in +Pointer to characters to add to dynamic string. +.AP int length in +Number of characters from string to add to dynamic string. If -1, +add all characters up to null terminating character. +.AP int newLength in +New length for dynamic string, not including null terminating +character. +.AP Tcl_Interp *interp in/out +Interpreter whose result is to be set from or moved to the +dynamic string. +.BE + +.SH DESCRIPTION +.PP +Dynamic strings provide a mechanism for building up arbitrarily long +strings by gradually appending information. If the dynamic string is +short then there will be no memory allocation overhead; as the string +gets larger, additional space will be allocated as needed. +.PP +\fBTcl_DStringInit\fR initializes a dynamic string to zero length. +The Tcl_DString structure must have been allocated by the caller. +No assumptions are made about the current state of the structure; +anything already in it is discarded. +If the structure has been used previously, \fBTcl_DStringFree\fR should +be called first to free up any memory allocated for the old +string. +.PP +\fBTcl_DStringAppend\fR adds new information to a dynamic string, +allocating more memory for the string if needed. +If \fIlength\fR is less than zero then everything in \fIstring\fR +is appended to the dynamic string; otherwise \fIlength\fR +specifies the number of bytes to append. +\fBTcl_DStringAppend\fR returns a pointer to the characters of +the new string. The string can also be retrieved from the +\fIstring\fR field of the Tcl_DString structure. +.PP +\fBTcl_DStringAppendElement\fR is similar to \fBTcl_DStringAppend\fR +except that it doesn't take a \fIlength\fR argument (it appends +all of \fIstring\fR) and it converts the string to a proper list element +before appending. +\fBTcl_DStringAppendElement\fR adds a separator space before the +new list element unless the new list element is the first in a +list or sub-list (i.e. either the current string is empty, or it +contains the single character ``{'', or the last two characters of +the current string are `` {''). +\fBTcl_DStringAppendElement\fR returns a pointer to the +characters of the new string. +.PP +\fBTcl_DStringStartSublist\fR and \fBTcl_DStringEndSublist\fR can be +used to create nested lists. +To append a list element that is itself a sublist, first +call \fBTcl_DStringStartSublist\fR, then call \fBTcl_DStringAppendElement\fR +for each of the elements in the sublist, then call +\fBTcl_DStringEndSublist\fR to end the sublist. +\fBTcl_DStringStartSublist\fR appends a space character if needed, +followed by an open brace; \fBTcl_DStringEndSublist\fR appends +a close brace. +Lists can be nested to any depth. +.PP +\fBTcl_DStringLength\fR is a macro that returns the current length +of a dynamic string (not including the terminating null character). +\fBTcl_DStringValue\fR is a macro that returns a pointer to the +current contents of a dynamic string. +.PP +.PP +\fBTcl_DStringSetLength\fR changes the length of a dynamic string. +If \fInewLength\fR is less than the string's current length, then +the string is truncated. +If \fInewLength\fR is greater than the string's current length, +then the string will become longer and new space will be allocated +for the string if needed. +However, \fBTcl_DStringSetLength\fR will not initialize the new +space except to provide a terminating null character; it is up to the +caller to fill in the new space. +\fBTcl_DStringSetLength\fR does not free up the string's storage space +even if the string is truncated to zero length, so \fBTcl_DStringFree\fR +will still need to be called. +.PP +\fBTcl_DStringTrunc\fR changes the length of a dynamic string. +This procedure is now deprecated. \fBTcl_DStringSetLength\fR should +be used instead. +.PP +\fBTcl_DStringFree\fR should be called when you're finished using +the string. It frees up any memory that was allocated for the string +and reinitializes the string's value to an empty string. +.PP +\fBTcl_DStringResult\fR sets the result of \fIinterp\fR to the value of +the dynamic string given by \fIdsPtr\fR. It does this by moving +a pointer from \fIdsPtr\fR to the interpreter's result. +This saves the cost of allocating new memory and copying the string. +\fBTcl_DStringResult\fR also reinitializes the dynamic string to +an empty string. +.PP +\fBTcl_DStringGetResult\fR does the opposite of \fBTcl_DStringResult\fR. +It sets the value of \fIdsPtr\fR to the result of \fIinterp\fR and +it clears \fIinterp\fR's result. +If possible it does this by moving a pointer rather than by copying +the string. + +.SH KEYWORDS +append, dynamic string, free, result diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/DetachPids.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/DetachPids.3 new file mode 100644 index 0000000000000000000000000000000000000000..504b2be320cf85f06aaf4c89032fa873582e4ca1 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/DetachPids.3 @@ -0,0 +1,77 @@ +'\" +'\" Copyright (c) 1989-1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: DetachPids.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_DetachPids 3 "" Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_DetachPids, Tcl_ReapDetachedProcs, Tcl_WaitPid \- manage child processes in background +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +\fBTcl_DetachPids\fR(\fInumPids, pidPtr\fR) +.sp +\fBTcl_ReapDetachedProcs\fR() +.sp +Tcl_Pid +\fBTcl_WaitPid\fR(\fIpid, statPtr, options\fR) +.SH ARGUMENTS +.AS int *statusPtr +.AP int numPids in +Number of process ids contained in the array pointed to by \fIpidPtr\fR. +.AP int *pidPtr in +Address of array containing \fInumPids\fR process ids. +.AP Tcl_Pid pid in +The id of the process (pipe) to wait for. +.AP int* statPtr out +The result of waiting on a process (pipe). Either 0 or ECHILD. +.AP int options +The options controlling the wait. WNOHANG specifies not to wait when +checking the process. +.BE +.SH DESCRIPTION +.PP +\fBTcl_DetachPids\fR and \fBTcl_ReapDetachedProcs\fR provide a +mechanism for managing subprocesses that are running in background. +These procedures are needed because the parent of a process must +eventually invoke the \fBwaitpid\fR kernel call (or one of a few other +similar kernel calls) to wait for the child to exit. Until the +parent waits for the child, the child's state cannot be completely +reclaimed by the system. If a parent continually creates children +and doesn't wait on them, the system's process table will eventually +overflow, even if all the children have exited. +.PP +\fBTcl_DetachPids\fR may be called to ask Tcl to take responsibility +for one or more processes whose process ids are contained in the +\fIpidPtr\fR array passed as argument. The caller presumably +has started these processes running in background and doesn't +want to have to deal with them again. +.PP +\fBTcl_ReapDetachedProcs\fR invokes the \fBwaitpid\fR kernel call +on each of the background processes so that its state can be cleaned +up if it has exited. If the process hasn't exited yet, +\fBTcl_ReapDetachedProcs\fR doesn't wait for it to exit; it will check again +the next time it is invoked. +Tcl automatically calls \fBTcl_ReapDetachedProcs\fR each time the +\fBexec\fR command is executed, so in most cases it isn't necessary +for any code outside of Tcl to invoke \fBTcl_ReapDetachedProcs\fR. +However, if you call \fBTcl_DetachPids\fR in situations where the +\fBexec\fR command may never get executed, you may wish to call +\fBTcl_ReapDetachedProcs\fR from time to time so that background +processes can be cleaned up. +.PP +\fBTcl_WaitPid\fR is a thin wrapper around the facilities provided by +the operating system to wait on the end of a spawned process and to +check a whether spawned process is still running. It is used by +\fBTcl_ReapDetachedProcs\fR and the channel system to portably access +the operating system. + +.SH KEYWORDS +background, child, detach, process, wait diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/DoOneEvent.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/DoOneEvent.3 new file mode 100644 index 0000000000000000000000000000000000000000..4c3b3205e9a10e6fc4977481c5e3d99403b05c68 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/DoOneEvent.3 @@ -0,0 +1,108 @@ +'\" +'\" Copyright (c) 1990-1992 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: DoOneEvent.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_DoOneEvent 3 7.5 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_DoOneEvent \- wait for events and invoke event handlers +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +int +\fBTcl_DoOneEvent\fR(\fIflags\fR) +.SH ARGUMENTS +.AS int flags +.AP int flags in +This parameter is normally zero. It may be an OR-ed combination +of any of the following flag bits: +TCL_WINDOW_EVENTS, +TCL_FILE_EVENTS, TCL_TIMER_EVENTS, TCL_IDLE_EVENTS, TCL_ALL_EVENTS, or +TCL_DONT_WAIT. +.BE + +.SH DESCRIPTION +.PP +This procedure is the entry point to Tcl's event loop; it is responsible for +waiting for events and dispatching event handlers created with +procedures such as \fBTk_CreateEventHandler\fR, \fBTcl_CreateFileHandler\fR, +\fBTcl_CreateTimerHandler\fR, and \fBTcl_DoWhenIdle\fR. +\fBTcl_DoOneEvent\fR checks to see if +events are already present on the Tcl event queue; if so, +it calls the handler(s) for the first (oldest) event, removes it from +the queue, and returns. +If there are no events ready to be handled, then \fBTcl_DoOneEvent\fR +checks for new events from all possible sources. +If any are found, it puts all of them on Tcl's event queue, calls +handlers for the first event on the queue, and returns. +If no events are found, \fBTcl_DoOneEvent\fR checks for \fBTcl_DoWhenIdle\fR +callbacks; if any are found, it invokes all of them and returns. +Finally, if no events or idle callbacks have been found, then +\fBTcl_DoOneEvent\fR sleeps until an event occurs; then it adds any +new events to the Tcl event queue, calls handlers for the first event, +and returns. +The normal return value is 1 to signify that some event +was processed (see below for other alternatives). +.PP +If the \fIflags\fR argument to \fBTcl_DoOneEvent\fR is non-zero, +it restricts the kinds of events that will be processed by +\fBTcl_DoOneEvent\fR. +\fIFlags\fR may be an OR-ed combination of any of the following bits: +.TP 27 +\fBTCL_WINDOW_EVENTS\fR \- +Process window system events. +.TP 27 +\fBTCL_FILE_EVENTS\fR \- +Process file events. +.TP 27 +\fBTCL_TIMER_EVENTS\fR \- +Process timer events. +.TP 27 +\fBTCL_IDLE_EVENTS\fR \- +Process idle callbacks. +.TP 27 +\fBTCL_ALL_EVENTS\fR \- +Process all kinds of events: equivalent to OR-ing together all of the +above flags or specifying none of them. +.TP 27 +\fBTCL_DONT_WAIT\fR \- +Don't sleep: process only events that are ready at the time of the +call. +.LP +If any of the flags \fBTCL_WINDOW_EVENTS\fR, \fBTCL_FILE_EVENTS\fR, +\fBTCL_TIMER_EVENTS\fR, or \fBTCL_IDLE_EVENTS\fR is set, then the only +events that will be considered are those for which flags are set. +Setting none of these flags is equivalent to the value +\fBTCL_ALL_EVENTS\fR, which causes all event types to be processed. +If an application has defined additional event sources with +\fBTcl_CreateEventSource\fR, then additional \fIflag\fR values +may also be valid, depending on those event sources. +.PP +The \fBTCL_DONT_WAIT\fR flag causes \fBTcl_DoOneEvent\fR not to put +the process to sleep: it will check for events but if none are found +then it returns immediately with a return value of 0 to indicate +that no work was done. +\fBTcl_DoOneEvent\fR will also return 0 without doing anything if +the only alternative is to block forever (this can happen, for example, +if \fIflags\fR is \fBTCL_IDLE_EVENTS\fR and there are no +\fBTcl_DoWhenIdle\fR callbacks pending, or if no event handlers or +timer handlers exist). +.PP +\fBTcl_DoOneEvent\fR may be invoked recursively. For example, +it is possible to invoke \fBTcl_DoOneEvent\fR recursively +from a handler called by \fBTcl_DoOneEvent\fR. This sort +of operation is useful in some modal situations, such +as when a +notification dialog has been popped up and an application wishes to +wait for the user to click a button in the dialog before +doing anything else. + +.SH KEYWORDS +callback, event, handler, idle, timer diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/DoWhenIdle.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/DoWhenIdle.3 new file mode 100644 index 0000000000000000000000000000000000000000..76c9e17008906cb1b74f255a8113593721b943cc --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/DoWhenIdle.3 @@ -0,0 +1,86 @@ +'\" +'\" Copyright (c) 1990 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: DoWhenIdle.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_DoWhenIdle 3 7.5 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_DoWhenIdle, Tcl_CancelIdleCall \- invoke a procedure when there are no pending events +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +\fBTcl_DoWhenIdle\fR(\fIproc, clientData\fR) +.sp +\fBTcl_CancelIdleCall\fR(\fIproc, clientData\fR) +.SH ARGUMENTS +.AS Tcl_IdleProc clientData +.AP Tcl_IdleProc *proc in +Procedure to invoke. +.AP ClientData clientData in +Arbitrary one-word value to pass to \fIproc\fR. +.BE + +.SH DESCRIPTION +.PP +\fBTcl_DoWhenIdle\fR arranges for \fIproc\fR to be invoked +when the application becomes idle. The application is +considered to be idle when \fBTcl_DoOneEvent\fR has been +called, couldn't find any events to handle, and is about +to go to sleep waiting for an event to occur. At this +point all pending \fBTcl_DoWhenIdle\fR handlers are +invoked. For each call to \fBTcl_DoWhenIdle\fR there will +be a single call to \fIproc\fR; after \fIproc\fR is +invoked the handler is automatically removed. +\fBTcl_DoWhenIdle\fR is only usable in programs that +use \fBTcl_DoOneEvent\fR to dispatch events. +.PP +\fIProc\fR should have arguments and result that match the +type \fBTcl_IdleProc\fR: +.CS +typedef void Tcl_IdleProc(ClientData \fIclientData\fR); +.CE +The \fIclientData\fR parameter to \fIproc\fR is a copy of the \fIclientData\fR +argument given to \fBTcl_DoWhenIdle\fR. Typically, \fIclientData\fR +points to a data structure containing application-specific information about +what \fIproc\fR should do. +.PP +\fBTcl_CancelIdleCall\fR +may be used to cancel one or more previous +calls to \fBTcl_DoWhenIdle\fR: if there is a \fBTcl_DoWhenIdle\fR +handler registered for \fIproc\fR and \fIclientData\fR, then it +is removed without invoking it. If there is more than one +handler on the idle list that refers to \fIproc\fR and \fIclientData\fR, +all of the handlers are removed. If no existing handlers match +\fIproc\fR and \fIclientData\fR then nothing happens. +.PP +\fBTcl_DoWhenIdle\fR is most useful in situations where +(a) a piece of work will have to be done but (b) it's +possible that something will happen in the near future +that will change what has to be done or require something +different to be done. \fBTcl_DoWhenIdle\fR allows the +actual work to be deferred until all pending events have +been processed. At this point the exact work to be done +will presumably be known and it can be done exactly once. +.PP +For example, \fBTcl_DoWhenIdle\fR might be used by an editor +to defer display updates until all pending commands have +been processed. Without this feature, redundant redisplays +might occur in some situations, such as the processing of +a command file. +.SH BUGS +.PP +At present it is not safe for an idle callback to reschedule itself +continuously. This will interact badly with certain features of Tk +that attempt to wait for all idle callbacks to complete. If you would +like for an idle callback to reschedule itself continuously, it is +better to use a timer handler with a zero timeout period. + +.SH KEYWORDS +callback, defer, idle callback diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/DoubleObj.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/DoubleObj.3 new file mode 100644 index 0000000000000000000000000000000000000000..a6adb12f9a3fe6d36d1e3a310f8c6a6f89add228 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/DoubleObj.3 @@ -0,0 +1,79 @@ +'\" +'\" Copyright (c) 1996-1997 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: DoubleObj.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_DoubleObj 3 8.0 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_NewDoubleObj, Tcl_SetDoubleObj, Tcl_GetDoubleFromObj \- manipulate Tcl objects as floating-point values +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +Tcl_Obj * +\fBTcl_NewDoubleObj\fR(\fIdoubleValue\fR) +.sp +\fBTcl_SetDoubleObj\fR(\fIobjPtr, doubleValue\fR) +.sp +int +\fBTcl_GetDoubleFromObj\fR(\fIinterp, objPtr, doublePtr\fR) +.SH ARGUMENTS +.AS Tcl_Interp doubleValue in/out +.AP double doubleValue in +A double-precision floating point value used to initialize or set a double object. +.AP Tcl_Obj *objPtr in/out +For \fBTcl_SetDoubleObj\fR, this points to the object to be converted +to double type. +For \fBTcl_GetDoubleFromObj\fR, this refers to the object +from which to get a double value; +if \fIobjPtr\fR does not already point to a double object, +an attempt will be made to convert it to one. +.AP Tcl_Interp *interp in/out +If an error occurs during conversion, +an error message is left in the interpreter's result object +unless \fIinterp\fR is NULL. +.AP double *doublePtr out +Points to place to store the double value +obtained from \fIobjPtr\fR. +.BE + +.SH DESCRIPTION +.PP +These procedures are used to create, modify, and read +double Tcl objects from C code. +\fBTcl_NewDoubleObj\fR and \fBTcl_SetDoubleObj\fR +will create a new object of double type +or modify an existing object to have double type. +Both of these procedures set the object to have the +double-precision floating point value given by \fIdoubleValue\fR; +\fBTcl_NewDoubleObj\fR returns a pointer to a newly created object +with reference count zero. +Both procedures set the object's type to be double +and assign the double value to the object's internal representation +\fIdoubleValue\fR member. +\fBTcl_SetDoubleObj\fR invalidates any old string representation +and, if the object is not already a double object, +frees any old internal representation. +.PP +\fBTcl_GetDoubleFromObj\fR attempts to return a double value +from the Tcl object \fIobjPtr\fR. +If the object is not already a double object, +it will attempt to convert it to one. +If an error occurs during conversion, it returns \fBTCL_ERROR\fR +and leaves an error message in the interpreter's result object +unless \fIinterp\fR is NULL. +Otherwise, it returns \fBTCL_OK\fR and stores the double value +in the address given by \fIdoublePtr\fR. +If the object is not already a double object, +the conversion will free any old internal representation. + +.SH "SEE ALSO" +Tcl_NewObj, Tcl_DecrRefCount, Tcl_IncrRefCount, Tcl_GetObjResult + +.SH KEYWORDS +double, double object, double type, internal representation, object, object type, string representation diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/DumpActiveMemory.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/DumpActiveMemory.3 new file mode 100644 index 0000000000000000000000000000000000000000..eb59436bec2c182e620aa00b69878b458d75017e --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/DumpActiveMemory.3 @@ -0,0 +1,68 @@ +'\" +'\" Copyright (c) 1992-1999 Karl Lehenbauer and Mark Diekhans. +'\" Copyright (c) 2000 by Scriptics Corporation. +'\" All rights reserved. +'\" +'\" RCS: @(#) $Id: DumpActiveMemory.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH "Tcl_DumpActiveMemory" 3 8.1 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_DumpActiveMemory, Tcl_InitMemory, Tcl_ValidateAllMemory \- Validated memory allocation interface. +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +int +\fBTcl_DumpActiveMemory\fR(\fIfileName\fR) +.sp +void +\fBTcl_InitMemory\fR(\fIinterp\fR) +.sp +void +\fBTcl_ValidateAllMemory\fR(\fIfileName, line\fR) + +.SH ARGUMENTS +.AP Tcl_Interp *interp in +Tcl interpreter in which to add commands. +.AP char *fileName in +For \fBTcl_DumpActiveMemory\fR, name of the file to which memory +information will be written. For \fBTcl_ValidateAllMemory\fR, name of +the file from which the call is being made (normally \fB__FILE__\fR). +.AP int line in +Line number at which the call to \fBTcl_ValidateAllMemory\fR is made +(normally \fB__LINE__\fR). +.BE + +.SH DESCRIPTION +These functions provide access to Tcl memory debugging information. +They are only available when Tcl has been compiled with +\fBTCL_MEM_DEBUG\fR defined at compile-time. +.PP +\fBTcl_DumpActiveMemory\fR will output a list of all currently +allocated memory to the specified file. The information output for +each allocated block of memory is: starting and ending addresses +(excluding guard zone), size, source file where \fBckalloc\fR was +called to allocate the block and line number in that file. It is +especially useful to call \fBTcl_DumpActiveMemory\fR after the Tcl +interpreter has been deleted. +.PP +\fBTcl_InitMemory\fR adds the Tcl \fBmemory\fR command to the +interpreter given by \fIinterp\fR. It is called by \fBTcl_Main\fR +when Tcl has been compiled with \fBTCL_MEM_DEBUG\fR defined. +.PP +\fBTcl_ValidateAllMemory\fR forces a validation of the guard zones of +all currently allocated blocks of memory. Normally validation of a +block occurs when its freed, unless full validation is enabled, in +which case validation of all blocks occurs when \fBckalloc\fR and +\fBckfree\fR are called. This function forces the validation to occur +at any point. + +.SH "SEE ALSO" +TCL_MEM_DEBUG, memory + +.SH KEYWORDS +memory, debug + + diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Encoding.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Encoding.3 new file mode 100644 index 0000000000000000000000000000000000000000..fb897752101f823ac2d935af5cf1c3965028d0c5 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Encoding.3 @@ -0,0 +1,523 @@ +'\" +'\" Copyright (c) 1997-1998 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: Encoding.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_GetEncoding 3 "8.1" Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_GetEncoding, Tcl_FreeEncoding, Tcl_ExternalToUtfDString, Tcl_ExternalToUtf, Tcl_UtfToExternalDString, Tcl_UtfToExternal, Tcl_WinTCharToUtf, Tcl_WinUtfToTChar, Tcl_GetEncodingName, Tcl_SetSystemEncoding, Tcl_GetEncodingNames, Tcl_CreateEncoding, Tcl_GetDefaultEncodingDir, Tcl_SetDefaultEncodingDir \- procedures for creating and using encodings. +.SH SYNOPSIS +.nf +\fB#include \fR +\fB#include \fR \fI/* Tcl_Win* functions only */\fR +.sp +Tcl_Encoding +\fBTcl_GetEncoding\fR(\fIinterp, name\fR) +.sp +void +\fBTcl_FreeEncoding\fR(\fIencoding\fR) +.sp +char * +\fBTcl_ExternalToUtfDString\fR(\fIencoding, src, srcLen, dstPtr\fR) +.sp +int +\fBTcl_ExternalToUtf\fR(\fIinterp, encoding, src, srcLen, flags, statePtr, dst, dstLen, srcReadPtr, dstWrotePtr, + dstCharsPtr\fR) +.sp +char * +\fBTcl_UtfToExternalDString\fR(\fIencoding, src, srcLen, dstPtr\fR) +.sp +int +\fBTcl_UtfToExternal\fR(\fIinterp, encoding, src, srcLen, flags, statePtr, dst, dstLen, srcReadPtr, dstWrotePtr, + dstCharsPtr\fR) +.sp +char * +\fBTcl_WinTCharToUtf\fR(\fItsrc, srcLen, dstPtr\fR) +.sp +TCHAR * +\fBTcl_WinUtfToTChar\fR(\fIsrc, srcLen, dstPtr\fR) +.sp +char * +\fBTcl_GetEncodingName\fR(\fIencoding\fR) +.sp +int +\fBTcl_SetSystemEncoding\fR(\fIinterp, name\fR) +.sp +void +\fBTcl_GetEncodingNames\fR(\fIinterp\fR) +.sp +Tcl_Encoding +\fBTcl_CreateEncoding\fR(\fItypePtr\fR) +.sp +char * +\fBTcl_GetDefaultEncodingDir\fR(\fIvoid\fR) +.sp +void +\fBTcl_SetDefaultEncodingDir\fR(\fIpath\fR) + + +.SH ARGUMENTS +.AS Tcl_EncodingState *dstWrotePtr +.AP Tcl_Interp *interp in +Interpreter to use for error reporting, or NULL if no error reporting is +desired. +.AP "CONST char" *name in +Name of encoding to load. +.AP Tcl_Encoding encoding in +The encoding to query, free, or use for converting text. If \fIencoding\fR is +NULL, the current system encoding is used. +.AP "CONST char" *src in +For the \fBTcl_ExternalToUtf\fR functions, an array of bytes in the +specified encoding that are to be converted to UTF-8. For the +\fBTcl_UtfToExternal\fR and \fBTcl_WinUtfToTChar\fR functions, an array of +UTF-8 characters to be converted to the specified encoding. +.AP "CONST TCHAR" *tsrc in +An array of Windows TCHAR characters to convert to UTF-8. +.AP int srcLen in +Length of \fIsrc\fR or \fItsrc\fR in bytes. If the length is negative, the +encoding-specific length of the string is used. +.AP Tcl_DString *dstPtr out +Pointer to an uninitialized or free \fBTcl_DString\fR in which the converted +result will be stored. +.AP int flags in +Various flag bits OR-ed together. +TCL_ENCODING_START signifies that the +source buffer is the first block in a (potentially multi-block) input +stream, telling the conversion routine to reset to an initial state and +perform any initialization that needs to occur before the first byte is +converted. TCL_ENCODING_END signifies that the source buffer is the last +block in a (potentially multi-block) input stream, telling the conversion +routine to perform any finalization that needs to occur after the last +byte is converted and then to reset to an initial state. +TCL_ENCODING_STOPONERROR signifies that the conversion routine should +return immediately upon reading a source character that doesn't exist in +the target encoding; otherwise a default fallback character will +automatically be substituted. +.AP Tcl_EncodingState *statePtr in/out +Used when converting a (generally long or indefinite length) byte stream +in a piece by piece fashion. The conversion routine stores its current +state in \fI*statePtr\fR after \fIsrc\fR (the buffer containing the +current piece) has been converted; that state information must be passed +back when converting the next piece of the stream so the conversion +routine knows what state it was in when it left off at the end of the +last piece. May be NULL, in which case the value specified for \fIflags\fR +is ignored and the source buffer is assumed to contain the complete string to +convert. +.AP char *dst out +Buffer in which the converted result will be stored. No more than +\fIdstLen\fR bytes will be stored in \fIdst\fR. +.AP int dstLen in +The maximum length of the output buffer \fIdst\fR in bytes. +.AP int *srcReadPtr out +Filled with the number of bytes from \fIsrc\fR that were actually +converted. This may be less than the original source length if there was +a problem converting some source characters. May be NULL. +.AP int *dstWrotePtr out +Filled with the number of bytes that were actually stored in the output +buffer as a result of the conversion. May be NULL. +.AP int *dstCharsPtr out +Filled with the number of characters that correspond to the number of bytes +stored in the output buffer. May be NULL. +.AP Tcl_EncodingType *typePtr in +Structure that defines a new type of encoding. +.AP char *path in +A path to the location of the encoding file. +.BE +.SH INTRODUCTION +.PP +These routines convert between Tcl's internal character representation, +UTF-8, and character representations used by various operating systems or +file systems, such as Unicode, ASCII, or Shift-JIS. When operating on +strings, such as such as obtaining the names of files or displaying +characters using international fonts, the strings must be translated into +one or possibly multiple formats that the various system calls can use. For +instance, on a Japanese Unix workstation, a user might obtain a filename +represented in the EUC-JP file encoding and then translate the characters to +the jisx0208 font encoding in order to display the filename in a Tk widget. +The purpose of the encoding package is to help bridge the translation gap. +UTF-8 provides an intermediate staging ground for all the various +encodings. In the example above, text would be translated into UTF-8 from +whatever file encoding the operating system is using. Then it would be +translated from UTF-8 into whatever font encoding the display routines +require. +.PP +Some basic encodings are compiled into Tcl. Others can be defined by the +user or dynamically loaded from encoding files in a +platform-independent manner. +.SH DESCRIPTION +.PP +\fBTcl_GetEncoding\fR finds an encoding given its \fIname\fR. The name may +refer to a builtin Tcl encoding, a user-defined encoding registered by +calling \fBTcl_CreateEncoding\fR, or a dynamically-loadable encoding +file. The return value is a token that represents the encoding and can be +used in subsequent calls to procedures such as \fBTcl_GetEncodingName\fR, +\fBTcl_FreeEncoding\fR, and \fBTcl_UtfToExternal\fR. If the name did not +refer to any known or loadable encoding, NULL is returned and an error +message is returned in \fIinterp\fR. +.PP +The encoding package maintains a database of all encodings currently in use. +The first time \fIname\fR is seen, \fBTcl_GetEncoding\fR returns an +encoding with a reference count of 1. If the same \fIname\fR is requested +further times, then the reference count for that encoding is incremented +without the overhead of allocating a new encoding and all its associated +data structures. +.PP +When an \fIencoding\fR is no longer needed, \fBTcl_FreeEncoding\fR +should be called to release it. When an \fIencoding\fR is no longer in use +anywhere (i.e., it has been freed as many times as it has been gotten) +\fBTcl_FreeEncoding\fR will release all storage the encoding was using +and delete it from the database. +.PP +\fBTcl_ExternalToUtfDString\fR converts a source buffer \fIsrc\fR from the +specified \fIencoding\fR into UTF-8. The converted bytes are stored in +\fIdstPtr\fR, which is then NULL terminated. The caller should eventually +call \fBTcl_DStringFree\fR to free any information stored in \fIdstPtr\fR. +When converting, if any of the characters in the source buffer cannot be +represented in the target encoding, a default fallback character will be +used. The return value is a pointer to the value stored in the DString. +.PP +\fBTcl_ExternalToUtf\fR converts a source buffer \fIsrc\fR from the specified +\fIencoding\fR into UTF-8. Up to \fIsrcLen\fR bytes are converted from the +source buffer and up to \fIdstLen\fR converted bytes are stored in \fIdst\fR. +In all cases, \fI*srcReadPtr\fR is filled with the number of bytes that were +successfully converted from \fIsrc\fR and \fI*dstWrotePtr\fR is filled with +the corresponding number of bytes that were stored in \fIdst\fR. The return +value is one of the following: +.RS +.IP \fBTCL_OK\fR 29 +All bytes of \fIsrc\fR were converted. +.IP \fBTCL_CONVERT_NOSPACE\fR 29 +The destination buffer was not large enough for all of the converted data; as +many characters as could fit were converted though. +.IP \fBTCL_CONVERT_MULTIBYTE\fR 29 +The last fews bytes in the source buffer were the beginning of a multibyte +sequence, but more bytes were needed to complete this sequence. A +subsequent call to the conversion routine should pass a buffer containing +the unconverted bytes that remained in \fIsrc\fR plus some further bytes +from the source stream to properly convert the formerly split-up multibyte +sequence. +.IP \fBTCL_CONVERT_SYNTAX\fR 29 +The source buffer contained an invalid character sequence. This may occur +if the input stream has been damaged or if the input encoding method was +misidentified. +.IP \fBTCL_CONVERT_UNKNOWN\fR 29 +The source buffer contained a character that could not be represented in +the target encoding and TCL_ENCODING_STOPONERROR was specified. +.RE +.LP +\fBTcl_UtfToExternalDString\fR converts a source buffer \fIsrc\fR from UTF-8 +into the specified \fIencoding\fR. The converted bytes are stored in +\fIdstPtr\fR, which is then terminated with the appropriate encoding-specific +NULL. The caller should eventually call \fBTcl_DStringFree\fR to free any +information stored in \fIdstPtr\fR. When converting, if any of the +characters in the source buffer cannot be represented in the target +encoding, a default fallback character will be used. The return value is +a pointer to the value stored in the DString. +.PP +\fBTcl_UtfToExternal\fR converts a source buffer \fIsrc\fR from UTF-8 into +the specified \fIencoding\fR. Up to \fIsrcLen\fR bytes are converted from +the source buffer and up to \fIdstLen\fR converted bytes are stored in +\fIdst\fR. In all cases, \fI*srcReadPtr\fR is filled with the number of +bytes that were successfully converted from \fIsrc\fR and \fI*dstWrotePtr\fR +is filled with the corresponding number of bytes that were stored in +\fIdst\fR. The return values are the same as the return values for +\fBTcl_ExternalToUtf\fR. +.PP +\fBTcl_WinUtfToTChar\fR and \fBTcl_WinTCharToUtf\fR are +Windows-only convenience +functions for converting between UTF-8 and Windows strings. On Windows 95 +(as with the Macintosh and Unix operating systems), +all strings exchanged between Tcl and the operating system are "char" +based. On Windows NT, some strings exchanged between Tcl and the +operating system are "char" oriented while others are in Unicode. By +convention, in Windows a TCHAR is a character in the ANSI code page +on Windows 95 and a Unicode character on Windows NT. +.PP +If you planned to use the same "char" based interfaces on both Windows +95 and Windows NT, you could use \fBTcl_UtfToExternal\fR and +\fBTcl_ExternalToUtf\fR (or their \fBTcl_DString\fR equivalents) with an +encoding of NULL (the current system encoding). On the other hand, +if you planned to use the Unicode interface when running on Windows NT +and the "char" interfaces when running on Windows 95, you would have +to perform the following type of test over and over in your program +(as represented in psuedo-code): +.CS +if (running NT) { + encoding <- Tcl_GetEncoding("unicode"); + nativeBuffer <- Tcl_UtfToExternal(encoding, utfBuffer); + Tcl_FreeEncoding(encoding); +} else { + nativeBuffer <- Tcl_UtfToExternal(NULL, utfBuffer); +.CE +\fBTcl_WinUtfToTChar\fR and \fBTcl_WinTCharToUtf\fR automatically +handle this test and use the proper encoding based on the current +operating system. \fBTcl_WinUtfToTChar\fR returns a pointer to +a TCHAR string, and \fBTcl_WinTCharToUtf\fR expects a TCHAR string +pointer as the \fIsrc\fR string. Otherwise, these functions +behave identically to \fBTcl_UtfToExternalDString\fR and +\fBTcl_ExternalToUtfDString\fR. +.PP +\fBTcl_GetEncodingName\fR is roughly the inverse of \fBTcl_GetEncoding\fR. +Given an \fIencoding\fR, the return value is the \fIname\fR argument that +was used to create the encoding. The string returned by +\fBTcl_GetEncodingName\fR is only guaranteed to persist until the +\fIencoding\fR is deleted. The caller must not modify this string. +.PP +\fBTcl_SetSystemEncoding\fR sets the default encoding that should be used +whenever the user passes a NULL value for the \fIencoding\fR argument to +any of the other encoding functions. If \fIname\fR is NULL, the system +encoding is reset to the default system encoding, \fBbinary\fR. If the +name did not refer to any known or loadable encoding, TCL_ERROR is +returned and an error message is left in \fIinterp\fR. Otherwise, this +procedure increments the reference count of the new system encoding, +decrements the reference count of the old system encoding, and returns +TCL_OK. +.PP +\fBTcl_GetEncodingNames\fR sets the \fIinterp\fR result to a list +consisting of the names of all the encodings that are currently defined +or can be dynamically loaded, searching the encoding path specified by +\fBTcl_SetDefaultEncodingDir\fR. This procedure does not ensure that the +dynamically-loadable encoding files contain valid data, but merely that they +exist. +.PP +\fBTcl_CreateEncoding\fR defines a new encoding and registers the C +procedures that are called back to convert between the encoding and +UTF-8. Encodings created by \fBTcl_CreateEncoding\fR are thereafter +visible in the database used by \fBTcl_GetEncoding\fR. Just as with the +\fBTcl_GetEncoding\fR procedure, the return value is a token that +represents the encoding and can be used in subsequent calls to other +encoding functions. \fBTcl_CreateEncoding\fR returns an encoding with a +reference count of 1. If an encoding with the specified \fIname\fR +already exists, then its entry in the database is replaced with the new +encoding; the token for the old encoding will remain valid and continue +to behave as before, but users of the new token will now call the new +encoding procedures. +.PP +The \fItypePtr\fR argument to \fBTcl_CreateEncoding\fR contains information +about the name of the encoding and the procedures that will be called to +convert between this encoding and UTF-8. It is defined as follows: +.PP +.CS +typedef struct Tcl_EncodingType { + CONST char *\fIencodingName\fR; + Tcl_EncodingConvertProc *\fItoUtfProc\fR; + Tcl_EncodingConvertProc *\fIfromUtfProc\fR; + Tcl_EncodingFreeProc *\fIfreeProc\fR; + ClientData \fIclientData\fR; + int \fInullSize\fR; +} Tcl_EncodingType; +.CE +.PP +The \fIencodingName\fR provides a string name for the encoding, by +which it can be referred in other procedures such as +\fBTcl_GetEncoding\fR. The \fItoUtfProc\fR refers to a callback +procedure to invoke to convert text from this encoding into UTF-8. +The \fIfromUtfProc\fR refers to a callback procedure to invoke to +convert text from UTF-8 into this encoding. The \fIfreeProc\fR refers +to a callback procedure to invoke when this encoding is deleted. The +\fIfreeProc\fR field may be NULL. The \fIclientData\fR contains an +arbitrary one-word value passed to \fItoUtfProc\fR, \fIfromUtfProc\fR, +and \fIfreeProc\fR whenever they are called. Typically, this is a +pointer to a data structure containing encoding-specific information +that can be used by the callback procedures. For instance, two very +similar encodings such as \fBascii\fR and \fBmacRoman\fR may use the +same callback procedure, but use different values of \fIclientData\fR +to control its behavior. The \fInullSize\fR specifies the number of +zero bytes that signify end-of-string in this encoding. It must be +\fB1\fR (for single-byte or multi-byte encodings like ASCII or +Shift-JIS) or \fB2\fR (for double-byte encodings like Unicode). +Constant-sized encodings with 3 or more bytes per character (such as +CNS11643) are not accepted. +.PP +The callback procedures \fItoUtfProc\fR and \fIfromUtfProc\fR should match the +type \fBTcl_EncodingConvertProc\fR: +.PP +.CS +typedef int Tcl_EncodingConvertProc( + ClientData \fIclientData\fR, + CONST char *\fIsrc\fR, + int \fIsrcLen\fR, + int \fIflags\fR, + Tcl_Encoding *\fIstatePtr\fR, + char *\fIdst\fR, + int \fIdstLen\fR, + int *\fIsrcReadPtr\fR, + int *\fIdstWrotePtr\fR, + int *\fIdstCharsPtr\fR); +.CE +.PP +The \fItoUtfProc\fR and \fIfromUtfProc\fR procedures are called by the +\fBTcl_ExternalToUtf\fR or \fBTcl_UtfToExternal\fR family of functions to +perform the actual conversion. The \fIclientData\fR parameter to these +procedures is the same as the \fIclientData\fR field specified to +\fBTcl_CreateEncoding\fR when the encoding was created. The remaining +arguments to the callback procedures are the same as the arguments, +documented at the top, to \fBTcl_ExternalToUtf\fR or +\fBTcl_UtfToExternal\fR, with the following exceptions. If the +\fIsrcLen\fR argument to one of those high-level functions is negative, +the value passed to the callback procedure will be the appropriate +encoding-specific string length of \fIsrc\fR. If any of the \fIsrcReadPtr\fR, +\fIdstWrotePtr\fR, or \fIdstCharsPtr\fR arguments to one of the high-level +functions is NULL, the corresponding value passed to the callback +procedure will be a non-NULL location. +.PP +The callback procedure \fIfreeProc\fR, if non-NULL, should match the type +\fBTcl_EncodingFreeProc\fR: +.CS +typedef void Tcl_EncodingFreeProc( + ClientData \fIclientData\fR); +.CE +.PP +This \fIfreeProc\fR function is called when the encoding is deleted. The +\fIclientData\fR parameter is the same as the \fIclientData\fR field +specified to \fBTcl_CreateEncoding\fR when the encoding was created. +.PP + +\fBTcl_GetDefaultEncodingDir\fR and \fBTcl_SetDefaultEncodingDir\fR +access and set the directory to use when locating the default encoding +files. If this value is not NULL, the \fBTclpInitLibraryPath\fR routine +appends the path to the head of the search path, and uses this path as +the first place to look into when trying to locate the encoding file. + +.SH "ENCODING FILES" +Space would prohibit precompiling into Tcl every possible encoding +algorithm, so many encodings are stored on disk as dynamically-loadable +encoding files. This behavior also allows the user to create additional +encoding files that can be loaded using the same mechanism. These +encoding files contain information about the tables and/or escape +sequences used to map between an external encoding and Unicode. The +external encoding may consist of single-byte, multi-byte, or double-byte +characters. +.PP +Each dynamically-loadable encoding is represented as a text file. The +initial line of the file, beginning with a ``#'' symbol, is a comment +that provides a human-readable description of the file. The next line +identifies the type of encoding file. It can be one of the following +letters: +.IP "[1] \fBS\fR" +A single-byte encoding, where one character is always one byte long in the +encoding. An example is \fBiso8859-1\fR, used by many European languages. +.IP "[2] \fBD\fR" +A double-byte encoding, where one character is always two bytes long in the +encoding. An example is \fBbig5\fR, used for Chinese text. +.IP "[3] \fBM\fR" +A multi-byte encoding, where one character may be either one or two bytes long. +Certain bytes are a lead bytes, indicating that another byte must follow +and that together the two bytes represent one character. Other bytes are not +lead bytes and represent themselves. An example is \fBshiftjis\fR, used by +many Japanese computers. +.IP "[4] \fBE\fR" +An escape-sequence encoding, specifying that certain sequences of bytes +do not represent characters, but commands that describe how following bytes +should be interpreted. +.PP +The rest of the lines in the file depend on the type. +.PP +Cases [1], [2], and [3] are collectively referred to as table-based encoding +files. The lines in a table-based encoding file are in the same +format as this example taken from the \fBshiftjis\fR encoding (this is not +the complete file): +.CS +# Encoding file: shiftjis, multi-byte +M +003F 0 40 +00 +0000000100020003000400050006000700080009000A000B000C000D000E000F +0010001100120013001400150016001700180019001A001B001C001D001E001F +0020002100220023002400250026002700280029002A002B002C002D002E002F +0030003100320033003400350036003700380039003A003B003C003D003E003F +0040004100420043004400450046004700480049004A004B004C004D004E004F +0050005100520053005400550056005700580059005A005B005C005D005E005F +0060006100620063006400650066006700680069006A006B006C006D006E006F +0070007100720073007400750076007700780079007A007B007C007D203E007F +0080000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000FF61FF62FF63FF64FF65FF66FF67FF68FF69FF6AFF6BFF6CFF6DFF6EFF6F +FF70FF71FF72FF73FF74FF75FF76FF77FF78FF79FF7AFF7BFF7CFF7DFF7EFF7F +FF80FF81FF82FF83FF84FF85FF86FF87FF88FF89FF8AFF8BFF8CFF8DFF8EFF8F +FF90FF91FF92FF93FF94FF95FF96FF97FF98FF99FF9AFF9BFF9CFF9DFF9EFF9F +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +81 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +300030013002FF0CFF0E30FBFF1AFF1BFF1FFF01309B309C00B4FF4000A8FF3E +FFE3FF3F30FD30FE309D309E30034EDD30053006300730FC20152010FF0F005C +301C2016FF5C2026202520182019201C201DFF08FF0930143015FF3BFF3DFF5B +FF5D30083009300A300B300C300D300E300F30103011FF0B221200B100D70000 +00F7FF1D2260FF1CFF1E22662267221E22342642264000B0203220332103FFE5 +FF0400A200A3FF05FF03FF06FF0AFF2000A72606260525CB25CF25CE25C725C6 +25A125A025B325B225BD25BC203B301221922190219121933013000000000000 +000000000000000000000000000000002208220B2286228722822283222A2229 +000000000000000000000000000000002227222800AC21D221D4220022030000 +0000000000000000000000000000000000000000222022A52312220222072261 +2252226A226B221A223D221D2235222B222C0000000000000000000000000000 +212B2030266F266D266A2020202100B6000000000000000025EF000000000000 +.CE +.PP +The third line of the file is three numbers. The first number is the +fallback character (in base 16) to use when converting from UTF-8 to this +encoding. The second number is a \fB1\fR if this file represents the +encoding for a symbol font, or \fB0\fR otherwise. The last number (in base +10) is how many pages of data follow. +.PP +Subsequent lines in the example above are pages that describe how to map +from the encoding into 2-byte Unicode. The first line in a page identifies +the page number. Following it are 256 double-byte numbers, arranged as 16 +rows of 16 numbers. Given a character in the encoding, the high byte of +that character is used to select which page, and the low byte of that +character is used as an index to select one of the double-byte numbers in +that page \- the value obtained being the corresponding Unicode character. +By examination of the example above, one can see that the characters 0x7E +and 0x8163 in \fBshiftjis\fR map to 203E and 2026 in Unicode, respectively. +.PP +Following the first page will be all the other pages, each in the same +format as the first: one number identifying the page followed by 256 +double-byte Unicode characters. If a character in the encoding maps to the +Unicode character 0000, it means that the character doesn't actually exist. +If all characters on a page would map to 0000, that page can be omitted. +.PP +Case [4] is the escape-sequence encoding file. The lines in an this type of +file are in the same format as this example taken from the \fBiso2022-jp\fR +encoding: +.CS +.ta 1.5i +# Encoding file: iso2022-jp, escape-driven +E +init {} +final {} +iso8859-1 \\x1b(B +jis0201 \\x1b(J +jis0208 \\x1b$@ +jis0208 \\x1b$B +jis0212 \\x1b$(D +gb2312 \\x1b$A +ksc5601 \\x1b$(C +.CE +.PP +In the file, the first column represents an option and the second column +is the associated value. \fBinit\fR is a string to emit or expect before +the first character is converted, while \fBfinal\fR is a string to emit +or expect after the last character. All other options are names of +table-based encodings; the associated value is the escape-sequence that +marks that encoding. Tcl syntax is used for the values; in the above +example, for instance, ``\fB{}\fR'' represents the empty string and +``\fB\\x1b\fR'' represents character 27. +.PP +When \fBTcl_GetEncoding\fR encounters an encoding \fIname\fR that has not +been loaded, it attempts to load an encoding file called \fIname\fB.enc\fR +from the \fBencoding\fR subdirectory of each directory specified in the +library path \fB$tcl_libPath\fR. If the encoding file exists, but is +malformed, an error message will be left in \fIinterp\fR. +.SH KEYWORDS +utf, encoding, convert + + + diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Eval.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Eval.3 new file mode 100644 index 0000000000000000000000000000000000000000..71cfccbc635ac6c2824662e99f7f2e3b82fa0cc7 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Eval.3 @@ -0,0 +1,199 @@ +'\" +'\" Copyright (c) 1989-1993 The Regents of the University of California. +'\" Copyright (c) 1994-1997 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: Eval.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_Eval 3 8.1 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_EvalObjEx, Tcl_EvalFile, Tcl_EvalObjv, Tcl_Eval, Tcl_EvalEx, Tcl_GlobalEval, Tcl_GlobalEvalObj, Tcl_VarEval, Tcl_VarEvalVA \- execute Tcl scripts +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +.VS +int +\fBTcl_EvalObjEx\fR(\fIinterp, objPtr, flags\fR) +.sp +int +\fBTcl_EvalFile\fR(\fIinterp, fileName\fR) +.sp +int +\fBTcl_EvalObjv\fR(\fIinterp, objc, objv, flags\fR) +.sp +int +\fBTcl_Eval\fR(\fIinterp, script\fR) +.sp +int +\fBTcl_EvalEx\fR(\fIinterp, script, numBytes, flags\fR) +.sp +int +\fBTcl_GlobalEval\fR(\fIinterp, script\fR) +.sp +int +\fBTcl_GlobalEvalObj\fR(\fIinterp, objPtr, flags\fR) +.sp +int +\fBTcl_VarEval\fR(\fIinterp, string, string, ... \fB(char *) NULL\fR) +.sp +int +\fBTcl_VarEvalVA\fR(\fIinterp, argList\fR) +.SH ARGUMENTS +.AS Tcl_Interp **termPtr; +.AP Tcl_Interp *interp in +Interpreter in which to execute the script. The interpreter's result is +modified to hold the result or error message from the script. +.AP Tcl_Obj *objPtr in +A Tcl object containing the script to execute. +.AP int flags in +ORed combination of flag bits that specify additional options. +\fBTCL_EVAL_GLOBAL\fR and \fBTCL_EVAL_DIRECT\fR are currently supported. +.AP char *fileName in +Name of a file containing a Tcl script. +.AP int objc in +The number of objects in the array pointed to by \fIobjPtr\fR; +this is also the number of words in the command. +.AP Tcl_Obj **objv in +Points to an array of pointers to objects; each object holds the +value of a single word in the command to execute. +.AP int numBytes in +The number of bytes in \fIscript\fR, not including any +null terminating character. If \-1, then all characters up to the +first null byte are used. +.AP char *script in +Points to first byte of script to execute (NULL terminated and UTF-8). +This script must be in writable memory: temporary modifications are made +to it during parsing. +.AP char *string in +String forming part of a Tcl script. +.AP va_list argList in +An argument list which must have been initialised using +\fBTCL_VARARGS_START\fR, and cleared using \fBva_end\fR. +.BE + +.SH DESCRIPTION +.PP +The procedures described here are invoked to execute Tcl scripts in +various forms. +\fBTcl_EvalObjEx\fR is the core procedure and is used by many of the others. +It executes the commands in the script stored in \fIobjPtr\fR +until either an error occurs or the end of the script is reached. +If this is the first time \fIobjPtr\fR has been executed, +its commands are compiled into bytecode instructions +which are then executed. The +bytecodes are saved in \fIobjPtr\fR so that the compilation step +can be skipped if the object is evaluated again in the future. +.PP +The return value from \fBTcl_EvalObjEx\fR (and all the other procedures +described here) is a Tcl completion code with +one of the values \fBTCL_OK\fR, \fBTCL_ERROR\fR, \fBTCL_RETURN\fR, +\fBTCL_BREAK\fR, or \fBTCL_CONTINUE\fR. +In addition, a result value or error message is left in \fIinterp\fR's +result; it can be retrieved using \fBTcl_GetObjResult\fR. +.PP +\fBTcl_EvalFile\fR reads the file given by \fIfileName\fR and evaluates +its contents as a Tcl script. It returns the same information as +\fBTcl_EvalObjEx\fR. +If the file couldn't be read then a Tcl error is returned to describe +why the file couldn't be read. +.PP +\fBTcl_EvalObjv\fR executes a single pre-parsed command instead of a +script. The \fIobjc\fR and \fIobjv\fR arguments contain the values +of the words for the Tcl command, one word in each object in +\fIobjv\fR. \fBTcl_EvalObjv\fR evaluates the command and returns +a completion code and result just like \fBTcl_EvalObjEx\fR. +.PP +\fBTcl_Eval\fR is similar to \fBTcl_EvalObjEx\fR except that the script to +be executed is supplied as a string instead of an object and no compilation +occurs. The string should be a proper UTF-8 string as converted by +\fBTcl_ExternalToUtfDString\fR or \fBTcl_ExternalToUtf\fR when it is known +to possibly contain upper ascii characters who's possible combinations +might be a UTF-8 special code. The string is parsed and executed directly +(using \fBTcl_EvalObjv\fR) instead of compiling it and executing the +bytecodes. In situations where it is known that the script will never be +executed again, \fBTcl_Eval\fR may be faster than \fBTcl_EvalObjEx\fR. +\fBTcl_Eval\fR returns a completion code and result just like +\fBTcl_EvalObjEx\fR. Note: for backward compatibility with versions before +Tcl 8.0, \fBTcl_Eval\fR copies the object result in \fIinterp\fR to +\fIinterp->result\fR (use is deprecated) where it can be accessed directly. +This makes \fBTcl_Eval\fR somewhat slower than \fBTcl_EvalEx\fR, which +doesn't do the copy. +.PP +\fBTcl_EvalEx\fR is an extended version of \fBTcl_Eval\fR that takes +additional arguments \fInumBytes\fR and \fIflags\fR. For the +efficiency reason given above, \fBTcl_EvalEx\fR is generally preferred +over \fBTcl_Eval\fR. +.PP +\fBTcl_GlobalEval\fR and \fBTcl_GlobalEvalObj\fR are older procedures +that are now deprecated. They are similar to \fBTcl_EvalEx\fR and +\fBTcl_EvalObjEx\fR except that the script is evaluated in the global +namespace and its variable context consists of global variables only +(it ignores any Tcl procedures that are active). These functions are +equivalent to using the \fBTCL_EVAL_GLOBAL\fR flag (see below). +.PP +\fBTcl_VarEval\fR takes any number of string arguments +of any length, concatenates them into a single string, +then calls \fBTcl_Eval\fR to execute that string as a Tcl command. +It returns the result of the command and also modifies +\fIinterp->result\fR in the same way as \fBTcl_Eval\fR. +The last argument to \fBTcl_VarEval\fR must be NULL to indicate the end +of arguments. \fBTcl_VarEval\fR is now deprecated. +.PP +\fBTcl_VarEvalVA\fR is the same as \fBTcl_VarEval\fR except that +instead of taking a variable number of arguments it takes an argument +list. Like \fBTcl_VarEval\fR, \fBTcl_VarEvalVA\fR is deprecated. + +.SH "FLAG BITS" +Any ORed combination of the following values may be used for the +\fIflags\fR argument to procedures such as \fBTcl_EvalObjEx\fR: +.TP 23 +\fBTCL_EVAL_DIRECT\fR +This flag is only used by \fBTcl_EvalObjEx\fR; it is ignored by +other procedures. If this flag bit is set, the script is not +compiled to bytecodes; instead it is executed directly +as is done by \fBTcl_EvalEx\fR. The +\fBTCL_EVAL_DIRECT\fR flag is useful in situations where the +contents of an object are going to change immediately, so the +bytecodes won't be reused in a future execution. In this case, +it's faster to execute the script directly. +.TP 23 +\fBTCL_EVAL_GLOBAL\fR +If this flag is set, the script is processed at global level. This +means that it is evaluated in the global namespace and its variable +context consists of global variables only (it ignores any Tcl +procedures at are active). + +.SH "MISCELLANEOUS DETAILS" +.PP +During the processing of a Tcl command it is legal to make nested +calls to evaluate other commands (this is how procedures and +some control structures are implemented). +If a code other than \fBTCL_OK\fR is returned +from a nested \fBTcl_EvalObjEx\fR invocation, +then the caller should normally return immediately, +passing that same return code back to its caller, +and so on until the top-level application is reached. +A few commands, like \fBfor\fR, will check for certain +return codes, like \fBTCL_BREAK\fR and \fBTCL_CONTINUE\fR, and process them +specially without returning. +.PP +\fBTcl_EvalObjEx\fR keeps track of how many nested \fBTcl_EvalObjEx\fR +invocations are in progress for \fIinterp\fR. +If a code of \fBTCL_RETURN\fR, \fBTCL_BREAK\fR, or \fBTCL_CONTINUE\fR is +about to be returned from the topmost \fBTcl_EvalObjEx\fR +invocation for \fIinterp\fR, +it converts the return code to \fBTCL_ERROR\fR +and sets \fIinterp\fR's result to an error message indicating that +the \fBreturn\fR, \fBbreak\fR, or \fBcontinue\fR command was +invoked in an inappropriate place. +This means that top-level applications should never see a return code +from \fBTcl_EvalObjEx\fR other then \fBTCL_OK\fR or \fBTCL_ERROR\fR. +.VE + +.SH KEYWORDS +execute, file, global, object, result, script diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Exit.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Exit.3 new file mode 100644 index 0000000000000000000000000000000000000000..b0737a56e8d48a059873acc03bdc82533a9c9699 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Exit.3 @@ -0,0 +1,131 @@ +'\" +'\" Copyright (c) 1995-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: Exit.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_Exit 3 8.1 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_Exit, Tcl_Finalize, Tcl_CreateExitHandler, Tcl_DeleteExitHandler, Tcl_ExitThread, Tcl_FinalizeThread, Tcl_CreateThreadExitHandler, Tcl_DeleteThreadExitHandler \- end the application or thread (and invoke exit handlers) +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +\fBTcl_Exit\fR(\fIstatus\fR) +.sp +\fBTcl_Finalize\fR() +.sp +\fBTcl_CreateExitHandler\fR(\fIproc, clientData\fR) +.sp +\fBTcl_DeleteExitHandler\fR(\fIproc, clientData\fR) +.sp +\fBTcl_ExitThread\fR(\fIstatus\fR) +.sp +\fBTcl_FinalizeThread\fR() +.sp +\fBTcl_CreateThreadExitHandler\fR(\fIproc, clientData\fR) +.sp +\fBTcl_DeleteThreadExitHandler\fR(\fIproc, clientData\fR) +.SH ARGUMENTS +.AS Tcl_ExitProc clientData +.AP int status in +Provides information about why the application or thread exited. +Exact meaning may +be platform-specific. 0 usually means a normal exit, any nonzero value +usually means that an error occurred. +.AP Tcl_ExitProc *proc in +Procedure to invoke before exiting application. +.AP ClientData clientData in +Arbitrary one-word value to pass to \fIproc\fR. +.BE + +.SH DESCRIPTION +.PP +The procedures described here provide a graceful mechanism to end the +execution of a \fBTcl\fR application. Exit handlers are invoked to cleanup the +application's state before ending the execution of \fBTcl\fR code. +.PP +Invoke \fBTcl_Exit\fR to end a \fBTcl\fR application and to exit from this +process. This procedure is invoked by the \fBexit\fR command, and can be +invoked anyplace else to terminate the application. +No-one should ever invoke the \fBexit\fR system procedure directly; always +invoke \fBTcl_Exit\fR instead, so that it can invoke exit handlers. +Note that if other code invokes \fBexit\fR system procedure directly, or +otherwise causes the application to terminate without calling +\fBTcl_Exit\fR, the exit handlers will not be run. +\fBTcl_Exit\fR internally invokes the \fBexit\fR system call, thus it never +returns control to its caller. +.PP +\fBTcl_Finalize\fR is similar to \fBTcl_Exit\fR except that it does not +exit from the current process. +It is useful for cleaning up when a process is finished using \fBTcl\fR but +wishes to continue executing, and when \fBTcl\fR is used in a dynamically +loaded extension that is about to be unloaded. +On some systems \fBTcl\fR is automatically notified when it is being +unloaded, and it calls \fBTcl_Finalize\fR internally; on these systems it +not necessary for the caller to explicitly call \fBTcl_Finalize\fR. +However, to ensure portability, your code should always invoke +\fBTcl_Finalize\fR when \fBTcl\fR is being unloaded, to ensure that the +code will work on all platforms. \fBTcl_Finalize\fR can be safely called +more than once. +.PP +.VS +\fBTcl_ExitThread\fR is used to terminate the current thread and invoke +per-thread exit handlers. This finalization is done by +\fBTcl_FinalizeThread\fR, which you can call if you just want to clean +up per-thread state and invoke the thread exit handlers. +\fBTcl_Finalize\fR calls \fBTcl_FinalizeThread\fR for the current +thread automatically. +.VE +.PP +\fBTcl_CreateExitHandler\fR arranges for \fIproc\fR to be invoked +by \fBTcl_Finalize\fR and \fBTcl_Exit\fR. +\fBTcl_CreateThreadExitHandler\fR arranges for \fIproc\fR to be invoked +by \fBTcl_FinalizeThread\fR and \fBTcl_ExitThread\fR. +This provides a hook for cleanup operations such as flushing buffers +and freeing global memory. +\fIProc\fR should match the type \fBTcl_ExitProc\fR: +.CS +typedef void Tcl_ExitProc(ClientData \fIclientData\fR); +.CE +The \fIclientData\fR parameter to \fIproc\fR is a +copy of the \fIclientData\fR argument given to +\fBTcl_CreateExitHandler\fR or \fBTcl_CreateThreadExitHandler\fR when +the callback +was created. Typically, \fIclientData\fR points to a data +structure containing application-specific information about +what to do in \fIproc\fR. +.PP +\fBTcl_DeleteExitHandler\fR and \fBTcl_DeleteThreadExitHandler\fR may be +called to delete a +previously-created exit handler. It removes the handler +indicated by \fIproc\fR and \fIclientData\fR so that no call +to \fIproc\fR will be made. If no such handler exists then +\fBTcl_DeleteExitHandler\fR or \fBTcl_DeleteThreadExitHandler\fR does nothing. +.PP +.VS +.PP +\fBTcl_Finalize\fR and \fBTcl_Exit\fR execute all registered exit handlers, +in reverse order from the order in which they were registered. +This matches the natural order in which extensions are loaded and unloaded; +if extension \fBA\fR loads extension \fBB\fR, it usually +unloads \fBB\fR before it itself is unloaded. +If extension \fBA\fR registers its exit handlers before loading extension +\fBB\fR, this ensures that any exit handlers for \fBB\fR will be executed +before the exit handlers for \fBA\fR. +.VE +.VS +.PP +\fBTcl_Finalize\fR and \fBTcl_Exit\fR call \fBTcl_FinalizeThread\fR +and the thread exit handlers \fIafter\fR +the process-wide exit handlers. This is because thread finalization shuts +down the I/O channel system, so any attempt at I/O by the global exit +handlers will vanish into the bitbucket. +.VE + +.SH KEYWORDS +callback, cleanup, dynamic loading, end application, exit, unloading, thread diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/ExprLong.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/ExprLong.3 new file mode 100644 index 0000000000000000000000000000000000000000..f60346caf964eb57b97ef1149204057878435da4 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/ExprLong.3 @@ -0,0 +1,112 @@ +'\" +'\" Copyright (c) 1989-1993 The Regents of the University of California. +'\" Copyright (c) 1994-1997 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: ExprLong.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_ExprLong 3 7.0 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_ExprLong, Tcl_ExprDouble, Tcl_ExprBoolean, Tcl_ExprString \- evaluate an expression +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +int +\fBTcl_ExprLong\fR(\fIinterp, string, longPtr\fR) +.sp +int +\fBTcl_ExprDouble\fR(\fIinterp, string, doublePtr\fR) +.sp +int +\fBTcl_ExprBoolean\fR(\fIinterp, string, booleanPtr\fR) +.sp +int +\fBTcl_ExprString\fR(\fIinterp, string\fR) +.SH ARGUMENTS +.AS Tcl_Interp *booleanPtr +.AP Tcl_Interp *interp in +Interpreter in whose context to evaluate \fIstring\fR or \fIobjPtr\fR. +.AP char *string in +Expression to be evaluated. Must be in writable memory (the expression +parser makes temporary modifications to the string during parsing, which +it undoes before returning). +.AP long *longPtr out +Pointer to location in which to store the integer value of the +expression. +.AP int *doublePtr out +Pointer to location in which to store the floating-point value of the +expression. +.AP int *booleanPtr out +Pointer to location in which to store the 0/1 boolean value of the +expression. +.BE + +.SH DESCRIPTION +.PP +These four procedures all evaluate the expression +given by the \fIstring\fR argument +and return the result in one of four different forms. +The expression can have any of the forms accepted by the \fBexpr\fR command. +Note that these procedures have been largely replaced by the +object-based procedures \fBTcl_ExprLongObj\fR, \fBTcl_ExprDoubleObj\fR, +\fBTcl_ExprBooleanObj\fR, and \fBTcl_ExprStringObj\fR. +Those object-based procedures evaluate an expression held in a Tcl object +instead of a string. +The object argument can retain an internal representation +that is more efficient to execute. +.PP +The \fIinterp\fR argument refers to an interpreter used to +evaluate the expression (e.g. for variables and nested Tcl +commands) and to return error information. +.PP +For all of these procedures the return value is a standard +Tcl result: \fBTCL_OK\fR means the expression was successfully +evaluated, and \fBTCL_ERROR\fR means that an error occurred while +evaluating the expression. +If \fBTCL_ERROR\fR is returned then +the interpreter's result will hold a message describing the error. +If an error occurs while executing a Tcl command embedded in +the expression then that error will be returned. +.PP +If the expression is successfully evaluated, then its value is +returned in one of four forms, depending on which procedure +is invoked. +\fBTcl_ExprLong\fR stores an integer value at \fI*longPtr\fR. +If the expression's actual value is a floating-point number, +then it is truncated to an integer. +If the expression's actual value is a non-numeric string then +an error is returned. +.PP +\fBTcl_ExprDouble\fR stores a floating-point value at \fI*doublePtr\fR. +If the expression's actual value is an integer, it is converted to +floating-point. +If the expression's actual value is a non-numeric string then +an error is returned. +.PP +\fBTcl_ExprBoolean\fR stores a 0/1 integer value at \fI*booleanPtr\fR. +If the expression's actual value is an integer or floating-point +number, then they store 0 at \fI*booleanPtr\fR if +the value was zero and 1 otherwise. +If the expression's actual value is a non-numeric string then +it must be one of the values accepted by \fBTcl_GetBoolean\fR +such as ``yes'' or ``no'', or else an error occurs. +.PP +\fBTcl_ExprString\fR returns the value of the expression as a +string stored in the interpreter's result. +If the expression's actual value is an integer +then \fBTcl_ExprString\fR converts it to a string using \fBsprintf\fR +with a ``%d'' converter. +If the expression's actual value is a floating-point +number, then \fBTcl_ExprString\fR calls \fBTcl_PrintDouble\fR +to convert it to a string. + +.SH "SEE ALSO" +Tcl_ExprLongObj, Tcl_ExprDoubleObj, Tcl_ExprBooleanObj, Tcl_ExprObj + +.SH KEYWORDS +boolean, double, evaluate, expression, integer, object, string diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/ExprLongObj.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/ExprLongObj.3 new file mode 100644 index 0000000000000000000000000000000000000000..95dedff30b4246aa6affd76e2b9c2e2881030432 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/ExprLongObj.3 @@ -0,0 +1,104 @@ +'\" +'\" Copyright (c) 1996-1997 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: ExprLongObj.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_ExprLongObj 3 8.0 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_ExprLongObj, Tcl_ExprDoubleObj, Tcl_ExprBooleanObj, Tcl_ExprObj \- evaluate an expression +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +int +\fBTcl_ExprLongObj\fR(\fIinterp, objPtr, longPtr\fR) +.sp +int +\fBTcl_ExprDoubleObj\fR(\fIinterp, objPtr, doublePtr\fR) +.sp +int +\fBTcl_ExprBooleanObj\fR(\fIinterp, objPtr, booleanPtr\fR) +.sp +int +\fBTcl_ExprObj\fR(\fIinterp, objPtr, resultPtrPtr\fR) +.SH ARGUMENTS +.AS Tcl_Interp *resultPtrPtr out +.AP Tcl_Interp *interp in +Interpreter in whose context to evaluate \fIstring\fR or \fIobjPtr\fR. +.AP Tcl_Obj *objPtr in +Pointer to an object containing the expression to evaluate. +.AP long *longPtr out +Pointer to location in which to store the integer value of the +expression. +.AP int *doublePtr out +Pointer to location in which to store the floating-point value of the +expression. +.AP int *booleanPtr out +Pointer to location in which to store the 0/1 boolean value of the +expression. +.AP Tcl_Obj *resultPtrPtr out +Pointer to location in which to store a pointer to the object +that is the result of the expression. +.BE + +.SH DESCRIPTION +.PP +These four procedures all evaluate an expression, returning +the result in one of four different forms. +The expression is given by the \fIobjPtr\fR argument, and it +can have any of the forms accepted by the \fBexpr\fR command. +.PP +The \fIinterp\fR argument refers to an interpreter used to +evaluate the expression (e.g. for variables and nested Tcl +commands) and to return error information. +.PP +For all of these procedures the return value is a standard +Tcl result: \fBTCL_OK\fR means the expression was successfully +evaluated, and \fBTCL_ERROR\fR means that an error occurred while +evaluating the expression. +If \fBTCL_ERROR\fR is returned, +then a message describing the error +can be retrieved using \fBTcl_GetObjResult\fR. +If an error occurs while executing a Tcl command embedded in +the expression then that error will be returned. +.PP +If the expression is successfully evaluated, then its value is +returned in one of four forms, depending on which procedure +is invoked. +\fBTcl_ExprLongObj\fR stores an integer value at \fI*longPtr\fR. +If the expression's actual value is a floating-point number, +then it is truncated to an integer. +If the expression's actual value is a non-numeric string then +an error is returned. +.PP +\fBTcl_ExprDoubleObj\fR stores a floating-point value at \fI*doublePtr\fR. +If the expression's actual value is an integer, it is converted to +floating-point. +If the expression's actual value is a non-numeric string then +an error is returned. +.PP +\fBTcl_ExprBooleanObj\fR stores a 0/1 integer value at \fI*booleanPtr\fR. +If the expression's actual value is an integer or floating-point +number, then they store 0 at \fI*booleanPtr\fR if +the value was zero and 1 otherwise. +If the expression's actual value is a non-numeric string then +it must be one of the values accepted by \fBTcl_GetBoolean\fR +such as ``yes'' or ``no'', or else an error occurs. +.PP +If \fBTcl_ExprObj\fR successfully evaluates the expression, +it stores a pointer to the Tcl object +containing the expression's value at \fI*resultPtrPtr\fR. +In this case, the caller is responsible for calling +\fBTcl_DecrRefCount\fR to decrement the object's reference count +when it is finished with the object. + +.SH "SEE ALSO" +Tcl_ExprLong, Tcl_ExprDouble, Tcl_ExprBoolean, Tcl_ExprString, Tcl_GetObjResult + +.SH KEYWORDS +boolean, double, evaluate, expression, integer, object, string diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/FindExec.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/FindExec.3 new file mode 100644 index 0000000000000000000000000000000000000000..3df5f3c0e219bdcd21bf077f4cf79a1d1ccafab3 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/FindExec.3 @@ -0,0 +1,58 @@ +'\" +'\" Copyright (c) 1995-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: FindExec.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_FindExecutable 3 8.1 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_FindExecutable, Tcl_GetNameOfExecutable \- identify or return the name of the binary file containing the application +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +void +\fBTcl_FindExecutable\fR(\fIargv0\fR) +.sp +CONST char * +\fBTcl_GetNameOfExecutable\fR() +.SH ARGUMENTS +.AS char *argv0 in +.AP char *argv0 in +The first command-line argument to the program, which gives the +application's name. +.BE + +.SH DESCRIPTION +.PP +The \fBTcl_FindExecutable\fR procedure computes the full path name of +the executable file from which the application was invoked and saves +it for Tcl's internal use. +The executable's path name is needed for several purposes in +Tcl. For example, it is needed on some platforms in the +implementation of the \fBload\fR command. +It is also returned by the \fBinfo nameofexecutable\fR command. +.PP +On UNIX platforms this procedure is typically invoked as the very +first thing in the application's main program; it must be passed +\fIargv[0]\fR as its argument. It is important not to change the +working directory before the invocation. +\fBTcl_FindExecutable\fR uses \fIargv0\fR +along with the \fBPATH\fR environment variable to find the +application's executable, if possible. If it fails to find +the binary, then future calls to \fBinfo nameofexecutable\fR +will return an empty string. +.PP +\fBTcl_GetNameOfExecutable\fR simply returns a pointer to the +internal full path name of the executable file as computed by +\fBTcl_FindExecutable\fR. This procedure call is the C API +equivalent to the \fBinfo nameofexecutable\fR command. NULL +is returned if the internal full path name has not been +computed or unknown. + +.SH KEYWORDS +binary, executable file diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/GetCwd.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/GetCwd.3 new file mode 100644 index 0000000000000000000000000000000000000000..723aef550996e48f9fb92a4d136340b3a30da532 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/GetCwd.3 @@ -0,0 +1,54 @@ +'\" +'\" Copyright (c) 1998-1999 Scriptics Corportation +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: GetCwd.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_GetCwd 3 8.1 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_GetCwd, Tcl_Chdir \- manipulate the current working directory +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +char * +\fBTcl_GetCwd\fR(\fIinterp\fR, \fIbufferPtr\fR) +.sp +int +\fBTcl_Chdir\fR(\fIpath\fR) +.SH ARGUMENTS +.AS Tcl_DString *bufferPtr +.AP Tcl_Interp *interp in +Interpreter in which to report an error, if any. +.AP Tcl_DString *bufferPtr in/out +This dynamic string is used to store the current working directory. +At the time of the call it should be uninitialized or free. The +caller must eventually call \fBTcl_DStringFree\fR to free up +anything stored here. +.AP char *path in +File path in UTF\-8 format. +.BE + +.SH DESCRIPTION +.PP +These procedures may be used to manipulate the current working +directory for the application. They provide C\-level access to +the same functionality as the Tcl \fBpwd\fR command. +.PP +\fBTcl_GetCwd\fR returns a pointer to a string specifying the current +directory, or NULL if the current directory could not be determined. +If NULL is returned, an error message is left in the interp's result. +Storage for the result string is allocated in bufferPtr; the caller +must call \fBTcl_DStringFree()\fR when the result is no longer needed. +The format of the path is UTF\-8. +.PP +\fBTcl_Chdir\fR changes the applications current working directory to +the value specified in \fIpath\fR. The format of the passed in string +must be UTF\-8. The function returns -1 on error or 0 on success. + +.SH KEYWORDS +pwd diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/GetHostName.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/GetHostName.3 new file mode 100644 index 0000000000000000000000000000000000000000..058a14bc69eb3aeac56b53d50879784e0b1c07ac --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/GetHostName.3 @@ -0,0 +1,28 @@ +'\" +'\" Copyright (c) 1998-2000 by Scriptics Corporation. +'\" All rights reserved. +'\" +'\" RCS: @(#) $Id: GetHostName.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_GetHostName 3 8.3 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_GetHostName \- get the name of the local host +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +char * +\fBTcl_GetHostName\fR() + +.SH DESCRIPTION +.PP +\fBTcl_GetHostName\fR is a utility procedure used by some of the +Tcl commands. It returns a pointer to a string containing the name +for the current machine, or an empty string if the name cannot be +determined. The string is statically allocated, and the caller must +not modify of free it. +.PP +.SH KEYWORDS +hostname diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/GetIndex.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/GetIndex.3 new file mode 100644 index 0000000000000000000000000000000000000000..b77cb57c81caa27fec31b5e9d8a9548943f57dd9 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/GetIndex.3 @@ -0,0 +1,102 @@ +'\" +'\" Copyright (c) 1997 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: GetIndex.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_GetIndexFromObj 3 8.1 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_GetIndexFromObj, Tcl_GetIndexFromObjStruct \- lookup string in table of keywords +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +int +\fBTcl_GetIndexFromObj\fR(\fIinterp, objPtr, tablePtr, msg, flags, +indexPtr\fR) +.VS +.sp +int +\fBTcl_GetIndexFromObjStruct\fR(\fIinterp, objPtr, tablePtr, offset, +msg, flags, indexPtr\fR) +.VE +.SH ARGUMENTS +.AS Tcl_Interp **tablePtr +.AP Tcl_Interp *interp in +Interpreter to use for error reporting; if NULL, then no message is +provided on errors. +.AP Tcl_Obj *objPtr in/out +The string value of this object is used to search through \fItablePtr\fR. +The internal representation is modified to hold the index of the matching +table entry. +.AP char **tablePtr in +An array of null-terminated strings. The end of the array is marked +by a NULL string pointer. +.VS +.AP int offset in +The offset to add to tablePtr to get to the next string in the +list. The end of the array is marked by a NULL string pointer. +.VE +.AP char *msg in +Null-terminated string describing what is being looked up, such as +\fBoption\fR. This string is included in error messages. +.AP int flags in +OR-ed combination of bits providing additional information for +operation. The only bit that is currently defined is \fBTCL_EXACT\fR. +.AP int *indexPtr out +The index of the string in \fItablePtr\fR that matches the value of +\fIobjPtr\fR is returned here. +.BE + +.SH DESCRIPTION +.PP +This procedure provides an efficient way for looking up keywords, +switch names, option names, and similar things where the value of +an object must be one of a predefined set of values. +\fIObjPtr\fR is compared against each of +the strings in \fItablePtr\fR to find a match. A match occurs if +\fIobjPtr\fR's string value is identical to one of the strings in +\fItablePtr\fR, or if it is a unique abbreviation +for exactly one of the strings in \fItablePtr\fR and the +\fBTCL_EXACT\fR flag was not specified; in either case +the index of the matching entry is stored at \fI*indexPtr\fR +and TCL_OK is returned. +.PP +If there is no matching entry, +TCL_ERROR is returned and an error message is left in \fIinterp\fR's +result if \fIinterp\fR isn't NULL. \fIMsg\fR is included in the +error message to indicate what was being looked up. For example, +if \fImsg\fR is \fBoption\fR the error message will have a form like +\fBbad option "firt": must be first, second, or third\fR. +.PP +If \fBTcl_GetIndexFromObj\fR completes successfully it modifies the +internal representation of \fIobjPtr\fR to hold the address of +the table and the index of the matching entry. If \fBTcl_GetIndexFromObj\fR +is invoked again with the same \fIobjPtr\fR and \fItablePtr\fR +arguments (e.g. during a reinvocation of a Tcl command), it returns +the matching index immediately without having to redo the lookup +operation. Note: \fBTcl_GetIndexFromObj\fR assumes that the entries +in \fItablePtr\fR are static: they must not change between +invocations. If the value of \fIobjPtr\fR is the empty string, +\fBTcl_GetIndexFromObj\fR will treat it as a non-matching value +and return TCL_ERROR. +.VS +.PP +\fBTcl_GetIndexFromObjStruct\fR works just like +\fBTcl_GetIndexFromObj\fR, except that instead of treating +\fItablePtr\fR as an array of string pointers, it treats it as the +first in a series of string ptrs that are spaced apart by \fIoffset\fR +bytes. This is particularly useful when processing things like +\fBTk_ConfigurationSpec\fR, whose string keys are in the same place in +each of several array elements. +.VE + +.SH "SEE ALSO" +Tcl_WrongNumArgs + +.SH KEYWORDS +index, object, table lookup diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/GetInt.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/GetInt.3 new file mode 100644 index 0000000000000000000000000000000000000000..47eeae6308bd3113a88d3d52e2484007865d943c --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/GetInt.3 @@ -0,0 +1,81 @@ +'\" +'\" Copyright (c) 1989-1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: GetInt.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_GetInt 3 "" Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_GetInt, Tcl_GetDouble, Tcl_GetBoolean \- convert from string to integer, double, or boolean +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +int +\fBTcl_GetInt\fR(\fIinterp, string, intPtr\fR) +.sp +int +\fBTcl_GetDouble\fR(\fIinterp, string, doublePtr\fR) +.sp +int +\fBTcl_GetBoolean\fR(\fIinterp, string, boolPtr\fR) +.SH ARGUMENTS +.AS Tcl_Interp *doublePtr +.AP Tcl_Interp *interp in +Interpreter to use for error reporting. +.AP char *string in +Textual value to be converted. +.AP int *intPtr out +Points to place to store integer value converted from \fIstring\fR. +.AP double *doublePtr out +Points to place to store double-precision floating-point +value converted from \fIstring\fR. +.AP int *boolPtr out +Points to place to store boolean value (0 or 1) converted from \fIstring\fR. +.BE + +.SH DESCRIPTION +.PP +These procedures convert from strings to integers or double-precision +floating-point values or booleans (represented as 0- or 1-valued +integers). Each of the procedures takes a \fIstring\fR argument, +converts it to an internal form of a particular type, and stores +the converted value at the location indicated by the procedure's +third argument. If all goes well, each of the procedures returns +TCL_OK. If \fIstring\fR doesn't have the proper syntax for the +desired type then TCL_ERROR is returned, an error message is left +in the interpreter's result, and nothing is stored at *\fIintPtr\fR +or *\fIdoublePtr\fR or *\fIboolPtr\fR. +.PP +\fBTcl_GetInt\fR expects \fIstring\fR to consist of a collection +of integer digits, optionally signed and optionally preceded by +white space. If the first two characters of \fIstring\fR are ``0x'' +then \fIstring\fR is expected to be in hexadecimal form; otherwise, +if the first character of \fIstring\fR is ``0'' then \fIstring\fR +is expected to be in octal form; otherwise, \fIstring\fR is +expected to be in decimal form. +.PP +\fBTcl_GetDouble\fR expects \fIstring\fR to consist of a floating-point +number, which is: white space; a sign; a sequence of digits; a +decimal point; a sequence of digits; the letter ``e''; and a +signed decimal exponent. Any of the fields may be omitted, except that +the digits either before or after the decimal point must be present +and if the ``e'' is present then it must be followed by the +exponent number. +.PP +\fBTcl_GetBoolean\fR expects \fIstring\fR to specify a boolean +value. If \fIstring\fR is any of \fB0\fR, \fBfalse\fR, +\fBno\fR, or \fBoff\fR, then \fBTcl_GetBoolean\fR stores a zero +value at \fI*boolPtr\fR. +If \fIstring\fR is any of \fB1\fR, \fBtrue\fR, \fByes\fR, or \fBon\fR, +then 1 is stored at \fI*boolPtr\fR. +Any of these values may be abbreviated, and upper-case spellings +are also acceptable. + +.SH KEYWORDS +boolean, conversion, double, floating-point, integer diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/GetOpnFl.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/GetOpnFl.3 new file mode 100644 index 0000000000000000000000000000000000000000..94678fb1366bceb7228b551b29c8f11a9d539094 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/GetOpnFl.3 @@ -0,0 +1,61 @@ +'\" +'\" Copyright (c) 1996-1997 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: GetOpnFl.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +.so man.macros +.TH Tcl_GetOpenFile 3 8.0 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_GetOpenFile \- Get a standard IO File * handle from a channel. (Unix only) +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +int +\fBTcl_GetOpenFile\fR(\fIinterp, string, write, checkUsage, filePtr\fR) +.sp +.SH ARGUMENTS +.AS Tcl_Interp checkUsage +.AP Tcl_Interp *interp in +Tcl interpreter from which file handle is to be obtained. +.AP char *string in +String identifying channel, such as \fBstdin\fR or \fBfile4\fR. +.AP int write in +Non-zero means the file will be used for writing, zero means it will +be used for reading. +.AP int checkUsage in +If non-zero, then an error will be generated if the file wasn't opened +for the access indicated by \fIwrite\fR. +.AP ClientData *filePtr out +Points to word in which to store pointer to FILE structure for +the file given by \fIstring\fR. +.BE + +.SH DESCRIPTION +.PP +\fBTcl_GetOpenFile\fR takes as argument a file identifier of the form +returned by the \fBopen\fR command and +returns at \fI*filePtr\fR a pointer to the FILE structure for +the file. +The \fIwrite\fR argument indicates whether the FILE pointer will +be used for reading or writing. +In some cases, such as a channel that connects to a pipeline of +subprocesses, different FILE pointers will be returned for reading +and writing. +\fBTcl_GetOpenFile\fR normally returns TCL_OK. +If an error occurs in \fBTcl_GetOpenFile\fR (e.g. \fIstring\fR didn't +make any sense or \fIcheckUsage\fR was set and the file wasn't opened +for the access specified by \fIwrite\fR) then TCL_ERROR is returned +and the interpreter's result will contain an error message. +In the current implementation \fIcheckUsage\fR is ignored and consistency +checks are always performed. +.VS +.PP +Note that this interface is only supported on the Unix platform. +.VE + +.SH KEYWORDS +channel, file handle, permissions, pipeline, read, write diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/GetStdChan.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/GetStdChan.3 new file mode 100644 index 0000000000000000000000000000000000000000..4e30730a65cb36c7293b5bd334c17b60c34f2b0e --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/GetStdChan.3 @@ -0,0 +1,73 @@ +'\" +'\" Copyright (c) 1996 by Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: GetStdChan.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_GetStdChannel 3 7.5 Tcl "Tcl Library Procedures" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +Tcl_GetStdChannel, Tcl_SetStdChannel \- procedures for retrieving and replacing the standard channels +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +Tcl_Channel +\fBTcl_GetStdChannel\fR(\fItype\fR) +.sp +\fBTcl_SetStdChannel\fR(\fIchannel, type\fR) +.sp +.SH ARGUMENTS +.AS Tcl_Channel channel in +.AP int type in +The identifier for the standard channel to retrieve or modify. Must be one of +\fBTCL_STDIN\fR, \fBTCL_STDOUT\fR, or \fBTCL_STDERR\fR. +.AP Tcl_Channel channel in +The channel to use as the new value for the specified standard channel. +.BE + +.SH DESCRIPTION +.PP +Tcl defines three special channels that are used by various I/O related +commands if no other channels are specified. The standard input channel +has a channel name of \fBstdin\fR and is used by \fBread\fR and \fBgets\fR. +The standard output channel is named \fBstdout\fR and is used by +\fBputs\fR. The standard error channel is named \fBstderr\fR and is used for +reporting errors. In addition, the standard channels are inherited by any +child processes created using \fBexec\fR or \fBopen\fR in the absence of any +other redirections. +.PP +The standard channels are actually aliases for other normal channels. The +current channel associated with a standard channel can be retrieved by calling +\fBTcl_GetStdChannel\fR with one of +\fBTCL_STDIN\fR, \fBTCL_STDOUT\fR, or \fBTCL_STDERR\fR as the \fItype\fR. The +return value will be a valid channel, or NULL. +.PP +A new channel can be set for the standard channel specified by \fItype\fR +by calling \fBTcl_SetStdChannel\fR with a new channel or NULL in the +\fIchannel\fR argument. If the specified channel is closed by a later call to +\fBTcl_Close\fR, then the corresponding standard channel will automatically be +set to NULL. +.PP +If \fBTcl_GetStdChannel\fR is called before \fBTcl_SetStdChannel\fR, Tcl will +construct a new channel to wrap the appropriate platform-specific standard +file handle. If \fBTcl_SetStdChannel\fR is called before +\fBTcl_GetStdChannel\fR, then the default channel will not be created. +.PP +If one of the standard channels is set to NULL, either by calling +\fBTcl_SetStdChannel\fR with a null \fIchannel\fR argument, or by calling +\fBTcl_Close\fR on the channel, then the next call to \fBTcl_CreateChannel\fR +will automatically set the standard channel with the newly created channel. If +more than one standard channel is NULL, then the standard channels will be +assigned starting with standard input, followed by standard output, with +standard error being last. + +.SH "SEE ALSO" +Tcl_Close(3), Tcl_CreateChannel(3) + +.SH KEYWORDS +standard channel, standard input, standard output, standard error diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/GetVersion.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/GetVersion.3 new file mode 100644 index 0000000000000000000000000000000000000000..5615b9cb0549e77a430bf59480f7b966ca8718a0 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/GetVersion.3 @@ -0,0 +1,49 @@ +'\" +'\" Copyright (c) 1999 Scriptics Corporation +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: GetVersion.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_GetVersion 3 7.5 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_GetVersion \- get the version of the library at runtime +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +\fBTcl_GetVersion\fR(\fImajor, minor, patchLevel, type\fR) +.SH ARGUMENTS +.AP int *major out +Major version number of the Tcl library. +.AP int *minor out +Minor version number of the Tcl library. +.AP int *patchLevel out +The patch level of the Tcl library (or alpha or beta number). +.AP Tcl_ReleaseType *type out +The type of release, also indicates the type of patch level. Can be +one of \fBTCL_ALPHA_RELEASE\fR, \fBTCL_BETA_RELEASE\fR, or +\fBTCL_FINAL_RELEASE\fR. +.BE + +.SH DESCRIPTION +.PP +\fBTcl_GetVersion\fR should be used to query the version number +of the Tcl library at runtime. This is useful when using a +dynamically loaded Tcl library or when writing a stubs-aware +extension. For instance, if you write an extension that is +linked against the Tcl stubs library, it could be loaded into +a program linked to an older version of Tcl than you expected. +Use \fBTcl_GetVersion\fR to verify that fact, and possibly to +change the behavior of your extension. +.PP +If may pass a NULL for any of the arguments. For instance if +you do not care about the \fIpatchLevel\fR of the library, pass +a NULL for the \fIpatchLevel\fR argument. + +.SH KEYWORDS +version, patchlevel, major, minor, alpha, beta, release + diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Hash.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Hash.3 new file mode 100644 index 0000000000000000000000000000000000000000..3202c3496948614b936eea01fb859563ce67453d --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Hash.3 @@ -0,0 +1,208 @@ +'\" +'\" Copyright (c) 1989-1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: Hash.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_Hash 3 "" Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_InitHashTable, Tcl_DeleteHashTable, Tcl_CreateHashEntry, Tcl_DeleteHashEntry, Tcl_FindHashEntry, Tcl_GetHashValue, Tcl_SetHashValue, Tcl_GetHashKey, Tcl_FirstHashEntry, Tcl_NextHashEntry, Tcl_HashStats \- procedures to manage hash tables +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +\fBTcl_InitHashTable\fR(\fItablePtr, keyType\fR) +.sp +\fBTcl_DeleteHashTable\fR(\fItablePtr\fR) +.sp +Tcl_HashEntry * +\fBTcl_CreateHashEntry\fR(\fItablePtr, key, newPtr\fR) +.sp +\fBTcl_DeleteHashEntry\fR(\fIentryPtr\fR) +.sp +Tcl_HashEntry * +\fBTcl_FindHashEntry\fR(\fItablePtr, key\fR) +.sp +ClientData +\fBTcl_GetHashValue\fR(\fIentryPtr\fR) +.sp +\fBTcl_SetHashValue\fR(\fIentryPtr, value\fR) +.sp +char * +\fBTcl_GetHashKey\fR(\fItablePtr, entryPtr\fR) +.sp +Tcl_HashEntry * +\fBTcl_FirstHashEntry\fR(\fItablePtr, searchPtr\fR) +.sp +Tcl_HashEntry * +\fBTcl_NextHashEntry\fR(\fIsearchPtr\fR) +.sp +char * +\fBTcl_HashStats\fR(\fItablePtr\fR) +.SH ARGUMENTS +.AS Tcl_HashSearch *searchPtr +.AP Tcl_HashTable *tablePtr in +Address of hash table structure (for all procedures but +\fBTcl_InitHashTable\fR, this must have been initialized by +previous call to \fBTcl_InitHashTable\fR). +.AP int keyType in +Kind of keys to use for new hash table. Must be either +TCL_STRING_KEYS, TCL_ONE_WORD_KEYS, or an integer value +greater than 1. +.AP char *key in +Key to use for probe into table. Exact form depends on +\fIkeyType\fR used to create table. +.AP int *newPtr out +The word at \fI*newPtr\fR is set to 1 if a new entry was created +and 0 if there was already an entry for \fIkey\fR. +.AP Tcl_HashEntry *entryPtr in +Pointer to hash table entry. +.AP ClientData value in +New value to assign to hash table entry. Need not have type +ClientData, but must fit in same space as ClientData. +.AP Tcl_HashSearch *searchPtr in +Pointer to record to use to keep track of progress in enumerating +all the entries in a hash table. +.BE + +.SH DESCRIPTION +.PP +A hash table consists of zero or more entries, each consisting of +a key and a value. +Given the key for an entry, the hashing routines can very quickly +locate the entry, and hence its value. +There may be at most one entry in a hash table with a +particular key, but many entries may have the same value. +Keys can take one of three forms: strings, +one-word values, or integer arrays. +All of the keys in a given table have the same form, which is +specified when the table is initialized. +.PP +The value of a hash table entry can be anything that fits in +the same space as a ``char *'' pointer. +Values for hash table entries are managed entirely by clients, +not by the hash module itself. +Typically each entry's value is a pointer to a data structure +managed by client code. +.PP +Hash tables grow gracefully as the number of entries increases, +so that there are always less than three entries per hash bucket, +on average. +This allows for fast lookups regardless of the number of entries +in a table. +.PP +\fBTcl_InitHashTable\fR initializes a structure that describes +a new hash table. +The space for the structure is provided by the caller, not by +the hash module. +The value of \fIkeyType\fR indicates what kinds of keys will +be used for all entries in the table. \fIKeyType\fR must have +one of the following values: +.IP \fBTCL_STRING_KEYS\fR 25 +Keys are null-terminated ASCII strings. +They are passed to hashing routines using the address of the +first character of the string. +.IP \fBTCL_ONE_WORD_KEYS\fR 25 +Keys are single-word values; they are passed to hashing routines +and stored in hash table entries as ``char *'' values. +The pointer value is the key; it need not (and usually doesn't) +actually point to a string. +.IP \fIother\fR 25 +If \fIkeyType\fR is not TCL_STRING_KEYS or TCL_ONE_WORD_KEYS, +then it must be an integer value greater than 1. +In this case the keys will be arrays of ``int'' values, where +\fIkeyType\fR gives the number of ints in each key. +This allows structures to be used as keys. +All keys must have the same size. +Array keys are passed into hashing functions using the address +of the first int in the array. +.PP +\fBTcl_DeleteHashTable\fR deletes all of the entries in a hash +table and frees up the memory associated with the table's +bucket array and entries. +It does not free the actual table structure (pointed to +by \fItablePtr\fR), since that memory is assumed to be managed +by the client. +\fBTcl_DeleteHashTable\fR also does not free or otherwise +manipulate the values of the hash table entries. +If the entry values point to dynamically-allocated memory, then +it is the client's responsibility to free these structures +before deleting the table. +.PP +\fBTcl_CreateHashEntry\fR locates the entry corresponding to a +particular key, creating a new entry in the table if there +wasn't already one with the given key. +If an entry already existed with the given key then \fI*newPtr\fR +is set to zero. +If a new entry was created, then \fI*newPtr\fR is set to a non-zero +value and the value of the new entry will be set to zero. +The return value from \fBTcl_CreateHashEntry\fR is a pointer to +the entry, which may be used to retrieve and modify the entry's +value or to delete the entry from the table. +.PP +\fBTcl_DeleteHashEntry\fR will remove an existing entry from a +table. +The memory associated with the entry itself will be freed, but +the client is responsible for any cleanup associated with the +entry's value, such as freeing a structure that it points to. +.PP +\fBTcl_FindHashEntry\fR is similar to \fBTcl_CreateHashEntry\fR +except that it doesn't create a new entry if the key doesn't exist; +instead, it returns NULL as result. +.PP +\fBTcl_GetHashValue\fR and \fBTcl_SetHashValue\fR are used to +read and write an entry's value, respectively. +Values are stored and retrieved as type ``ClientData'', which is +large enough to hold a pointer value. On almost all machines this is +large enough to hold an integer value too. +.PP +\fBTcl_GetHashKey\fR returns the key for a given hash table entry, +either as a pointer to a string, a one-word (``char *'') key, or +as a pointer to the first word of an array of integers, depending +on the \fIkeyType\fR used to create a hash table. +In all cases \fBTcl_GetHashKey\fR returns a result with type +``char *''. +When the key is a string or array, the result of \fBTcl_GetHashKey\fR +points to information in the table entry; this information will +remain valid until the entry is deleted or its table is deleted. +.PP +\fBTcl_FirstHashEntry\fR and \fBTcl_NextHashEntry\fR may be used +to scan all of the entries in a hash table. +A structure of type ``Tcl_HashSearch'', provided by the client, +is used to keep track of progress through the table. +\fBTcl_FirstHashEntry\fR initializes the search record and +returns the first entry in the table (or NULL if the table is +empty). +Each subsequent call to \fBTcl_NextHashEntry\fR returns the +next entry in the table or +NULL if the end of the table has been reached. +A call to \fBTcl_FirstHashEntry\fR followed by calls to +\fBTcl_NextHashEntry\fR will return each of the entries in +the table exactly once, in an arbitrary order. +It is unadvisable to modify the structure of the table, e.g. +by creating or deleting entries, while the search is in +progress. +.PP +\fBTcl_HashStats\fR returns a dynamically-allocated string with +overall information about a hash table, such as the number of +entries it contains, the number of buckets in its hash array, +and the utilization of the buckets. +It is the caller's responsibility to free the result string +by passing it to \fBckfree\fR. +.PP +The header file \fBtcl.h\fR defines the actual data structures +used to implement hash tables. +This is necessary so that clients can allocate Tcl_HashTable +structures and so that macros can be used to read and write +the values of entries. +However, users of the hashing routines should never refer directly +to any of the fields of any of the hash-related data structures; +use the procedures and macros defined here. + +.SH KEYWORDS +hash table, key, lookup, search, value diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Init.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Init.3 new file mode 100644 index 0000000000000000000000000000000000000000..b0398a4e126b6f4d87954ac1dbaa767c1affb59e --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Init.3 @@ -0,0 +1,37 @@ +'\" +'\" Copyright (c) 1998-2000 by Scriptics Corporation. +'\" All rights reserved. +'\" +'\" RCS: @(#) $Id: Init.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_Init 3 8.0 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_Init \- find and source initialization script +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +int +\fBTcl_Init\fR(\fIinterp\fR) +.SH ARGUMENTS +.AP Tcl_Interp *interp in +Interpreter to initialize. +.BE + +.SH DESCRIPTION +.PP +\fBTcl_Init\fR is a helper procedure that finds and \fBsource\fR's the +\fBinit.tcl\fR script, which should exist somewhere on the Tcl library +path. On Macintosh systems, it additionally checks for an \fBInit\fR +resource and sources the contents of that resource if \fBinit.tcl\fR +cannot be found. +.PP +\fBTcl_Init\fR is typically called from \fBTcl_AppInit\fR procedures. + +.SH "SEE ALSO" +Tcl_AppInit, Tcl_Main + +.SH KEYWORDS +application, initialization, interpreter diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/InitStubs.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/InitStubs.3 new file mode 100644 index 0000000000000000000000000000000000000000..3ba510e509d9840c4bd89c7590777de17db06d5c --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/InitStubs.3 @@ -0,0 +1,91 @@ +'\" +'\" Copyright (c) 1999 Scriptics Corportation +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: InitStubs.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_InitStubs 3 8.1 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_InitStubs \- initialize the Tcl stubs mechanism +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +char * +\fBTcl_InitStubs\fR(\fIinterp, version, exact\fR) +.SH ARGUMENTS +.AS Tcl_Interp *interp in +.AP Tcl_Interp *interp in +Tcl interpreter handle. +.AP char *version in +A version string consisting of one or more decimal numbers +separated by dots. +.AP int exact in +Non-zero means that only the particular version specified by +\fIversion\fR is acceptable. +Zero means that versions newer than \fIversion\fR are also +acceptable as long as they have the same major version number +as \fIversion\fR. +.BE +.SH INTRODUCTION +.PP +The Tcl stubs mechanism defines a way to dynamically bind +extensions to a particular Tcl implementation at run time. +This provides two significant benefits to Tcl users: +.IP 1) 5 +Extensions that use the stubs mechanism can be loaded into +multiple versions of Tcl without being recompiled or +relinked. +.IP 2) 5 +Extensions that use the stubs mechanism can be dynamically +loaded into statically-linked Tcl applications. +.PP +The stubs mechanism accomplishes this by exporting function tables +that define an interface to the Tcl API. The extension then accesses +the Tcl API through offsets into the function table, so there are no +direct references to any of the Tcl library's symbols. This +redirection is transparent to the extension, so an extension writer +can continue to use all public Tcl functions as documented. +.PP +The stubs mechanism requires no changes to applications incorporating +Tcl interpreters. Only developers creating C-based Tcl extensions +need to take steps to use the stubs mechanism with their extensions. +.PP +Enabling the stubs mechanism for an extension requires the following +steps: +.IP 1) 5 +Call \fBTcl_InitStubs\fR in the extension before calling any other +Tcl functions. +.IP 2) 5 +Define the USE_TCL_STUBS symbol. Typically, you would include the +-DUSE_TCL_STUBS flag when compiling the extension. +.IP 3) 5 +Link the extension with the Tcl stubs library instead of the standard +Tcl library. On Unix platforms, the library name is +\fIlibtclstub8.1.a\fR; on Windows platforms, the library name is +\fItclstub81.lib\fR. +.PP +If the extension also requires the Tk API, it must also call +\fBTk_InitStubs\fR to initialize the Tk stubs interface and link +with the Tk stubs libraries. See the \fBTk_InitStubs\fR page for +more information. +.SH DESCRIPTION +\fBTcl_InitStubs\fR attempts to initialize the stub table pointers +and ensure that the correct version of Tcl is loaded. In addition +to an interpreter handle, it accepts as arguments a version number +and a Boolean flag indicating whether the extension requires +an exact version match or not. If \fIexact\fR is 0, then the +extension is indicating that newer versions of Tcl are acceptable +as long as they have the same major version number as \fIversion\fR; +non-zero means that only the specified \fIversion\fR is acceptable. +\fBTcl_InitStubs\fR returns a string containing the actual version +of Tcl satisfying the request, or NULL if the Tcl version is not +acceptable, does not support stubs, or any other error condition occurred. +.SH "SEE ALSO" +\fBTk_InitStubs\fR +.SH KEYWORDS +stubs diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/IntObj.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/IntObj.3 new file mode 100644 index 0000000000000000000000000000000000000000..5465b7b5271c31230b64ba36c84ea08076baf67c --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/IntObj.3 @@ -0,0 +1,104 @@ +'\" +'\" Copyright (c) 1996-1997 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: IntObj.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_IntObj 3 8.0 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_NewIntObj, Tcl_NewLongObj, Tcl_SetIntObj, Tcl_SetLongObj, Tcl_GetIntFromObj, Tcl_GetLongFromObj \- manipulate Tcl objects as integers +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +Tcl_Obj * +\fBTcl_NewIntObj\fR(\fIintValue\fR) +.sp +Tcl_Obj * +\fBTcl_NewLongObj\fR(\fIlongValue\fR) +.sp +\fBTcl_SetIntObj\fR(\fIobjPtr, intValue\fR) +.sp +\fBTcl_SetLongObj\fR(\fIobjPtr, longValue\fR) +.sp +int +\fBTcl_GetIntFromObj\fR(\fIinterp, objPtr, intPtr\fR) +.sp +int +\fBTcl_GetLongFromObj\fR(\fIinterp, objPtr, longPtr\fR) +.SH ARGUMENTS +.AS Tcl_Interp *interp +.AP int intValue in +Integer value used to initialize or set an integer object. +.AP long longValue in +Long integer value used to initialize or set an integer object. +.AP Tcl_Obj *objPtr in/out +For \fBTcl_SetIntObj\fR and \fBTcl_SetLongObj\fR, +this points to the object to be converted to integer type. +For \fBTcl_GetIntFromObj\fR and \fBTcl_GetLongFromObj\fR, +this refers to the object +from which to get an integer or long integer value; +if \fIobjPtr\fR does not already point to an integer object, +an attempt will be made to convert it to one. +.AP Tcl_Interp *interp in/out +If an error occurs during conversion, +an error message is left in the interpreter's result object +unless \fIinterp\fR is NULL. +.AP int *intPtr out +Points to place to store the integer value +obtained by \fBTcl_GetIntFromObj\fR from \fIobjPtr\fR. +.AP long *longPtr out +Points to place to store the long integer value +obtained by \fBTcl_GetLongFromObj\fR from \fIobjPtr\fR. +.BE + +.SH DESCRIPTION +.PP +These procedures are used to create, modify, and read +integer Tcl objects from C code. +\fBTcl_NewIntObj\fR, \fBTcl_NewLongObj\fR, +\fBTcl_SetIntObj\fR, and \fBTcl_SetLongObj\fR +create a new object of integer type +or modify an existing object to have integer type. +\fBTcl_NewIntObj\fR and \fBTcl_SetIntObj\fR set the object to have the +integer value given by \fIintValue\fR, +while \fBTcl_NewLongObj\fR and \fBTcl_SetLongObj\fR +set the object to have the +long integer value given by \fIlongValue\fR. +\fBTcl_NewIntObj\fR and \fBTcl_NewLongObj\fR +return a pointer to a newly created object with reference count zero. +These procedures set the object's type to be integer +and assign the integer value to the object's internal representation +\fIlongValue\fR member. +\fBTcl_SetIntObj\fR and \fBTcl_SetLongObj\fR +invalidate any old string representation and, +if the object is not already an integer object, +free any old internal representation. +.PP +\fBTcl_GetIntFromObj\fR and \fBTcl_GetLongFromObj\fR +attempt to return an integer value from the Tcl object \fIobjPtr\fR. +If the object is not already an integer object, +they will attempt to convert it to one. +If an error occurs during conversion, they return \fBTCL_ERROR\fR +and leave an error message in the interpreter's result object +unless \fIinterp\fR is NULL. +Also, if the long integer held in the object's internal representation +\fIlongValue\fR member can not be represented in a (non-long) integer, +\fBTcl_GetIntFromObj\fR returns \fBTCL_ERROR\fR +and leaves an error message in the interpreter's result object +unless \fIinterp\fR is NULL. +Otherwise, both procedures return \fBTCL_OK\fR and +store the integer or the long integer value +in the address given by \fIintPtr\fR and \fIlongPtr\fR respectively. +If the object is not already an integer object, +the conversion will free any old internal representation. + +.SH "SEE ALSO" +Tcl_NewObj, Tcl_DecrRefCount, Tcl_IncrRefCount, Tcl_GetObjResult + +.SH KEYWORDS +integer, integer object, integer type, internal representation, object, object type, string representation diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Interp.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Interp.3 new file mode 100644 index 0000000000000000000000000000000000000000..929be7b9fe2c6d4635ca73d5b453b5431597c0a5 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Interp.3 @@ -0,0 +1,126 @@ +'\" +'\" Copyright (c) 1989-1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: Interp.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_Interp 3 7.5 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_Interp \- client-visible fields of interpreter structures +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +typedef struct { + char *\fIresult\fR; + Tcl_FreeProc *\fIfreeProc\fR; + int \fIerrorLine\fR; +} Tcl_Interp; + +typedef void Tcl_FreeProc(char *\fIblockPtr\fR); +.BE + +.SH DESCRIPTION +.PP +The \fBTcl_CreateInterp\fR procedure returns a pointer to a Tcl_Interp +structure. This pointer is then passed into other Tcl procedures +to process commands in the interpreter and perform other operations +on the interpreter. Interpreter structures contain many many fields +that are used by Tcl, but only three that may be accessed by +clients: \fIresult\fR, \fIfreeProc\fR, and \fIerrorLine\fR. +.PP +The \fIresult\fR and \fIfreeProc\fR fields are used to return +results or error messages from commands. +This information is returned by command procedures back to \fBTcl_Eval\fR, +and by \fBTcl_Eval\fR back to its callers. +The \fIresult\fR field points to the string that represents the +result or error message, and the \fIfreeProc\fR field tells how +to dispose of the storage for the string when it isn't needed anymore. +The easiest way for command procedures to manipulate these +fields is to call procedures like \fBTcl_SetResult\fR +or \fBTcl_AppendResult\fR; they +will hide all the details of managing the fields. +The description below is for those procedures that manipulate the +fields directly. +.PP +Whenever a command procedure returns, it must ensure +that the \fIresult\fR field of its interpreter points to the string +being returned by the command. +The \fIresult\fR field must always point to a valid string. +If a command wishes to return no result then \fIinterp->result\fR +should point to an empty string. +Normally, results are assumed to be statically allocated, +which means that the contents will not change before the next time +\fBTcl_Eval\fR is called or some other command procedure is invoked. +.VS +In this case, the \fIfreeProc\fR field must be zero. +Alternatively, a command procedure may dynamically +allocate its return value (e.g. using \fBTcl_Alloc\fR) +and store a pointer to it in \fIinterp->result\fR. +In this case, the command procedure must also set \fIinterp->freeProc\fR +to the address of a procedure that can free the value, or \fBTCL_DYNAMIC\fR +if the storage was allocated directly by Tcl or by a call to +\fBTcl_Alloc\fR. +.VE +If \fIinterp->freeProc\fR is non-zero, then Tcl will call \fIfreeProc\fR +to free the space pointed to by \fIinterp->result\fR before it +invokes the next command. +If a client procedure overwrites \fIinterp->result\fR when +\fIinterp->freeProc\fR is non-zero, then it is responsible for calling +\fIfreeProc\fR to free the old \fIinterp->result\fR (the \fBTcl_FreeResult\fR +macro should be used for this purpose). +.PP +\fIFreeProc\fR should have arguments and result that match the +\fBTcl_FreeProc\fR declaration above: it receives a single +argument which is a pointer to the result value to free. +.VS +In most applications \fBTCL_DYNAMIC\fR is the only non-zero value ever +used for \fIfreeProc\fR. +.VE +However, an application may store a different procedure address +in \fIfreeProc\fR in order to use an alternate memory allocator +or in order to do other cleanup when the result memory is freed. +.PP +As part of processing each command, \fBTcl_Eval\fR initializes +\fIinterp->result\fR +and \fIinterp->freeProc\fR just before calling the command procedure for +the command. The \fIfreeProc\fR field will be initialized to zero, +and \fIinterp->result\fR will point to an empty string. Commands that +do not return any value can simply leave the fields alone. +Furthermore, the empty string pointed to by \fIresult\fR is actually +part of an array of \fBTCL_RESULT_SIZE\fR characters (approximately 200). +If a command wishes to return a short string, it can simply copy +it to the area pointed to by \fIinterp->result\fR. Or, it can use +the sprintf procedure to generate a short result string at the location +pointed to by \fIinterp->result\fR. +.PP +It is a general convention in Tcl-based applications that the result +of an interpreter is normally in the initialized state described +in the previous paragraph. +Procedures that manipulate an interpreter's result (e.g. by +returning an error) will generally assume that the result +has been initialized when the procedure is called. +If such a procedure is to be called after the result has been +changed, then \fBTcl_ResetResult\fR should be called first to +reset the result to its initialized state. The direct use of +\fIinterp->result\fR is strongly deprecated (see \fBTcl_SetResult\fR). +.PP +The \fIerrorLine\fR +field is valid only after \fBTcl_Eval\fR returns +a \fBTCL_ERROR\fR return code. In this situation the \fIerrorLine\fR +field identifies the line number of the command being executed when +the error occurred. The line numbers are relative to the command +being executed: 1 means the first line of the command passed to +\fBTcl_Eval\fR, 2 means the second line, and so on. +The \fIerrorLine\fR field is typically used in conjunction with +\fBTcl_AddErrorInfo\fR to report information about where an error +occurred. +\fIErrorLine\fR should not normally be modified except by \fBTcl_Eval\fR. + +.SH KEYWORDS +free, initialized, interpreter, malloc, result diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/LinkVar.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/LinkVar.3 new file mode 100644 index 0000000000000000000000000000000000000000..d9fd3ef1fd1cec2b0deab0e5b51a356e5be062ca --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/LinkVar.3 @@ -0,0 +1,115 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: LinkVar.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_LinkVar 3 7.5 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_LinkVar, Tcl_UnlinkVar, Tcl_UpdateLinkedVar \- link Tcl variable to C variable +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +int +\fBTcl_LinkVar\fR(\fIinterp, varName, addr, type\fR) +.sp +\fBTcl_UnlinkVar\fR(\fIinterp, varName\fR) +.sp +\fBTcl_UpdateLinkedVar\fR(\fIinterp, varName\fR) +.SH ARGUMENTS +.AS Tcl_Interp writable +.AP Tcl_Interp *interp in +Interpreter that contains \fIvarName\fR. +Also used by \fBTcl_LinkVar\fR to return error messages. +.AP char *varName in +Name of global variable. Must be in writable memory: Tcl may make +temporary modifications to it while parsing the variable name. +.AP char *addr in +Address of C variable that is to be linked to \fIvarName\fR. +.AP int type in +Type of C variable. Must be one of TCL_LINK_INT, TCL_LINK_DOUBLE, +TCL_LINK_BOOLEAN, or TCL_LINK_STRING, optionally OR'ed with +TCL_LINK_READ_ONLY to make Tcl variable read-only. +.BE + +.SH DESCRIPTION +.PP +\fBTcl_LinkVar\fR uses variable traces to keep the Tcl variable +named by \fIvarName\fR in sync with the C variable at the address +given by \fIaddr\fR. +Whenever the Tcl variable is read the value of the C variable will +be returned, and whenever the Tcl variable is written the C +variable will be updated to have the same value. +\fBTcl_LinkVar\fR normally returns TCL_OK; if an error occurs +while setting up the link (e.g. because \fIvarName\fR is the +name of array) then TCL_ERROR is returned and the interpreter's result +contains an error message. +.PP +The \fItype\fR argument specifies the type of the C variable, +and must have one of the following values, optionally OR'ed with +TCL_LINK_READ_ONLY: +.TP +\fBTCL_LINK_INT\fR +The C variable is of type \fBint\fR. +Any value written into the Tcl variable must have a proper integer +form acceptable to \fBTcl_GetInt\fR; attempts to write +non-integer values into \fIvarName\fR will be rejected with +Tcl errors. +.TP +\fBTCL_LINK_DOUBLE\fR +The C variable is of type \fBdouble\fR. +Any value written into the Tcl variable must have a proper real +form acceptable to \fBTcl_GetDouble\fR; attempts to write +non-real values into \fIvarName\fR will be rejected with +Tcl errors. +.TP +\fBTCL_LINK_BOOLEAN\fR +The C variable is of type \fBint\fR. +If its value is zero then it will read from Tcl as ``0''; +otherwise it will read from Tcl as ``1''. +Whenever \fIvarName\fR is +modified, the C variable will be set to a 0 or 1 value. +Any value written into the Tcl variable must have a proper boolean +form acceptable to \fBTcl_GetBoolean\fR; attempts to write +non-boolean values into \fIvarName\fR will be rejected with +Tcl errors. +.TP +\fBTCL_LINK_STRING\fR +The C variable is of type \fBchar *\fR. +.VS +If its value is not null then it must be a pointer to a string +allocated with \fBTcl_Alloc\fR. +.VE +Whenever the Tcl variable is modified the current C string will be +freed and new memory will be allocated to hold a copy of the variable's +new value. +If the C variable contains a null pointer then the Tcl variable +will read as ``NULL''. +.PP +If the TCL_LINK_READ_ONLY flag is present in \fItype\fR then the +variable will be read-only from Tcl, so that its value can only be +changed by modifying the C variable. +Attempts to write the variable from Tcl will be rejected with errors. +.PP +\fBTcl_UnlinkVar\fR removes the link previously set up for the +variable given by \fIvarName\fR. If there does not exist a link +for \fIvarName\fR then the procedure has no effect. +.PP +\fBTcl_UpdateLinkedVar\fR may be invoked after the C variable has +changed to force the Tcl variable to be updated immediately. +In many cases this procedure is not needed, since any attempt to +read the Tcl variable will return the latest value of the C variable. +However, if a trace has been set on the Tcl variable (such as a +Tk widget that wishes to display the value of the variable), the +trace will not trigger when the C variable has changed. +\fBTcl_UpdateLinkedVar\fR ensures that any traces on the Tcl +variable are invoked. + +.SH KEYWORDS +boolean, integer, link, read-only, real, string, traces, variable diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/ListObj.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/ListObj.3 new file mode 100644 index 0000000000000000000000000000000000000000..258f6940fc4dada448985ec286c58acb1e6ae0c3 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/ListObj.3 @@ -0,0 +1,247 @@ +'\" +'\" Copyright (c) 1996-1997 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: ListObj.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_ListObj 3 8.0 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_ListObjAppendList, Tcl_ListObjAppendElement, Tcl_NewListObj, Tcl_SetListObj, Tcl_ListObjGetElements, Tcl_ListObjLength, Tcl_ListObjIndex, Tcl_ListObjReplace \- manipulate Tcl objects as lists +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +int +\fBTcl_ListObjAppendList\fR(\fIinterp, listPtr, elemListPtr\fR) +.sp +int +\fBTcl_ListObjAppendElement\fR(\fIinterp, listPtr, objPtr\fR) +.sp +Tcl_Obj * +\fBTcl_NewListObj\fR(\fIobjc, objv\fR) +.sp +\fBTcl_SetListObj\fR(\fIobjPtr, objc, objv\fR) +.sp +int +\fBTcl_ListObjGetElements\fR(\fIinterp, listPtr, objcPtr, objvPtr\fR) +.sp +int +\fBTcl_ListObjLength\fR(\fIinterp, listPtr, intPtr\fR) +.sp +int +\fBTcl_ListObjIndex\fR(\fIinterp, listPtr, index, objPtrPtr\fR) +.sp +int +\fBTcl_ListObjReplace\fR(\fIinterp, listPtr, first, count, objc, objv\fR) +.SH ARGUMENTS +.AS Tcl_Interp "*CONST objv[]" out +.AP Tcl_Interp *interp in +If an error occurs while converting an object to be a list object, +an error message is left in the interpreter's result object +unless \fIinterp\fR is NULL. +.AP Tcl_Obj *listPtr in/out +Points to the list object to be manipulated. +If \fIlistPtr\fR does not already point to a list object, +an attempt will be made to convert it to one. +.AP Tcl_Obj *elemListPtr in/out +For \fBTcl_ListObjAppendList\fR, this points to a list object +containing elements to be appended onto \fIlistPtr\fR. +Each element of *\fIelemListPtr\fR will +become a new element of \fIlistPtr\fR. +If *\fIelemListPtr\fR is not NULL and +does not already point to a list object, +an attempt will be made to convert it to one. +.AP Tcl_Obj *objPtr in +For \fBTcl_ListObjAppendElement\fR, +points to the Tcl object that will be appended to \fIlistPtr\fR. +For \fBTcl_SetListObj\fR, +this points to the Tcl object that will be converted to a list object +containing the \fIobjc\fR elements of the array referenced by \fIobjv\fR. +.AP int *objcPtr in +Points to location where \fBTcl_ListObjGetElements\fR +stores the number of element objects in \fIlistPtr\fR. +.AP Tcl_Obj ***objvPtr out +A location where \fBTcl_ListObjGetElements\fR stores a pointer to an array +of pointers to the element objects of \fIlistPtr\fR. +.AP int objc in +The number of Tcl objects that \fBTcl_NewListObj\fR +will insert into a new list object, +and \fBTcl_ListObjReplace\fR will insert into \fIlistPtr\fR. +For \fBTcl_SetListObj\fR, +the number of Tcl objects to insert into \fIobjPtr\fR. +.VS +.AP Tcl_Obj "*CONST\ objv[]" in +An array of pointers to objects. +\fBTcl_NewListObj\fR will insert these objects into a new list object +and \fBTcl_ListObjReplace\fR will insert them into an existing \fIlistPtr\fR. +Each object will become a separate list element. +.VE +.AP int *intPtr out +Points to location where \fBTcl_ListObjLength\fR +stores the length of the list. +.AP int index in +Index of the list element that \fBTcl_ListObjIndex\fR +is to return. +The first element has index 0. +.AP Tcl_Obj **objPtrPtr out +Points to place where \fBTcl_ListObjIndex\fR is to store +a pointer to the resulting list element object. +.AP int first in +Index of the starting list element that \fBTcl_ListObjReplace\fR +is to replace. +The list's first element has index 0. +.AP int count in +The number of elements that \fBTcl_ListObjReplace\fR +is to replace. +.BE + +.SH DESCRIPTION +.PP +Tcl list objects have an internal representation that supports +the efficient indexing and appending. +The procedures described in this man page are used to +create, modify, index, and append to Tcl list objects from C code. +.PP +\fBTcl_ListObjAppendList\fR and \fBTcl_ListObjAppendElement\fR +both add one or more objects +to the end of the list object referenced by \fIlistPtr\fR. +\fBTcl_ListObjAppendList\fR appends each element of the list object +referenced by \fIelemListPtr\fR while +\fBTcl_ListObjAppendElement\fR appends the single object +referenced by \fIobjPtr\fR. +Both procedures will convert the object referenced by \fIlistPtr\fR +to a list object if necessary. +If an error occurs during conversion, +both procedures return \fBTCL_ERROR\fR and leave an error message +in the interpreter's result object if \fIinterp\fR is not NULL. +Similarly, if \fIelemListPtr\fR does not already refer to a list object, +\fBTcl_ListObjAppendList\fR will attempt to convert it to one +and if an error occurs during conversion, +will return \fBTCL_ERROR\fR +and leave an error message in the interpreter's result object +if interp is not NULL. +Both procedures invalidate any old string representation of \fIlistPtr\fR +and, if it was converted to a list object, +free any old internal representation. +Similarly, \fBTcl_ListObjAppendList\fR frees any old internal representation +of \fIelemListPtr\fR if it converts it to a list object. +After appending each element in \fIelemListPtr\fR, +\fBTcl_ListObjAppendList\fR increments the element's reference count +since \fIlistPtr\fR now also refers to it. +For the same reason, \fBTcl_ListObjAppendElement\fR +increments \fIobjPtr\fR's reference count. +If no error occurs, +the two procedures return \fBTCL_OK\fR after appending the objects. +.PP +\fBTcl_NewListObj\fR and \fBTcl_SetListObj\fR +create a new object or modify an existing object to hold +the \fIobjc\fR elements of the array referenced by \fIobjv\fR +where each element is a pointer to a Tcl object. +If \fIobjc\fR is less than or equal to zero, +they return an empty object. +The new object's string representation is left invalid. +The two procedures increment the reference counts +of the elements in \fIobjc\fR since the list object now refers to them. +The new list object returned by \fBTcl_NewListObj\fR +has reference count zero. +.PP +\fBTcl_ListObjGetElements\fR returns a count and a pointer to an array of +the elements in a list object. It returns the count by storing it in the +address \fIobjcPtr\fR. Similarly, it returns the array pointer by storing +it in the address \fIobjvPtr\fR. +The memory pointed to is managed by Tcl and should not be freed by the +caller. +If \fIlistPtr\fR is not already a list object, \fBTcl_ListObjGetElements\fR +will attempt to convert it to one; if the conversion fails, it returns +\fBTCL_ERROR\fR and leaves an error message in the interpreter's result +object if \fIinterp\fR is not NULL. +Otherwise it returns \fBTCL_OK\fR after storing the count and array pointer. +.PP +\fBTcl_ListObjLength\fR returns the number of elements in the list object +referenced by \fIlistPtr\fR. +It returns this count by storing an integer in the address \fIintPtr\fR. +If the object is not already a list object, +\fBTcl_ListObjLength\fR will attempt to convert it to one; +if the conversion fails, it returns \fBTCL_ERROR\fR +and leaves an error message in the interpreter's result object +if \fIinterp\fR is not NULL. +Otherwise it returns \fBTCL_OK\fR after storing the list's length. +.PP +The procedure \fBTcl_ListObjIndex\fR returns a pointer to the object +at element \fIindex\fR in the list referenced by \fIlistPtr\fR. +It returns this object by storing a pointer to it +in the address \fIobjPtrPtr\fR. +If \fIlistPtr\fR does not already refer to a list object, +\fBTcl_ListObjIndex\fR will attempt to convert it to one; +if the conversion fails, it returns \fBTCL_ERROR\fR +and leaves an error message in the interpreter's result object +if \fIinterp\fR is not NULL. +If the index is out of range, +that is, \fIindex\fR is negative or +greater than or equal to the number of elements in the list, +\fBTcl_ListObjIndex\fR stores a NULL in \fIobjPtrPtr\fR +and returns \fBTCL_OK\fR. +Otherwise it returns \fBTCL_OK\fR after storing the element's +object pointer. +The reference count for the list element is not incremented; +the caller must do that if it needs to retain a pointer to the element. +.PP +\fBTcl_ListObjReplace\fR replaces zero or more elements +of the list referenced by \fIlistPtr\fR +with the \fIobjc\fR objects in the array referenced by \fIobjv\fR. +If \fIlistPtr\fR does not point to a list object, +\fBTcl_ListObjReplace\fR will attempt to convert it to one; +if the conversion fails, it returns \fBTCL_ERROR\fR +and leaves an error message in the interpreter's result object +if \fIinterp\fR is not NULL. +Otherwise, it returns \fBTCL_OK\fR after replacing the objects. +If \fIobjv\fR is NULL, no new elements are added. +If the argument \fIfirst\fR is zero or negative, +it refers to the first element. +If \fIfirst\fR is greater than or equal to the +number of elements in the list, then no elements are deleted; +the new elements are appended to the list. +\fIcount\fR gives the number of elements to replace. +If \fIcount\fR is zero or negative then no elements are deleted; +the new elements are simply inserted before the one +designated by \fIfirst\fR. +\fBTcl_ListObjReplace\fR invalidates \fIlistPtr\fR's +old string representation. +The reference counts of any elements inserted from \fIobjv\fR +are incremented since the resulting list now refers to them. +Similarly, the reference counts for any replaced objects are decremented. +.PP +Because \fBTcl_ListObjReplace\fR combines +both element insertion and deletion, +it can be used to implement a number of list operations. +For example, the following code inserts the \fIobjc\fR objects +referenced by the array of object pointers \fIobjv\fR +just before the element \fIindex\fR of the list referenced by \fIlistPtr\fR: +.CS +result = Tcl_ListObjReplace(interp, listPtr, index, 0, objc, objv); +.CE +Similarly, the following code appends the \fIobjc\fR objects +referenced by the array \fIobjv\fR +to the end of the list \fIlistPtr\fR: +.CS +result = Tcl_ListObjLength(interp, listPtr, &length); +if (result == TCL_OK) { + result = Tcl_ListObjReplace(interp, listPtr, length, 0, objc, objv); +} +.CE +The \fIcount\fR list elements starting at \fIfirst\fR can be deleted +by simply calling \fBTcl_ListObjReplace\fR +with a NULL \fIobjvPtr\fR: +.CS +result = Tcl_ListObjReplace(interp, listPtr, first, count, 0, NULL); +.CE + +.SH "SEE ALSO" +Tcl_NewObj, Tcl_DecrRefCount, Tcl_IncrRefCount, Tcl_GetObjResult + +.SH KEYWORDS +append, index, insert, internal representation, length, list, list object, list type, object, object type, replace, string representation diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Notifier.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Notifier.3 new file mode 100644 index 0000000000000000000000000000000000000000..27d4bca831aa47c6d4f6d79b90c8063c86098c12 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Notifier.3 @@ -0,0 +1,602 @@ +'\" +'\" Copyright (c) 1998-1999 Scriptics Corporation +'\" Copyright (c) 1995-1997 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: Notifier.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Notifier 3 8.1 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_CreateEventSource, Tcl_DeleteEventSource, Tcl_SetMaxBlockTime, Tcl_QueueEvent, Tcl_ThreadQueueEvent, Tcl_ThreadAlert, Tcl_GetCurrentThread, Tcl_DeleteEvents, Tcl_InitNotifier, Tcl_FinalizeNotifier, Tcl_WaitForEvent, Tcl_AlertNotifier, Tcl_SetTimer, Tcl_ServiceAll, Tcl_ServiceEvent, Tcl_GetServiceMode, Tcl_SetServiceMode \- the event queue and notifier interfaces +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +void +\fBTcl_CreateEventSource\fR(\fIsetupProc, checkProc, clientData\fR) +.sp +void +\fBTcl_DeleteEventSource\fR(\fIsetupProc, checkProc, clientData\fR) +.sp +void +\fBTcl_SetMaxBlockTime\fR(\fItimePtr\fR) +.sp +void +\fBTcl_QueueEvent\fR(\fIevPtr, position\fR) +.VS 8.1 +.sp +void +\fBTcl_ThreadQueueEvent\fR(\fIthreadId, evPtr, position\fR) +.sp +void +\fBTcl_ThreadAlert\fR(\fIthreadId, clientData\fR) +.sp +Tcl_ThreadId +\fBTcl_GetCurrentThread\fR() +.sp +void +\fBTcl_DeleteEvents\fR(\fIdeleteProc, clientData\fR) +.sp +ClientData +\fBTcl_InitNotifier\fR() +.sp +void +\fBTcl_FinalizeNotifier\fR(\fIclientData\fR) +.sp +int +\fBTcl_WaitForEvent\fR(\fItimePtr\fR) +.sp +void +\fBTcl_AlertNotifier\fR(\fIclientData\fR) +.sp +void +\fBTcl_SetTimer\fR(\fItimePtr\fR) +.sp +int +\fBTcl_ServiceAll\fR() +.sp +int +\fBTcl_ServiceEvent\fR(\fIflags\fR) +.sp +int +\fBTcl_GetServiceMode\fR() +.sp +int +\fBTcl_SetServiceMode\fR(\fImode\fR) +.VE + +.SH ARGUMENTS +.AS Tcl_EventDeleteProc milliseconds +.AP Tcl_EventSetupProc *setupProc in +Procedure to invoke to prepare for event wait in \fBTcl_DoOneEvent\fR. +.AP Tcl_EventCheckProc *checkProc in +Procedure for \fBTcl_DoOneEvent\fR to invoke after waiting for +events. Checks to see if any events have occurred and, if so, +queues them. +.AP ClientData clientData in +Arbitrary one-word value to pass to \fIsetupProc\fR, \fIcheckProc\fR, or +\fIdeleteProc\fR. +.AP Tcl_Time *timePtr in +Indicates the maximum amount of time to wait for an event. This +is specified as an interval (how long to wait), not an absolute +time (when to wakeup). If the pointer passed to \fBTcl_WaitForEvent\fR +is NULL, it means there is no maximum wait time: wait forever if +necessary. +.AP Tcl_Event *evPtr in +An event to add to the event queue. The storage for the event must +have been allocated by the caller using \fBTcl_Alloc\fR or \fBckalloc\fR. +.AP Tcl_QueuePosition position in +Where to add the new event in the queue: \fBTCL_QUEUE_TAIL\fR, +\fBTCL_QUEUE_HEAD\fR, or \fBTCL_QUEUE_MARK\fR. +.AP Tcl_ThreadId threadId in +A unique identifier for a thread. +.AP Tcl_EventDeleteProc *deleteProc in +Procedure to invoke for each queued event in \fBTcl_DeleteEvents\fR. +.AP int flags in +What types of events to service. These flags are the same as those +passed to \fBTcl_DoOneEvent\fR. +.VS 8.1 +.AP int mode in +Inidicates whether events should be serviced by \fBTcl_ServiceAll\fR. +Must be one of \fBTCL_SERVICE_NONE\fR or \fBTCL_SERVICE_ALL\fR. +.VE +.BE + +.SH INTRODUCTION +.PP +The interfaces described here are used to customize the Tcl event +loop. The two most common customizations are to add new sources of +events and to merge Tcl's event loop with some other event loop, such +as one provided by an application in which Tcl is embedded. Each of +these tasks is described in a separate section below. +.PP +The procedures in this manual entry are the building blocks out of which +the Tcl event notifier is constructed. The event notifier is the lowest +layer in the Tcl event mechanism. It consists of three things: +.IP [1] +Event sources: these represent the ways in which events can be +generated. For example, there is a timer event source that implements +the \fBTcl_CreateTimerHandler\fR procedure and the \fBafter\fR +command, and there is a file event source that implements the +\fBTcl_CreateFileHandler\fR procedure on Unix systems. An event +source must work with the notifier to detect events at the right +times, record them on the event queue, and eventually notify +higher-level software that they have occurred. The procedures +\fBTcl_CreateEventSource\fR, \fBTcl_DeleteEventSource\fR, +and \fBTcl_SetMaxBlockTime\fR, \fBTcl_QueueEvent\fR, and +\fBTcl_DeleteEvents\fR are used primarily by event sources. +.IP [2] +The event queue: for non-threaded applications, +there is a single queue for the whole application, +containing events that have been detected but not yet serviced. Event +sources place events onto the queue so that they may be processed in +order at appropriate times during the event loop. The event queue +guarantees a fair discipline of event handling, so that no event +source can starve the others. It also allows events to be saved for +servicing at a future time. +.VS 8.1 +Threaded applications work in a +similar manner, except that there is a separate event queue for +each thread containing a Tcl interpreter. +\fBTcl_QueueEvent\fR is used (primarily +by event sources) to add events to the event queue and +\fBTcl_DeleteEvents\fR is used to remove events from the queue without +processing them. In a threaded application, \fBTcl_QueueEvent\fR adds +an event to the current thread's queue, and \fBTcl_ThreadQueueEvent\fR +adds an event to a queue in a specific thread. +.IP [3] +The event loop: in order to detect and process events, the application +enters a loop that waits for events to occur, places them on the event +queue, and then processes them. Most applications will do this by +calling the procedure \fBTcl_DoOneEvent\fR, which is described in a +separate manual entry. +.PP +Most Tcl applications need not worry about any of the internals of +the Tcl notifier. However, the notifier now has enough flexibility +to be retargeted either for a new platform or to use an external event +loop (such as the Motif event loop, when Tcl is embedded in a Motif +application). The procedures \fBTcl_WaitForEvent\fR and +\fBTcl_SetTimer\fR are normally implemented by Tcl, but may be +replaced with new versions to retarget the notifier (the +\fBTcl_InitNotifier\fR, \fBTcl_AlertNotifier\fR, +\fBTcl_FinalizeNotifier\fR, \fBTcl_Sleep\fR, +\fBTcl_CreateFileHandler\fR, and \fBTcl_DeleteFileHandler\fR must +also be replaced; see CREATING A NEW NOTIFIER below for details). +The procedures \fBTcl_ServiceAll\fR, \fBTcl_ServiceEvent\fR, +\fBTcl_GetServiceMode\fR, and \fBTcl_SetServiceMode\fR are provided +to help connect Tcl's event loop to an external event loop such as +Motif's. +.SH "NOTIFIER BASICS" +.VE +.PP +The easiest way to understand how the notifier works is to consider +what happens when \fBTcl_DoOneEvent\fR is called. +\fBTcl_DoOneEvent\fR is passed a \fIflags\fR argument that indicates +what sort of events it is OK to process and also whether or not to +block if no events are ready. \fBTcl_DoOneEvent\fR does the following +things: +.IP [1] +Check the event queue to see if it contains any events that can +be serviced. If so, service the first possible event, remove it +.VS 8.1 +from the queue, and return. It does this by calling +\fBTcl_ServiceEvent\fR and passing in the \fIflags\fR argument. +.VE +.IP [2] +Prepare to block for an event. To do this, \fBTcl_DoOneEvent\fR +invokes a \fIsetup procedure\fR in each event source. +The event source will perform event-source specific initialization and +.VS 8.1 +possibly call \fBTcl_SetMaxBlockTime\fR to limit how long +.VE +\fBTcl_WaitForEvent\fR will block if no new events occur. +.IP [3] +Call \fBTcl_WaitForEvent\fR. This procedure is implemented differently +on different platforms; it waits for an event to occur, based on the +information provided by the event sources. +It may cause the application to block if \fItimePtr\fR specifies +an interval other than 0. +\fBTcl_WaitForEvent\fR returns when something has happened, +such as a file becoming readable or the interval given by \fItimePtr\fR +expiring. If there are no events for \fBTcl_WaitForEvent\fR to +wait for, so that it would block forever, then it returns immediately +and \fBTcl_DoOneEvent\fR returns 0. +.IP [4] +Call a \fIcheck procedure\fR in each event source. The check +procedure determines whether any events of interest to this source +occurred. If so, the events are added to the event queue. +.IP [5] +Check the event queue to see if it contains any events that can +be serviced. If so, service the first possible event, remove it +from the queue, and return. +.IP [6] +See if there are idle callbacks pending. If so, invoke all of them and +return. +.IP [7] +Either return 0 to indicate that no events were ready, or go back to +step [2] if blocking was requested by the caller. + +.SH "CREATING A NEW EVENT SOURCE" +.PP +An event source consists of three procedures invoked by the notifier, +plus additional C procedures that are invoked by higher-level code +to arrange for event-driven callbacks. The three procedures called +by the notifier consist of the setup and check procedures described +above, plus an additional procedure that is invoked when an event +is removed from the event queue for servicing. +.PP +The procedure \fBTcl_CreateEventSource\fR creates a new event source. +Its arguments specify the setup procedure and check procedure for +the event source. +\fISetupProc\fR should match the following prototype: +.CS +typedef void Tcl_EventSetupProc( + ClientData \fIclientData\fR, + int \fIflags\fR); +.CE +The \fIclientData\fR argument will be the same as the \fIclientData\fR +argument to \fBTcl_CreateEventSource\fR; it is typically used to +point to private information managed by the event source. +The \fIflags\fR argument will be the same as the \fIflags\fR +argument passed to \fBTcl_DoOneEvent\fR except that it will never +be 0 (\fBTcl_DoOneEvent\fR replaces 0 with \fBTCL_ALL_EVENTS\fR). +\fIFlags\fR indicates what kinds of events should be considered; +if the bit corresponding to this event source isn't set, the event +source should return immediately without doing anything. For +example, the file event source checks for the \fBTCL_FILE_EVENTS\fR +bit. +.PP +\fISetupProc\fR's job is to make sure that the application wakes up +when events of the desired type occur. This is typically done in a +platform-dependent fashion. For example, under Unix an event source +might call \fBTcl_CreateFileHandler\fR; under Windows it might +request notification with a Windows event. For timer-driven event +sources such as timer events or any polled event, the event source +can call \fBTcl_SetMaxBlockTime\fR to force the application to wake +up after a specified time even if no events have occurred. +.VS 8.1 +If no event source calls \fBTcl_SetMaxBlockTime\fR +then \fBTcl_WaitForEvent\fR will wait as long as necessary for an +event to occur; otherwise, it will only wait as long as the shortest +interval passed to \fBTcl_SetMaxBlockTime\fR by one of the event +sources. If an event source knows that it already has events ready to +report, it can request a zero maximum block time. For example, the +setup procedure for the X event source looks to see if there are +events already queued. If there are, it calls +\fBTcl_SetMaxBlockTime\fR with a 0 block time so that +\fBTcl_WaitForEvent\fR does not block if there is no new data on the X +connection. +.VE +The \fItimePtr\fR argument to \fBTcl_WaitForEvent\fR points to +a structure that describes a time interval in seconds and +microseconds: +.CS +typedef struct Tcl_Time { + long \fIsec\fR; + long \fIusec\fR; +} Tcl_Time; +.CE +The \fIusec\fR field should be less than 1000000. +.PP +.VS 8.1 +Information provided to \fBTcl_SetMaxBlockTime\fR +is only used for the next call to \fBTcl_WaitForEvent\fR; it is +discarded after \fBTcl_WaitForEvent\fR returns. +.VE +The next time an event wait is done each of the event sources' +setup procedures will be called again, and they can specify new +information for that event wait. +.PP +.VS 8.1 +If the application uses an external event loop rather than +\fBTcl_DoOneEvent\fR, the event sources may need to call +\fBTcl_SetMaxBlockTime\fR at other times. For example, if a new event +handler is registered that needs to poll for events, the event source +may call \fBTcl_SetMaxBlockTime\fR to set the block time to zero to +force the external event loop to call Tcl. In this case, +\fBTcl_SetMaxBlockTime\fR invokes \fBTcl_SetTimer\fR with the shortest +interval seen since the last call to \fBTcl_DoOneEvent\fR or +\fBTcl_ServiceAll\fR. +.PP +In addition to the generic procedure \fBTcl_SetMaxBlockTime\fR, other +platform-specific procedures may also be available for +\fIsetupProc\fR, if there is additional information needed by +\fBTcl_WaitForEvent\fR on that platform. For example, on Unix systems +the \fBTcl_CreateFileHandler\fR interface can be used to wait for file events. +.VE +.PP +The second procedure provided by each event source is its check +procedure, indicated by the \fIcheckProc\fR argument to +\fBTcl_CreateEventSource\fR. \fICheckProc\fR must match the +following prototype: +.CS +typedef void Tcl_EventCheckProc( + ClientData \fIclientData\fR, + int \fIflags\fR); +.CE +The arguments to this procedure are the same as those for \fIsetupProc\fR. +\fBCheckProc\fR is invoked by \fBTcl_DoOneEvent\fR after it has waited +for events. Presumably at least one event source is now prepared to +queue an event. \fBTcl_DoOneEvent\fR calls each of the event sources +in turn, so they all have a chance to queue any events that are ready. +The check procedure does two things. First, it must see if any events +have triggered. Different event sources do this in different ways. +.PP +If an event source's check procedure detects an interesting event, it +must add the event to Tcl's event queue. To do this, the event source +calls \fBTcl_QueueEvent\fR. The \fIevPtr\fR argument is a pointer to +a dynamically allocated structure containing the event (see below for +more information on memory management issues). Each event source can +define its own event structure with whatever information is relevant +to that event source. However, the first element of the structure +must be a structure of type \fBTcl_Event\fR, and the address of this +structure is used when communicating between the event source and the +rest of the notifier. A \fBTcl_Event\fR has the following definition: +.CS +typedef struct { + Tcl_EventProc *\fIproc\fR; + struct Tcl_Event *\fInextPtr\fR; +} Tcl_Event; +.CE +The event source must fill in the \fIproc\fR field of +the event before calling \fBTcl_QueueEvent\fR. +The \fInextPtr\fR is used to link together the events in the queue +and should not be modified by the event source. +.PP +An event may be added to the queue at any of three positions, depending +on the \fIposition\fR argument to \fBTcl_QueueEvent\fR: +.IP \fBTCL_QUEUE_TAIL\fR 24 +Add the event at the back of the queue, so that all other pending +events will be serviced first. This is almost always the right +place for new events. +.IP \fBTCL_QUEUE_HEAD\fR 24 +Add the event at the front of the queue, so that it will be serviced +before all other queued events. +.IP \fBTCL_QUEUE_MARK\fR 24 +Add the event at the front of the queue, unless there are other +events at the front whose position is \fBTCL_QUEUE_MARK\fR; if so, +add the new event just after all other \fBTCL_QUEUE_MARK\fR events. +This value of \fIposition\fR is used to insert an ordered sequence of +events at the front of the queue, such as a series of +Enter and Leave events synthesized during a grab or ungrab operation +in Tk. +.PP +.VS 8.1 +When it is time to handle an event from the queue (steps 1 and 4 +above) \fBTcl_ServiceEvent\fR will invoke the \fIproc\fR specified +.VE +in the first queued \fBTcl_Event\fR structure. +\fIProc\fR must match the following prototype: +.CS +typedef int Tcl_EventProc( + Tcl_Event *\fIevPtr\fR, + int \fIflags\fR); +.CE +The first argument to \fIproc\fR is a pointer to the event, which will +be the same as the first argument to the \fBTcl_QueueEvent\fR call that +added the event to the queue. +The second argument to \fIproc\fR is the \fIflags\fR argument for the +.VS 8.1 +current call to \fBTcl_ServiceEvent\fR; this is used by the event source +.VE +to return immediately if its events are not relevant. +.PP +It is up to \fIproc\fR to handle the event, typically by invoking +one or more Tcl commands or C-level callbacks. +Once the event source has finished handling the event it returns 1 +to indicate that the event can be removed from the queue. +If for some reason the event source decides that the event cannot +be handled at this time, it may return 0 to indicate that the event +.VS 8.1 +should be deferred for processing later; in this case \fBTcl_ServiceEvent\fR +.VE +will go on to the next event in the queue and attempt to service it. +There are several reasons why an event source might defer an event. +One possibility is that events of this type are excluded by the +\fIflags\fR argument. +For example, the file event source will always return 0 if the +\fBTCL_FILE_EVENTS\fR bit isn't set in \fIflags\fR. +Another example of deferring events happens in Tk if +\fBTk_RestrictEvents\fR has been invoked to defer certain kinds +of window events. +.PP +.VS 8.1 +When \fIproc\fR returns 1, \fBTcl_ServiceEvent\fR will remove the +event from the event queue and free its storage. +Note that the storage for an event must be allocated by +the event source (using \fBTcl_Alloc\fR or the Tcl macro \fBckalloc\fR) +before calling \fBTcl_QueueEvent\fR, but it +will be freed by \fBTcl_ServiceEvent\fR, not by the event source. +.PP +Threaded applications work in a +similar manner, except that there is a separate event queue for +each thread containing a Tcl interpreter. +Calling \fBTcl_QueueEvent\fR in a multithreaded application adds +an event to the current thread's queue. +To add an event to another thread's queue, use \fBTcl_ThreadQueueEvent\fR. +\fBTcl_ThreadQueueEvent\fR accepts as an argument a Tcl_ThreadId argument, +which uniquely identifies a thread in a Tcl application. To obtain the +Tcl_ThreadID for the current thread, use the \fBTcl_GetCurrentThread\fR +procedure. (A thread would then need to pass this identifier to other +threads for those threads to be able to add events to its queue.) +After adding an event to another thread's queue, you then typically +need to call \fBTcl_ThreadAlert\fR to "wake up" that thread's notifier to +alert it to the new event. +.PP +\fBTcl_DeleteEvents\fR can be used to explicitly remove one or more +events from the event queue. \fBTcl_DeleteEvents\fR calls \fIproc\fR +for each event in the queue, deleting those for with the procedure +returns 1. Events for which the procedure returns 0 are left in the +queue. \fIProc\fR should match the following prototype: +.CS +typedef int Tcl_EventDeleteProc( + Tcl_Event *\fIevPtr\fR, + ClientData \fIclientData\fR); +.CE +The \fIclientData\fR argument will be the same as the \fIclientData\fR +argument to \fBTcl_DeleteEvents\fR; it is typically used to point to +private information managed by the event source. The \fIevPtr\fR will +point to the next event in the queue. +.PP +\fBTcl_DeleteEventSource\fR deletes an event source. The \fIsetupProc\fR, +\fIcheckProc\fR, and \fIclientData\fR arguments must exactly match those +provided to the \fBTcl_CreateEventSource\fR for the event source to be deleted. +If no such source exists, \fBTcl_DeleteEventSource\fR has no effect. +.VE + +.SH "CREATING A NEW NOTIFIER" +.PP +The notifier consists of all the procedures described in this manual +entry, plus \fBTcl_DoOneEvent\fR and \fBTcl_Sleep\fR, which are +.VS 8.1 +available on all platforms, and \fBTcl_CreateFileHandler\fR and +\fBTcl_DeleteFileHandler\fR, which are Unix-specific. Most of these +procedures are generic, in that they are the same for all notifiers. +However, eight of the procedures are notifier-dependent: +\fBTcl_InitNotifier\fR, \fBTcl_AlertNotifier\fR, \fBTcl_FinalizeNotifier\fR, +\fBTcl_SetTimer\fR, \fBTcl_Sleep\fR, \fBTcl_WaitForEvent\fR, +\fBTcl_CreateFileHandler\fR and \fBTcl_DeleteFileHandler\fR. To +support a new platform or to integrate Tcl with an +application-specific event loop, you must write new versions of these +procedures. +.PP +\fBTcl_InitNotifier\fR initializes the notifier state and returns +a handle to the notifier state. Tcl calls this +procedure when intializing a Tcl interpreter. Similarly, +\fBTcl_FinalizeNotifier\fR shuts down the notifier, and is +called by \fBTcl_Finalize\fR when shutting down a Tcl interpreter. +.PP +\fBTcl_WaitForEvent\fR is the lowest-level procedure in the notifier; +it is responsible for waiting for an ``interesting'' event to occur or +for a given time to elapse. Before \fBTcl_WaitForEvent\fR is invoked, +each of the event sources' setup procedure will have been invoked. +The \fItimePtr\fR argument to +\fBTcl_WaitForEvent\fR gives the maximum time to block for an event, +based on calls to \fBTcl_SetMaxBlockTime\fR made by setup procedures +and on other information (such as the \fBTCL_DONT_WAIT\fR bit in +\fIflags\fR). +.PP +Ideally, \fBTcl_WaitForEvent\fR should only wait for an event +to occur; it should not actually process the event in any way. +Later on, the +event sources will process the raw events and create Tcl_Events on +the event queue in their \fIcheckProc\fR procedures. +However, on some platforms (such as Windows) this isn't possible; +events may be processed in \fBTcl_WaitForEvent\fR, including queuing +Tcl_Events and more (for example, callbacks for native widgets may be +invoked). The return value from \fBTcl_WaitForEvent\fR must be either +0, 1, or \-1. On platforms such as Windows where events get processed in +\fBTcl_WaitForEvent\fR, a return value of 1 means that there may be more +events still pending that haven't been processed. This is a sign to the +caller that it must call \fBTcl_WaitForEvent\fR again if it wants all +pending events to be processed. A 0 return value means that calling +\fBTcl_WaitForEvent\fR again will not have any effect: either this is a +platform where \fBTcl_WaitForEvent\fR only waits without doing any event +processing, or \fBTcl_WaitForEvent\fR knows for sure that there are no +additional events to process (e.g. it returned because the time +elapsed). Finally, a return value of \-1 means that the event loop is +no longer operational and the application should probably unwind and +terminate. Under Windows this happens when a WM_QUIT message is received; +under Unix it happens when \fBTcl_WaitForEvent\fR would have waited +forever because there were no active event sources and the timeout was +infinite. +.PP +\fBTcl_AlertNotifier\fR is used in multithreaded applications to allow +any thread to "wake up" the notifier to alert it to new events on its +queue. \fBTcl_AlertNotifier\fR requires as an argument the notifier +handle returned by \fBTcl_InitNotifier\fR. +.PP +If the notifier will be used with an external event loop, then it must +also support the \fBTcl_SetTimer\fR interface. \fBTcl_SetTimer\fR is +invoked by \fBTcl_SetMaxBlockTime\fR whenever the maximum blocking +time has been reduced. \fBTcl_SetTimer\fR should arrange for the +external event loop to invoke \fBTcl_ServiceAll\fR after the specified +interval even if no events have occurred. This interface is needed +because \fBTcl_WaitForEvent\fR isn't invoked when there is an external +event loop. If the +notifier will only be used from \fBTcl_DoOneEvent\fR, then +\fBTcl_SetTimer\fR need not do anything. +.PP +On Unix systems, the file event source also needs support from the +notifier. The file event source consists of the +\fBTcl_CreateFileHandler\fR and \fBTcl_DeleteFileHandler\fR +procedures, which are described in the \fBTcl_CreateFileHandler\fR +manual page. +.PP +The \fBTcl_Sleep\fR and \fBTcl_DoOneEvent\fR interfaces are described +in their respective manual pages. +.PP +The easiest way to create a new notifier is to look at the code +for an existing notifier, such as the files \fBunix/tclUnixNotfy.c\fR +or \fBwin/tclWinNotify.c\fR in the Tcl source distribution. + +.SH "EXTERNAL EVENT LOOPS" +.PP +The notifier interfaces are designed so that Tcl can be embedded into +applications that have their own private event loops. In this case, +the application does not call \fBTcl_DoOneEvent\fR except in the case +of recursive event loops such as calls to the Tcl commands \fBupdate\fR +or \fBvwait\fR. Most of the time is spent in the external event loop +of the application. In this case the notifier must arrange for the +external event loop to call back into Tcl when something +happens on the various Tcl event sources. These callbacks should +arrange for appropriate Tcl events to be placed on the Tcl event queue. +.PP +Because the external event loop is not calling \fBTcl_DoOneEvent\fR on +a regular basis, it is up to the notifier to arrange for +\fBTcl_ServiceEvent\fR to be called whenever events are pending on the +Tcl event queue. The easiest way to do this is to invoke +\fBTcl_ServiceAll\fR at the end of each callback from the external +event loop. This will ensure that all of the event sources are +polled, any queued events are serviced, and any pending idle handlers +are processed before returning control to the application. In +addition, event sources that need to poll for events can call +\fBTcl_SetMaxBlockTime\fR to force the external event loop to call +Tcl even if no events are available on the system event queue. +.PP +As a side effect of processing events detected in the main external +event loop, Tcl may invoke \fBTcl_DoOneEvent\fR to start a recursive event +loop in commands like \fBvwait\fR. \fBTcl_DoOneEvent\fR will invoke +the external event loop, which will result in callbacks as described +in the preceding paragraph, which will result in calls to +\fBTcl_ServiceAll\fR. However, in these cases it is undesirable to +service events in \fBTcl_ServiceAll\fR. Servicing events there is +unnecessary because control will immediately return to the +external event loop and hence to \fBTcl_DoOneEvent\fR, which can +service the events itself. Furthermore, \fBTcl_DoOneEvent\fR is +supposed to service only a single event, whereas \fBTcl_ServiceAll\fR +normally services all pending events. To handle this situation, +\fBTcl_DoOneEvent\fR sets a flag for \fBTcl_ServiceAll\fR +that causes it to return without servicing any events. +This flag is called the \fIservice mode\fR; +\fBTcl_DoOneEvent\fR restores it to its previous value before it returns. +.PP +In some cases, however, it may be necessary for \fBTcl_ServiceAll\fR +to service events +even when it has been invoked from \fBTcl_DoOneEvent\fR. This happens +when there is yet another recursive event loop invoked via an +event handler called by \fBTcl_DoOneEvent\fR (such as one that is +part of a native widget). In this case, \fBTcl_DoOneEvent\fR may not +have a chance to service events so \fBTcl_ServiceAll\fR must service +them all. Any recursive event loop that calls an external event +loop rather than \fBTcl_DoOneEvent\fR must reset the service mode so +that all events get processed in \fBTcl_ServiceAll\fR. This is done +by invoking the \fBTcl_SetServiceMode\fR procedure. If +\fBTcl_SetServiceMode\fR is passed \fBTCL_SERVICE_NONE\fR, then calls +to \fBTcl_ServiceAll\fR will return immediately without processing any +events. If \fBTcl_SetServiceMode\fR is passed \fBTCL_SERVICE_ALL\fR, +then calls to \fBTcl_ServiceAll\fR will behave normally. +\fBTcl_SetServiceMode\fR returns the previous value of the service +mode, which should be restored when the recursive loop exits. +\fBTcl_GetServiceMode\fR returns the current value of the service +mode. +.VE +.SH "SEE ALSO" +\fBTcl_CreateFileHandler\fR, \fBTcl_DeleteFileHandler\fR, \fBTcl_Sleep\fR, +\fBTcl_DoOneEvent\fR, \fBThread(3)\fR +.SH KEYWORDS +event, notifier, event queue, event sources, file events, timer, idle, service mode, threads diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Object.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Object.3 new file mode 100644 index 0000000000000000000000000000000000000000..f91e79b3f62861dbe5032f28891551d551a0adb4 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Object.3 @@ -0,0 +1,337 @@ +'\" +'\" Copyright (c) 1996-1997 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: Object.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_Obj 3 8.0 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_NewObj, Tcl_DuplicateObj, Tcl_IncrRefCount, Tcl_DecrRefCount, Tcl_IsShared, Tcl_InvalidateStringRep \- manipulate Tcl objects +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +Tcl_Obj * +\fBTcl_NewObj\fR() +.sp +Tcl_Obj * +\fBTcl_DuplicateObj\fR(\fIobjPtr\fR) +.sp +\fBTcl_IncrRefCount\fR(\fIobjPtr\fR) +.sp +\fBTcl_DecrRefCount\fR(\fIobjPtr\fR) +.sp +int +\fBTcl_IsShared\fR(\fIobjPtr\fR) +.sp +\fBTcl_InvalidateStringRep\fR(\fIobjPtr\fR) +.SH ARGUMENTS +.AS Tcl_Obj *objPtr in +.AP Tcl_Obj *objPtr in +Points to an object; +must have been the result of a previous call to \fBTcl_NewObj\fR. +.BE + +.SH INTRODUCTION +.PP +This man page presents an overview of Tcl objects and how they are used. +It also describes generic procedures for managing Tcl objects. +These procedures are used to create and copy objects, +and increment and decrement the count of references (pointers) to objects. +The procedures are used in conjunction with ones +that operate on specific types of objects such as +\fBTcl_GetIntFromObj\fR and \fBTcl_ListObjAppendElement\fR. +The individual procedures are described along with the data structures +they manipulate. +.PP +Tcl's \fIdual-ported\fR objects provide a general-purpose mechanism +for storing and exchanging Tcl values. +They largely replace the use of strings in Tcl. +For example, they are used to store variable values, +command arguments, command results, and scripts. +Tcl objects behave like strings but also hold an internal representation +that can be manipulated more efficiently. +For example, a Tcl list is now represented as an object +that holds the list's string representation +as well as an array of pointers to the objects for each list element. +Dual-ported objects avoid most runtime type conversions. +They also improve the speed of many operations +since an appropriate representation is immediately available. +The compiler itself uses Tcl objects to +cache the instruction bytecodes resulting from compiling scripts. +.PP +The two representations are a cache of each other and are computed lazily. +That is, each representation is only computed when necessary, +it is computed from the other representation, +and, once computed, it is saved. +In addition, a change in one representation invalidates the other one. +As an example, a Tcl program doing integer calculations can +operate directly on a variable's internal machine integer +representation without having to constantly convert +between integers and strings. +Only when it needs a string representing the variable's value, +say to print it, +will the program regenerate the string representation from the integer. +Although objects contain an internal representation, +their semantics are defined in terms of strings: +an up-to-date string can always be obtained, +and any change to the object will be reflected in that string +when the object's string representation is fetched. +Because of this representation invalidation and regeneration, +it is dangerous for extension writers to access +\fBTcl_Obj\fR fields directly. +It is better to access Tcl_Obj information using +procedures like \fBTcl_GetStringFromObj\fR and \fBTcl_GetString\fR. +.PP +Objects are allocated on the heap +and are referenced using a pointer to their \fBTcl_Obj\fR structure. +Objects are shared as much as possible. +This significantly reduces storage requirements +because some objects such as long lists are very large. +Also, most Tcl values are only read and never modified. +This is especially true for procedure arguments, +which can be shared between the caller and the called procedure. +Assignment and argument binding is done by +simply assigning a pointer to the value. +Reference counting is used to determine when it is safe to +reclaim an object's storage. +.PP +Tcl objects are typed. +An object's internal representation is controlled by its type. +Seven types are predefined in the Tcl core +including integer, double, list, and bytecode. +Extension writers can extend the set of types +by using the procedure \fBTcl_RegisterObjType\fR . + +.SH "THE TCL_OBJ STRUCTURE" +.PP +Each Tcl object is represented by a \fBTcl_Obj\fR structure +which is defined as follows. +.CS +typedef struct Tcl_Obj { + int \fIrefCount\fR; + char *\fIbytes\fR; + int \fIlength\fR; + Tcl_ObjType *\fItypePtr\fR; + union { + long \fIlongValue\fR; + double \fIdoubleValue\fR; + VOID *\fIotherValuePtr\fR; + struct { + VOID *\fIptr1\fR; + VOID *\fIptr2\fR; + } \fItwoPtrValue\fR; + } \fIinternalRep\fR; +} Tcl_Obj; +.CE +The \fIbytes\fR and the \fIlength\fR members together hold +an object's string representation, +which is a \fIcounted\fR or \fIbinary string\fR +that may contain binary data with embedded null bytes. +\fIbytes\fR points to the first byte of the string representation. +The \fIlength\fR member gives the number of bytes. +The byte array must always have a null after the last byte, +at offset \fIlength\fR; +this allows string representations that do not contain nulls +to be treated as conventional null-terminated C strings. +C programs use \fBTcl_GetStringFromObj\fR and \fBTcl_GetString\fR to get +an object's string representation. +If \fIbytes\fR is NULL, +the string representation is invalid. +.PP +An object's type manages its internal representation. +The member \fItypePtr\fR points to the Tcl_ObjType structure +that describes the type. +If \fItypePtr\fR is NULL, +the internal representation is invalid. +.PP +The \fIinternalRep\fR union member holds +an object's internal representation. +This is either a (long) integer, a double-precision floating point number, +a pointer to a value containing additional information +needed by the object's type to represent the object, +or two arbitrary pointers. +.PP +The \fIrefCount\fR member is used to tell when it is safe to free +an object's storage. +It holds the count of active references to the object. +Maintaining the correct reference count is a key responsibility +of extension writers. +Reference counting is discussed below +in the section \fBSTORAGE MANAGEMENT OF OBJECTS\fR. +.PP +Although extension writers can directly access +the members of a Tcl_Obj structure, +it is much better to use the appropriate procedures and macros. +For example, extension writers should never +read or update \fIrefCount\fR directly; +they should use macros such as +\fBTcl_IncrRefCount\fR and \fBTcl_IsShared\fR instead. +.PP +A key property of Tcl objects is that they hold two representations. +An object typically starts out containing only a string representation: +it is untyped and has a NULL \fItypePtr\fR. +An object containing an empty string or a copy of a specified string +is created using \fBTcl_NewObj\fR or \fBTcl_NewStringObj\fR respectively. +An object's string value is gotten with +\fBTcl_GetStringFromObj\fR or \fBTcl_GetString\fR +and changed with \fBTcl_SetStringObj\fR. +If the object is later passed to a procedure like \fBTcl_GetIntFromObj\fR +that requires a specific internal representation, +the procedure will create one and set the object's \fItypePtr\fR. +The internal representation is computed from the string representation. +An object's two representations are duals of each other: +changes made to one are reflected in the other. +For example, \fBTcl_ListObjReplace\fR will modify an object's +internal representation and the next call to \fBTcl_GetStringFromObj\fR +or \fBTcl_GetString\fR will reflect that change. +.PP +Representations are recomputed lazily for efficiency. +A change to one representation made by a procedure +such as \fBTcl_ListObjReplace\fR is not reflected immediately +in the other representation. +Instead, the other representation is marked invalid +so that it is only regenerated if it is needed later. +Most C programmers never have to be concerned with how this is done +and simply use procedures such as \fBTcl_GetBooleanFromObj\fR or +\fBTcl_ListObjIndex\fR. +Programmers that implement their own object types +must check for invalid representations +and mark representations invalid when necessary. +The procedure \fBTcl_InvalidateStringRep\fR is used +to mark an object's string representation invalid and to +free any storage associated with the old string representation. +.PP +Objects usually remain one type over their life, +but occasionally an object must be converted from one type to another. +For example, a C program might build up a string in an object +with repeated calls to \fBTcl_AppendToObj\fR, +and then call \fBTcl_ListObjIndex\fR to extract a list element from +the object. +The same object holding the same string value +can have several different internal representations +at different times. +Extension writers can also force an object to be converted from one type +to another using the \fBTcl_ConvertToType\fR procedure. +Only programmers that create new object types need to be concerned +about how this is done. +A procedure defined as part of the object type's implementation +creates a new internal representation for an object +and changes its \fItypePtr\fR. +See the man page for \fBTcl_RegisterObjType\fR +to see how to create a new object type. + +.SH "EXAMPLE OF THE LIFETIME OF AN OBJECT" +.PP +As an example of the lifetime of an object, +consider the following sequence of commands: +.CS +\fBset x 123\fR +.CE +This assigns to \fIx\fR an untyped object whose +\fIbytes\fR member points to \fB123\fR and \fIlength\fR member contains 3. +The object's \fItypePtr\fR member is NULL. +.CS +\fBputs "x is $x"\fR +.CE +\fIx\fR's string representation is valid (since \fIbytes\fR is non-NULL) +and is fetched for the command. +.CS +\fBincr x\fR +.CE +The \fBincr\fR command first gets an integer from \fIx\fR's object +by calling \fBTcl_GetIntFromObj\fR. +This procedure checks whether the object is already an integer object. +Since it is not, it converts the object +by setting the object's \fIinternalRep.longValue\fR member +to the integer \fB123\fR +and setting the object's \fItypePtr\fR +to point to the integer Tcl_ObjType structure. +Both representations are now valid. +\fBincr\fR increments the object's integer internal representation +then invalidates its string representation +(by calling \fBTcl_InvalidateStringRep\fR) +since the string representation +no longer corresponds to the internal representation. +.CS +\fBputs "x is now $x"\fR +.CE +The string representation of \fIx\fR's object is needed +and is recomputed. +The string representation is now \fB124\fR. +and both representations are again valid. + +.SH "STORAGE MANAGEMENT OF OBJECTS" +.PP +Tcl objects are allocated on the heap and are shared as much as possible +to reduce storage requirements. +Reference counting is used to determine when an object is +no longer needed and can safely be freed. +An object just created by \fBTcl_NewObj\fR or \fBTcl_NewStringObj\fR +has \fIrefCount\fR 0. +The macro \fBTcl_IncrRefCount\fR increments the reference count +when a new reference to the object is created. +The macro \fBTcl_DecrRefCount\fR decrements the count +when a reference is no longer needed and, +if the object's reference count drops to zero, frees its storage. +An object shared by different code or data structures has +\fIrefCount\fR greater than 1. +Incrementing an object's reference count ensures that +it won't be freed too early or have its value change accidently. +.PP +As an example, the bytecode interpreter shares argument objects +between calling and called Tcl procedures to avoid having to copy objects. +It assigns the call's argument objects to the procedure's +formal parameter variables. +In doing so, it calls \fBTcl_IncrRefCount\fR to increment +the reference count of each argument since there is now a new +reference to it from the formal parameter. +When the called procedure returns, +the interpreter calls \fBTcl_DecrRefCount\fR to decrement +each argument's reference count. +When an object's reference count drops less than or equal to zero, +\fBTcl_DecrRefCount\fR reclaims its storage. +Most command procedures do not have to be concerned about +reference counting since they use an object's value immediately +and don't retain a pointer to the object after they return. +However, if they do retain a pointer to an object in a data structure, +they must be careful to increment its reference count +since the retained pointer is a new reference. +.PP +Command procedures that directly modify objects +such as those for \fBlappend\fR and \fBlinsert\fR must be careful to +copy a shared object before changing it. +They must first check whether the object is shared +by calling \fBTcl_IsShared\fR. +If the object is shared they must copy the object +by using \fBTcl_DuplicateObj\fR; +this returns a new duplicate of the original object +that has \fIrefCount\fR 0. +If the object is not shared, +the command procedure "owns" the object and can safely modify it directly. +For example, the following code appears in the command procedure +that implements \fBlinsert\fR. +This procedure modifies the list object passed to it in \fIobjv[1]\fR +by inserting \fIobjc-3\fR new elements before \fIindex\fR. +.CS +listPtr = objv[1]; +if (Tcl_IsShared(listPtr)) { + listPtr = Tcl_DuplicateObj(listPtr); +} +result = Tcl_ListObjReplace(interp, listPtr, index, 0, (objc-3), &(objv[3])); +.CE +As another example, \fBincr\fR's command procedure +must check whether the variable's object is shared before +incrementing the integer in its internal representation. +If it is shared, it needs to duplicate the object +in order to avoid accidently changing values in other data structures. + +.SH "SEE ALSO" +Tcl_ConvertToType, Tcl_GetIntFromObj, Tcl_ListObjAppendElement, Tcl_ListObjIndex, Tcl_ListObjReplace, Tcl_RegisterObjType + +.SH KEYWORDS +internal representation, object, object creation, object type, reference counting, string representation, type conversion diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/ObjectType.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/ObjectType.3 new file mode 100644 index 0000000000000000000000000000000000000000..aa9113a9f2ed76b5d0f4a55d9f57e7ca27731e7f --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/ObjectType.3 @@ -0,0 +1,198 @@ +'\" +'\" Copyright (c) 1996-1997 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: ObjectType.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_ObjType 3 8.0 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_RegisterObjType, Tcl_GetObjType, Tcl_AppendAllObjTypes, Tcl_ConvertToType \- manipulate Tcl object types +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +\fBTcl_RegisterObjType\fR(\fItypePtr\fR) +.sp +Tcl_ObjType * +\fBTcl_GetObjType\fR(\fItypeName\fR) +.sp +int +\fBTcl_AppendAllObjTypes\fR(\fIinterp, objPtr\fR) +.sp +int +\fBTcl_ConvertToType\fR(\fIinterp, objPtr, typePtr\fR) +.SH ARGUMENTS +.AS Tcl_ObjType *typeName in +.AP Tcl_ObjType *typePtr in +Points to the structure containing information about the Tcl object type. +This storage must must live forever, +typically by being statically allocated. +.AP char *typeName in +The name of a Tcl object type that \fBTcl_GetObjType\fR should look up. +.AP Tcl_Interp *interp in +Interpreter to use for error reporting. +.AP Tcl_Obj *objPtr in +For \fBTcl_AppendAllObjTypes\fR, this points to the object onto which +it appends the name of each object type as a list element. +For \fBTcl_ConvertToType\fR, this points to an object that +must have been the result of a previous call to \fBTcl_NewObj\fR. +.BE + +.SH DESCRIPTION +.PP +The procedures in this man page manage Tcl object types. +The are used to register new object types, +look up types, +and force conversions from one type to another. +.PP +\fBTcl_RegisterObjType\fR registers a new Tcl object type +in the table of all object types supported by Tcl. +The argument \fItypePtr\fR points to a Tcl_ObjType structure that +describes the new type by giving its name +and by supplying pointers to four procedures +that implement the type. +If the type table already contains a type +with the same name as in \fItypePtr\fR, +it is replaced with the new type. +The Tcl_ObjType structure is described +in the section \fBTHE TCL_OBJTYPE STRUCTURE\fR below. +.PP +\fBTcl_GetObjType\fR returns a pointer to the Tcl_ObjType +with name \fItypeName\fR. +It returns NULL if no type with that name is registered. +.PP +\fBTcl_AppendAllObjTypes\fR appends the name of each object type +as a list element onto the Tcl object referenced by \fIobjPtr\fR. +The return value is \fBTCL_OK\fR unless there was an error +converting \fIobjPtr\fR to a list object; +in that case \fBTCL_ERROR\fR is returned. +.PP +\fBTcl_ConvertToType\fR converts an object from one type to another +if possible. +It creates a new internal representation for \fIobjPtr\fR +appropriate for the target type \fItypePtr\fR +and sets its \fItypePtr\fR member to that type. +Any internal representation for \fIobjPtr\fR's old type is freed. +If an error occurs during conversion, it returns \fBTCL_ERROR\fR +and leaves an error message in the result object for \fIinterp\fR +unless \fIinterp\fR is NULL. +Otherwise, it returns \fBTCL_OK\fR. +Passing a NULL \fIinterp\fR allows this procedure to be used +as a test whether the conversion can be done (and in fact was done). + +.SH "THE TCL_OBJTYPE STRUCTURE" +.PP +Extension writers can define new object types by defining four +procedures, +initializing a Tcl_ObjType structure to describe the type, +and calling \fBTcl_RegisterObjType\fR. +The \fBTcl_ObjType\fR structure is defined as follows: +.CS +typedef struct Tcl_ObjType { + char *\fIname\fR; + Tcl_FreeInternalRepProc *\fIfreeIntRepProc\fR; + Tcl_DupInternalRepProc *\fIdupIntRepProc\fR; + Tcl_UpdateStringProc *\fIupdateStringProc\fR; + Tcl_SetFromAnyProc *\fIsetFromAnyProc\fR; +} Tcl_ObjType; +.CE +.PP +The \fIname\fR member describes the name of the type, e.g. \fBint\fR. +Extension writers can look up an object type using its name +with the \fBTcl_GetObjType\fR procedure. +The remaining four members are pointers to procedures +called by the generic Tcl object code: +.PP +The \fIsetFromAnyProc\fR member contains the address of a function +called to create a valid internal representation +from an object's string representation. +.CS +typedef int (Tcl_SetFromAnyProc) (Tcl_Interp *\fIinterp\fR, Tcl_Obj *\fIobjPtr\fR); +.CE +If an internal representation can't be created from the string, +it returns \fBTCL_ERROR\fR and puts a message +describing the error in the result object for \fIinterp\fR +unless \fIinterp\fR is NULL. +If \fIsetFromAnyProc\fR is successful, +it stores the new internal representation, +sets \fIobjPtr\fR's \fItypePtr\fR member to point to +\fIsetFromAnyProc\fR's \fBTcl_ObjType\fR, and returns \fBTCL_OK\fR. +Before setting the new internal representation, +the \fIsetFromAnyProc\fR must free any internal representation +of \fIobjPtr\fR's old type; +it does this by calling the old type's \fIfreeIntRepProc\fR +if it is not NULL. +As an example, the \fIsetFromAnyProc\fR for the builtin Tcl integer type +gets an up-to-date string representation for \fIobjPtr\fR +by calling \fBTcl_GetStringFromObj\fR. +It parses the string to obtain an integer and, +if this succeeds, +stores the integer in \fIobjPtr\fR's internal representation +and sets \fIobjPtr\fR's \fItypePtr\fR member to point to the integer type's +Tcl_ObjType structure. +.PP +The \fIupdateStringProc\fR member contains the address of a function +called to create a valid string representation +from an object's internal representation. +.CS +typedef void (Tcl_UpdateStringProc) (Tcl_Obj *\fIobjPtr\fR); +.CE +\fIobjPtr\fR's \fIbytes\fR member is always NULL when it is called. +It must always set \fIbytes\fR non-NULL before returning. +We require the string representation's byte array +to have a null after the last byte, at offset \fIlength\fR; +this allows string representations that do not contain null bytes +to be treated as conventional null character-terminated C strings. +Storage for the byte array must be allocated in the heap by \fBTcl_Alloc\fR. +Note that \fIupdateStringProc\fRs must allocate +enough storage for the string's bytes and the terminating null byte. +The \fIupdateStringProc\fR for Tcl's builtin list type, for example, +builds an array of strings for each element object +and then calls \fBTcl_Merge\fR +to construct a string with proper Tcl list structure. +It stores this string as the list object's string representation. +.PP +The \fIdupIntRepProc\fR member contains the address of a function +called to copy an internal representation from one object to another. +.CS +typedef void (Tcl_DupInternalRepProc) (Tcl_Obj *\fIsrcPtr\fR, Tcl_Obj *\fIdupPtr\fR); +.CE +\fIdupPtr\fR's internal representation is made a copy of \fIsrcPtr\fR's +internal representation. +Before the call, +\fIsrcPtr\fR's internal representation is valid and \fIdupPtr\fR's is not. +\fIsrcPtr\fR's object type determines what +copying its internal representation means. +For example, the \fIdupIntRepProc\fR for the Tcl integer type +simply copies an integer. +The builtin list type's \fIdupIntRepProc\fR +allocates a new array that points at the original element objects; +the elements are shared between the two lists +(and their reference counts are incremented to reflect the new references). +.PP +The \fIfreeIntRepProc\fR member contains the address of a function +that is called when an object is freed. +.CS +typedef void (Tcl_FreeInternalRepProc) (Tcl_Obj *\fIobjPtr\fR); +.CE +The \fIfreeIntRepProc\fR function can deallocate the storage +for the object's internal representation +and do other type-specific processing necessary when an object is freed. +For example, Tcl list objects have an \fIinternalRep.otherValuePtr\fR +that points to an array of pointers to each element in the list. +The list type's \fIfreeIntRepProc\fR decrements +the reference count for each element object +(since the list will no longer refer to those objects), +then deallocates the storage for the array of pointers. +The \fIfreeIntRepProc\fR member can be set to NULL +to indicate that the internal representation does not require freeing. + +.SH "SEE ALSO" +Tcl_NewObj, Tcl_DecrRefCount, Tcl_IncrRefCount + +.SH KEYWORDS +internal representation, object, object type, string representation, type conversion diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/OpenFileChnl.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/OpenFileChnl.3 new file mode 100644 index 0000000000000000000000000000000000000000..5b43067ec8f93d04dd09733b1fd094a56dcf92a9 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/OpenFileChnl.3 @@ -0,0 +1,607 @@ +'\" +'\" Copyright (c) 1996-1997 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: OpenFileChnl.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +.so man.macros +.TH Tcl_OpenFileChannel 3 8.3 Tcl "Tcl Library Procedures" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +Tcl_OpenFileChannel, Tcl_OpenCommandChannel, Tcl_MakeFileChannel, Tcl_GetChannel, Tcl_GetChannelNames, Tcl_GetChannelNamesEx, Tcl_RegisterChannel, Tcl_UnregisterChannel, Tcl_Close, Tcl_ReadChars, Tcl_Read, Tcl_GetsObj, Tcl_Gets, Tcl_WriteObj, Tcl_WriteChars, Tcl_Write, Tcl_Flush, Tcl_Seek, Tcl_Tell, Tcl_GetChannelOption, Tcl_SetChannelOption, Tcl_Eof, Tcl_InputBlocked, Tcl_InputBuffered, Tcl_Ungets \- buffered I/O facilities using channels +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +typedef ... Tcl_Channel; +.sp +Tcl_Channel +\fBTcl_OpenFileChannel\fR(\fIinterp, fileName, mode, permissions\fR) +.sp +Tcl_Channel +\fBTcl_OpenCommandChannel\fR(\fIinterp, argc, argv, flags\fR) +.VS 8.0 +.sp +Tcl_Channel +\fBTcl_MakeFileChannel\fR(\fIhandle, readOrWrite\fR) +.VE +.sp +Tcl_Channel +\fBTcl_GetChannel\fR(\fIinterp, channelName, modePtr\fR) +.VS 8.3 +.sp +int +\fBTcl_GetChannelNames\fR(\fIinterp\fR) +.sp +int +\fBTcl_GetChannelNamesEx\fR(\fIinterp, pattern\fR) +.VE +.sp +void +\fBTcl_RegisterChannel\fR(\fIinterp, channel\fR) +.sp +int +\fBTcl_UnregisterChannel\fR(\fIinterp, channel\fR) +.sp +int +\fBTcl_Close\fR(\fIinterp, channel\fR) +.sp +.VS 8.1 +int +\fBTcl_ReadChars\fR(\fIchannel, readObjPtr, charsToRead, appendFlag\fR) +.sp +int +\fBTcl_Read\fR(\fIchannel, byteBuf, bytesToRead\fR) +.sp +int +\fBTcl_GetsObj\fR(\fIchannel, lineObjPtr\fR) +.sp +int +\fBTcl_Gets\fR(\fIchannel, lineRead\fR) +.sp +int +\fBTcl_Ungets\fR(\fIchannel, input, inputLen, addAtEnd\fR) +.sp +int +\fBTcl_WriteObj\fR(\fIchannel, writeObjPtr\fR) +.sp +int +\fBTcl_WriteChars\fR(\fIchannel, charBuf, bytesToWrite\fR) +.sp +int +\fBTcl_Write\fR(\fIchannel, byteBuf, bytesToWrite\fR) +.VE +.sp +int +\fBTcl_Eof\fR(\fIchannel\fR) +.sp +int +\fBTcl_Flush\fR(\fIchannel\fR) +.sp +int +\fBTcl_InputBlocked\fR(\fIchannel\fR) +.sp +int +\fBTcl_InputBuffered\fR(\fIchannel\fR) +.sp +int +\fBTcl_Seek\fR(\fIchannel, offset, seekMode\fR) +.sp +int +\fBTcl_Tell\fR(\fIchannel\fR) +.sp +int +\fBTcl_GetChannelOption\fR(\fIinterp, channel, optionName, optionValue\fR) +.sp +int +\fBTcl_SetChannelOption\fR(\fIinterp, channel, optionName, newValue\fR) +.sp +.SH ARGUMENTS +.AS Tcl_ChannelType newClientProcPtr in +.AP Tcl_Interp *interp in +Used for error reporting and to look up a channel registered in it. +.AP char *fileName in +The name of a local or network file. +.AP char *mode in +Specifies how the file is to be accessed. May have any of the values +allowed for the \fImode\fR argument to the Tcl \fBopen\fR command. For +\fBTcl_OpenCommandChannel\fR, may be NULL. +.AP int permissions in +POSIX-style permission flags such as 0644. If a new file is created, these +permissions will be set on the created file. +.AP int argc in +The number of elements in \fIargv\fR. +.AP char **argv in +Arguments for constructing a command pipeline. These values have the same +meaning as the non-switch arguments to the Tcl \fBexec\fR command. +.AP int flags in +Specifies the disposition of the stdio handles in pipeline: OR-ed +combination of \fBTCL_STDIN\fR, \fBTCL_STDOUT\fR, \fBTCL_STDERR\fR, and +\fBTCL_ENFORCE_MODE\fR. If \fBTCL_STDIN\fR is set, stdin for the first child +in the pipe is the pipe channel, otherwise it is the same as the standard +input of the invoking process; likewise for \fBTCL_STDOUT\fR and +\fBTCL_STDERR\fR. If \fBTCL_ENFORCE_MODE\fR is not set, then the pipe can +redirect stdio handles to override the stdio handles for which +\fBTCL_STDIN\fR, \fBTCL_STDOUT\fR and \fBTCL_STDERR\fR have been set. If it +is set, then such redirections cause an error. +.VS 8.0 +.AP ClientData handle in +Operating system specific handle for I/O to a file. For Unix this is a +file descriptor, for Windows it is a HANDLE. +.AP int readOrWrite in +OR-ed combination of \fBTCL_READABLE\fR and \fBTCL_WRITABLE\fR to indicate +what operations are valid on \fIhandle\fR. +.AP char *channelName in +The name of the channel. +.VE +.AP int *modePtr out +Points at an integer variable that will receive an OR-ed combination of +\fBTCL_READABLE\fR and \fBTCL_WRITABLE\fR denoting whether the channel is +open for reading and writing. +.AP Tcl_Channel channel in +A Tcl channel for input or output. Must have been the return value +from a procedure such as \fBTcl_OpenFileChannel\fR. +.VS 8.1 br +.AP Tcl_Obj *readObjPtr in/out +A pointer to a Tcl Object in which to store the characters read from the +channel. +.AP int charsToRead in +The number of characters to read from the channel. If the channel's encoding +is \fBbinary\fR, this is equivalent to the number of bytes to read from the +channel. +.AP int appendFlag in +If non-zero, data read from the channel will be appended to the object. +Otherwise, the data will replace the existing contents of the object. +.AP char *readBuf out +A buffer in which to store the bytes read from the channel. +.AP int bytesToRead in +The number of bytes to read from the channel. The buffer \fIreadBuf\fR must +be large enough to hold this many bytes. +.AP Tcl_Obj *lineObjPtr in/out +A pointer to a Tcl object in which to store the line read from the +channel. The line read will be appended to the current value of the +object. +.AP Tcl_DString *lineRead in/out +A pointer to a Tcl dynamic string in which to store the line read from the +channel. Must have been initialized by the caller. The line read will be +appended to any data already in the dynamic string. +.AP Tcl_Obj *writeObjPtr in +A pointer to a Tcl Object whose contents will be output to the channel. +.AP "CONST char" *charBuf in +A buffer containing the characters to output to the channel. +.AP char *byteBuf in +A buffer containing the bytes to output to the channel. +.AP int bytesToWrite in +The number of bytes to consume from \fIcharBuf\fR or \fIbyteBuf\fR and +output to the channel. +.VE +.AP int offset in +How far to move the access point in the channel at which the next input or +output operation will be applied, measured in bytes from the position +given by \fIseekMode\fR. May be either positive or negative. +.AP int seekMode in +Relative to which point to seek; used with \fIoffset\fR to calculate the new +access point for the channel. Legal values are \fBSEEK_SET\fR, +\fBSEEK_CUR\fR, and \fBSEEK_END\fR. +.AP char *optionName in +The name of an option applicable to this channel, such as \fB\-blocking\fR. +May have any of the values accepted by the \fBfconfigure\fR command. +.AP Tcl_DString *optionValue in +Where to store the value of an option or a list of all options and their +values. Must have been initialized by the caller. +.AP char *newValue in +New value for the option given by \fIoptionName\fR. +.VS 8.3 +.AP char *pattern in +The pattern to match on, passed to Tcl_StringMatch, or NULL. +.AP char *input in +The input to add to a channel buffer. +.AP int inputLen in +Length of the input +.AP int addToEnd in +Flag indicating whether the input should be added to the end or +beginning of the channel buffer. +.VE +.BE + +.SH DESCRIPTION +.PP +The Tcl channel mechanism provides a device-independent and +platform-independent mechanism for performing buffered input +and output operations on a variety of file, socket, and device +types. +The channel mechanism is extensible to new channel types, by +providing a low level channel driver for the new type; the channel driver +interface is described in the manual entry for \fBTcl_CreateChannel\fR. The +channel mechanism provides a buffering scheme modeled after +Unix's standard I/O, and it also allows for nonblocking I/O on +channels. +.PP +The procedures described in this manual entry comprise the C APIs of the +generic layer of the channel architecture. For a description of the channel +driver architecture and how to implement channel drivers for new types of +channels, see the manual entry for \fBTcl_CreateChannel\fR. + +.SH TCL_OPENFILECHANNEL +.PP +\fBTcl_OpenFileChannel\fR opens a file specified by \fIfileName\fR and +returns a channel handle that can be used to perform input and output on +the file. This API is modeled after the \fBfopen\fR procedure of +the Unix standard I/O library. +The syntax and meaning of all arguments is similar to those +given in the Tcl \fBopen\fR command when opening a file. +If an error occurs while opening the channel, \fBTcl_OpenFileChannel\fR +returns NULL and records a POSIX error code that can be +retrieved with \fBTcl_GetErrno\fR. +In addition, if \fIinterp\fR is non-NULL, \fBTcl_OpenFileChannel\fR +leaves an error message in \fIinterp\fR's result after any error. +.PP +The newly created channel is not registered in the supplied interpreter; to +register it, use \fBTcl_RegisterChannel\fR, described below. +If one of the standard channels, \fBstdin, stdout\fR or \fBstderr\fR was +previously closed, the act of creating the new channel also assigns it as a +replacement for the standard channel. + +.SH TCL_OPENCOMMANDCHANNEL +.PP +\fBTcl_OpenCommandChannel\fR provides a C-level interface to the +functions of the \fBexec\fR and \fBopen\fR commands. +It creates a sequence of subprocesses specified +by the \fIargv\fR and \fIargc\fR arguments and returns a channel that can +be used to communicate with these subprocesses. +The \fIflags\fR argument indicates what sort of communication will +exist with the command pipeline. +.PP +If the \fBTCL_STDIN\fR flag is set then the standard input for the +first subprocess will be tied to the channel: writing to the channel +will provide input to the subprocess. If \fBTCL_STDIN\fR is not set, +then standard input for the first subprocess will be the same as this +application's standard input. If \fBTCL_STDOUT\fR is set then +standard output from the last subprocess can be read from the channel; +otherwise it goes to this application's standard output. If +\fBTCL_STDERR\fR is set, standard error output for all subprocesses is +returned to the channel and results in an error when the channel is +closed; otherwise it goes to this application's standard error. If +\fBTCL_ENFORCE_MODE\fR is not set, then \fIargc\fR and \fIargv\fR can +redirect the stdio handles to override \fBTCL_STDIN\fR, +\fBTCL_STDOUT\fR, and \fBTCL_STDERR\fR; if it is set, then it is an +error for argc and argv to override stdio channels for which +\fBTCL_STDIN\fR, \fBTCL_STDOUT\fR, and \fBTCL_STDERR\fR have been set. +.PP +If an error occurs while opening the channel, \fBTcl_OpenCommandChannel\fR +returns NULL and records a POSIX error code that can be retrieved with +\fBTcl_GetErrno\fR. +In addition, \fBTcl_OpenCommandChannel\fR leaves an error message in +the interpreter's result if \fIinterp\fR is not NULL. +.PP +The newly created channel is not registered in the supplied interpreter; to +register it, use \fBTcl_RegisterChannel\fR, described below. +If one of the standard channels, \fBstdin, stdout\fR or \fBstderr\fR was +previously closed, the act of creating the new channel also assigns it as a +replacement for the standard channel. + +.SH TCL_MAKEFILECHANNEL +.PP +\fBTcl_MakeFileChannel\fR makes a \fBTcl_Channel\fR from an existing, +platform-specific, file handle. +The newly created channel is not registered in the supplied interpreter; to +register it, use \fBTcl_RegisterChannel\fR, described below. +If one of the standard channels, \fBstdin, stdout\fR or \fBstderr\fR was +previously closed, the act of creating the new channel also assigns it as a +replacement for the standard channel. + +.SH TCL_GETCHANNEL +.PP +\fBTcl_GetChannel\fR returns a channel given the \fIchannelName\fR used to +create it with \fBTcl_CreateChannel\fR and a pointer to a Tcl interpreter in +\fIinterp\fR. If a channel by that name is not registered in that interpreter, +the procedure returns NULL. If the \fImode\fR argument is not NULL, it +points at an integer variable that will receive an OR-ed combination of +\fBTCL_READABLE\fR and \fBTCL_WRITABLE\fR describing whether the channel is +open for reading and writing. +.PP +\fBTcl_GetChannelNames\fR and \fBTcl_GetChannelNamesEx\fR write the +names of the registered channels to the interpreter's result as a +list object. \fBTcl_GetChannelNamesEx\fR will filter these names +according to the \fIpattern\fR. If \fIpattern\fR is NULL, then it +will not do any filtering. The return value is \fBTCL_OK\fR if no +errors occured writing to the result, otherwise it is \fBTCL_ERROR\fR, +and the error message is left in the interpreter's result. + +.SH TCL_REGISTERCHANNEL +.PP +\fBTcl_RegisterChannel\fR adds a channel to the set of channels accessible +in \fIinterp\fR. After this call, Tcl programs executing in that +interpreter can refer to the channel in input or output operations using +the name given in the call to \fBTcl_CreateChannel\fR. After this call, +the channel becomes the property of the interpreter, and the caller should +not call \fBTcl_Close\fR for the channel; the channel will be closed +automatically when it is unregistered from the interpreter. +.PP +Code executing outside of any Tcl interpreter can call +\fBTcl_RegisterChannel\fR with \fIinterp\fR as NULL, to indicate that it +wishes to hold a reference to this channel. Subsequently, the channel can +be registered in a Tcl interpreter and it will only be closed when the +matching number of calls to \fBTcl_UnregisterChannel\fR have been made. +This allows code executing outside of any interpreter to safely hold a +reference to a channel that is also registered in a Tcl interpreter. + +.SH TCL_UNREGISTERCHANNEL +.PP +\fBTcl_UnregisterChannel\fR removes a channel from the set of channels +accessible in \fIinterp\fR. After this call, Tcl programs will no longer be +able to use the channel's name to refer to the channel in that interpreter. +If this operation removed the last registration of the channel in any +interpreter, the channel is also closed and destroyed. +.PP +Code not associated with a Tcl interpreter can call +\fBTcl_UnregisterChannel\fR with \fIinterp\fR as NULL, to indicate to Tcl +that it no longer holds a reference to that channel. If this is the last +reference to the channel, it will now be closed. + +.SH TCL_CLOSE +.PP +\fBTcl_Close\fR destroys the channel \fIchannel\fR, which must denote a +currently open channel. The channel should not be registered in any +interpreter when \fBTcl_Close\fR is called. Buffered output is flushed to +the channel's output device prior to destroying the channel, and any +buffered input is discarded. If this is a blocking channel, the call does +not return until all buffered data is successfully sent to the channel's +output device. If this is a nonblocking channel and there is buffered +output that cannot be written without blocking, the call returns +immediately; output is flushed in the background and the channel will be +closed once all of the buffered data has been output. In this case errors +during flushing are not reported. +.PP +If the channel was closed successfully, \fBTcl_Close\fR returns \fBTCL_OK\fR. +If an error occurs, \fBTcl_Close\fR returns \fBTCL_ERROR\fR and records a +POSIX error code that can be retrieved with \fBTcl_GetErrno\fR. +If the channel is being closed synchronously and an error occurs during +closing of the channel and \fIinterp\fR is not NULL, an error message is +left in the interpreter's result. +.PP +Note: it is not safe to call \fBTcl_Close\fR on a channel that has been +registered using \fBTcl_RegisterChannel\fR; see the documentation for +\fBTcl_RegisterChannel\fR, above, for details. If the channel has ever +been given as the \fBchan\fR argument in a call to +\fBTcl_RegisterChannel\fR, you should instead use +\fBTcl_UnregisterChannel\fR, which will internally call \fBTcl_Close\fR +when all calls to \fBTcl_RegisterChannel\fR have been matched by +corresponding calls to \fBTcl_UnregisterChannel\fR. + +.VS 8.1 br +.SH "TCL_READCHARS AND TCL_READ" +.PP +\fBTcl_ReadChars\fR consumes bytes from \fIchannel\fR, converting the bytes +to UTF-8 based on the channel's encoding and storing the produced data in +\fIreadObjPtr\fR's string representation. The return value of +\fBTcl_ReadChars\fR is the number of characters, up to \fIcharsToRead\fR, +that were stored in \fIobjPtr\fR. If an error occurs while reading, the +return value is \-1 and \fBTcl_ReadChars\fR records a POSIX error code that +can be retrieved with \fBTcl_GetErrno\fR. +.PP +The return value may be smaller than the value to read, indicating that less +data than requested was available. This is called a \fIshort read\fR. In +blocking mode, this can only happen on an end-of-file. In nonblocking mode, +a short read can also occur if there is not enough input currently +available: \fBTcl_ReadChars\fR returns a short count rather than waiting +for more data. +.PP +If the channel is in blocking mode, a return value of zero indicates an +end-of-file condition. If the channel is in nonblocking mode, a return +value of zero indicates either that no input is currently available or an +end-of-file condition. Use \fBTcl_Eof\fR and \fBTcl_InputBlocked\fR to tell +which of these conditions actually occurred. +.PP +\fBTcl_ReadChars\fR translates the various end-of-line representations into +the canonical \fB\en\fR internal representation according to the current +end-of-line recognition mode. End-of-line recognition and the various +platform-specific modes are described in the manual entry for the Tcl +\fBfconfigure\fR command. +.PP +As a performance optimization, when reading from a channel with the encoding +\fBbinary\fR, the bytes are not converted to UTF-8 as they are read. +Instead, they are stored in \fIreadObjPtr\fR's internal representation as a +byte-array object. The string representation of this object will only be +constructed if it is needed (e.g., because of a call to +\fBTcl_GetStringFromObj\fR). In this way, byte-oriented data can be read +from a channel, manipulated by calling \fBTcl_GetByteArrayFromObj\fR and +related functions, and then written to a channel without the expense of ever +converting to or from UTF-8. +.PP +\fBTcl_Read\fR is similar to \fBTcl_ReadChars\fR, except that it doesn't do +encoding conversions, regardless of the channel's encoding. It is deprecated +and exists for backwards compatibility with non-internationalized Tcl +extensions. It consumes bytes from \fIchannel\fR and stores them in +\fIbuf\fR, performing end-of-line translations on the way. The return value +of \fBTcl_Read\fR is the number of bytes, up to \fItoRead\fR, written in +\fIbuf\fR. The buffer produced by \fBTcl_Read\fR is not NULL terminated. +Its contents are valid from the zeroth position up to and excluding the +position indicated by the return value. + +.SH "TCL_GETSOBJ AND TCL_GETS" +.PP +\fBTcl_GetsObj\fR consumes bytes from \fIchannel\fR, converting the bytes to +UTF-8 based on the channel's encoding, until a full line of input has been +seen. If the channel's encoding is \fBbinary\fR, each byte read from the +channel is treated as an individual Unicode character. All of the +characters of the line except for the terminating end-of-line character(s) +are appended to \fIlineObjPtr\fR's string representation. The end-of-line +character(s) are read and discarded. +.PP +If a line was successfully read, the return value is greater than or equal +to zero and indicates the number of bytes stored in \fIlineObjPtr\fR. If an +error occurs, \fBTcl_GetsObj\fR returns \-1 and records a POSIX error code +that can be retrieved with \fBTcl_GetErrno\fR. \fBTcl_GetsObj\fR also +returns \-1 if the end of the file is reached; the \fBTcl_Eof\fR procedure +can be used to distinguish an error from an end-of-file condition. +.PP +If the channel is in nonblocking mode, the return value can also be \-1 if +no data was available or the data that was available did not contain an +end-of-line character. When \-1 is returned, the \fBTcl_InputBlocked\fR +procedure may be invoked to determine if the channel is blocked because +of input unavailability. +.PP +\fBTcl_Gets\fR is the same as \fBTcl_GetsObj\fR except the resulting +characters are appended to the appended to the dynamic string given by +\fIdsPtr\fR rather than a Tcl object. + +.SH "TCL_UNGETS" +.PP +\fBTcl_Ungets\fR is used to add data to the input queue of a channel, +at either the head or tail of the queue. \fIInput\fR is a pointer to +the data that is to be added. \fIInputLen\fR gives the length of the +input to add. \fIAddAtEnd\fR, in non-zero, indicates that the data is +to be added at the end of queue; otherwise it will be added at the +head of the queue. If \fIchannel\fR has a "sticky" EOF set, no data will be +added to the input queue. \fBTcl_Ungets\fR returns \fIinputLen\fR or +-1 if an error occurs. + +.SH "TCL_WRITECHARS, TCL_WRITEOBJ, AND TCL_WRITE" +.PP +\fBTcl_WriteChars\fR accepts \fIbytesToWrite\fR bytes of character data at +\fIcharBuf\fR. The UTF-8 characters in the buffer are converted to the +channel's encoding and queued for output to \fIchannel\fR. If +\fIbytesToWrite\fR is negative, \fBTcl_WriteChars\fR expects \fIcharBuf\fR +to be NULL terminated and it outputs everything up to the NULL. +.PP +Data queued for output may not appear on the output device immediately, due +to internal buffering. If the data should appear immediately, call +\fBTcl_Flush\fR after the call to \fBTcl_WriteChars\fR, or set the +\fB\-buffering\fR option on the channel to \fBnone\fR. If you wish the data +to appear as soon as a complete line is accepted for output, set the +\fB\-buffering\fR option on the channel to \fBline\fR mode. +.PP +The return value of \fBTcl_WriteChars\fR is a count of how many bytes were +accepted for output to the channel. This is either greater than zero to +indicate success or \-1 to indicate that an error occurred. If an error +occurs, \fBTcl_WriteChars\fR records a POSIX error code that may be +retrieved with \fBTcl_GetErrno\fR. +.PP +Newline characters in the output data are translated to platform-specific +end-of-line sequences according to the \fB\-translation\fR option for the +channel. This is done even if the channel has no encoding. +.PP +\fBTcl_WriteObj\fR is similar to \fBTcl_WriteChars\fR except it +accepts a Tcl object whose contents will be output to the channel. The +UTF-8 characters in \fIwriteObjPtr\fR's string representation are converted +to the channel's encoding and queued for output to \fIchannel\fR. +As a performance optimization, when writing to a channel with the encoding +\fBbinary\fR, UTF-8 characters are not converted as they are written. +Instead, the bytes in \fIwriteObjPtr\fR's internal representation as a +byte-array object are written to the channel. The byte-array representation +of the object will be constructed if it is needed. In this way, +byte-oriented data can be read from a channel, manipulated by calling +\fBTcl_GetByteArrayFromObj\fR and related functions, and then written to a +channel without the expense of ever converting to or from UTF-8. +.PP +\fBTcl_Write\fR is similar to \fBTcl_WriteChars\fR except that it doesn't do +encoding conversions, regardless of the channel's encoding. It is +deprecated and exists for backwards compatibility with non-internationalized +Tcl extensions. It accepts \fIbytesToWrite\fR bytes of data at +\fIbyteBuf\fR and queues them for output to \fIchannel\fR. If +\fIbytesToWrite\fR is negative, \fBTcl_Write\fR expects \fIbyteBuf\fR to be +NULL terminated and it outputs everything up to the NULL. +.VE + +.SH TCL_FLUSH +.PP +\fBTcl_Flush\fR causes all of the buffered output data for \fIchannel\fR +to be written to its underlying file or device as soon as possible. +If the channel is in blocking mode, the call does not return until +all the buffered data has been sent to the channel or some error occurred. +The call returns immediately if the channel is nonblocking; it starts +a background flush that will write the buffered data to the channel +eventually, as fast as the channel is able to absorb it. +.PP +The return value is normally \fBTCL_OK\fR. +If an error occurs, \fBTcl_Flush\fR returns \fBTCL_ERROR\fR and +records a POSIX error code that can be retrieved with \fBTcl_GetErrno\fR. + +.SH TCL_SEEK +.PP +\fBTcl_Seek\fR moves the access point in \fIchannel\fR where subsequent +data will be read or written. Buffered output is flushed to the channel and +buffered input is discarded, prior to the seek operation. +.PP +\fBTcl_Seek\fR normally returns the new access point. +If an error occurs, \fBTcl_Seek\fR returns \-1 and records a POSIX error +code that can be retrieved with \fBTcl_GetErrno\fR. +After an error, the access point may or may not have been moved. + +.SH TCL_TELL +.PP +\fBTcl_Tell\fR returns the current access point for a channel. The returned +value is \-1 if the channel does not support seeking. + +.SH TCL_GETCHANNELOPTION +.PP +\fBTcl_GetChannelOption\fR retrieves, in \fIdsPtr\fR, the value of one of +the options currently in effect for a channel, or a list of all options and +their values. The \fIchannel\fR argument identifies the channel for which +to query an option or retrieve all options and their values. +If \fIoptionName\fR is not NULL, it is the name of the +option to query; the option's value is copied to the Tcl dynamic string +denoted by \fIoptionValue\fR. If +\fIoptionName\fR is NULL, the function stores an alternating list of option +names and their values in \fIoptionValue\fR, using a series of calls to +\fBTcl_DStringAppendElement\fR. The various preexisting options and +their possible values are described in the manual entry for the Tcl +\fBfconfigure\fR command. Other options can be added by each channel type. +These channel type specific options are described in the manual entry for +the Tcl command that creates a channel of that type; for example, the +additional options for TCP based channels are described in the manual entry +for the Tcl \fBsocket\fR command. +The procedure normally returns \fBTCL_OK\fR. If an error occurs, it returns +\fBTCL_ERROR\fR and calls \fBTcl_SetErrno\fR to store an appropriate POSIX +error code. + +.SH TCL_SETCHANNELOPTION +.PP +\fBTcl_SetChannelOption\fR sets a new value for an option on \fIchannel\fR. +\fIOptionName\fR is the option to set and \fInewValue\fR is the value to +set. +The procedure normally returns \fBTCL_OK\fR. If an error occurs, +it returns \fBTCL_ERROR\fR; in addition, if \fIinterp\fR is non-NULL, +\fBTcl_SetChannelOption\fR leaves an error message in the interpreter's result. + +.SH TCL_EOF +.PP +\fBTcl_Eof\fR returns a nonzero value if \fIchannel\fR encountered +an end of file during the last input operation. + +.SH TCL_INPUTBLOCKED +.PP +\fBTcl_InputBlocked\fR returns a nonzero value if \fIchannel\fR is in +nonblocking mode and the last input operation returned less data than +requested because there was insufficient data available. +The call always returns zero if the channel is in blocking mode. + +.SH TCL_INPUTBUFFERED +.PP +\fBTcl_InputBuffered\fR returns the number of bytes of input currently +buffered in the internal buffers for a channel. If the channel is not open +for reading, this function always returns zero. + +.VS 8.0 +.SH "PLATFORM ISSUES" +.PP +The handles returned from \fBTcl_GetChannelHandle\fR depend on the +platform and the channel type. On Unix platforms, the handle is +always a Unix file descriptor as returned from the \fBopen\fR system +call. On Windows platforms, the handle is a file \fBHANDLE\fR when +the channel was created with \fBTcl_OpenFileChannel\fR, +\fBTcl_OpenCommandChannel\fR, or \fBTcl_MakeFileChannel\fR. Other +channel types may return a different type of handle on Windows +platforms. On the Macintosh platform, the handle is a file reference +number as returned from \fBHOpenDF\fR. +.VE + +.SH "SEE ALSO" +DString(3), fconfigure(n), filename(n), fopen(2), Tcl_CreateChannel(3) + +.SH KEYWORDS +access point, blocking, buffered I/O, channel, channel driver, end of file, +flush, input, nonblocking, output, read, seek, write diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/OpenTcp.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/OpenTcp.3 new file mode 100644 index 0000000000000000000000000000000000000000..03c29772054d67a5c265cfb67bc6e7b305481be2 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/OpenTcp.3 @@ -0,0 +1,179 @@ +'\" +'\" Copyright (c) 1996-7 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: OpenTcp.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +.so man.macros +.TH Tcl_OpenTcpClient 3 8.0 Tcl "Tcl Library Procedures" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +Tcl_OpenTcpClient, Tcl_MakeTcpClientChannel, Tcl_OpenTcpServer \- procedures to open channels using TCP sockets +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +Tcl_Channel +\fBTcl_OpenTcpClient\fR(\fIinterp, port, host, myaddr, myport, async\fR) +.sp +Tcl_Channel +\fBTcl_MakeTcpClientChannel\fR(\fIsock\fR) +.sp +Tcl_Channel +\fBTcl_OpenTcpServer\fR(\fIinterp, port, myaddr, proc, clientData\fR) +.sp +.SH ARGUMENTS +.AS Tcl_ChannelType newClientProcPtr in +.AP Tcl_Interp *interp in +Tcl interpreter to use for error reporting. If non-NULL and an +error occurs, an error message is left in the interpreter's result. +.AP int port in +A port number to connect to as a client or to listen on as a server. +.AP char *host in +A string specifying a host name or address for the remote end of the connection. +.AP int myport in +A port number for the client's end of the socket. If 0, a port number +is allocated at random. +.AP char *myaddr in +A string specifying the host name or address for network interface to use +for the local end of the connection. If NULL, a default interface is +chosen. +.AP int async in +If nonzero, the client socket is connected asynchronously to the server. +.AP ClientData sock in +Platform-specific handle for client TCP socket. +.AP Tcl_TcpAcceptProc *proc in +Pointer to a procedure to invoke each time a new connection is +accepted via the socket. +.AP ClientData clientData in +Arbitrary one-word value to pass to \fIproc\fR. +.BE + +.SH DESCRIPTION +.PP +These functions are convenience procedures for creating +channels that communicate over TCP sockets. +The operations on a channel +are described in the manual entry for \fBTcl_OpenFileChannel\fR. + +.SH TCL_OPENTCPCLIENT +.PP +\fBTcl_OpenTcpClient\fR opens a client TCP socket connected to a \fIport\fR +on a specific \fIhost\fR, and returns a channel that can be used to +communicate with the server. The host to connect to can be specified either +as a domain name style name (e.g. \fBwww.sunlabs.com\fR), or as a string +containing the alphanumeric representation of its four-byte address (e.g. +\fB127.0.0.1\fR). Use the string \fBlocalhost\fR to connect to a TCP socket on +the host on which the function is invoked. +.PP +The \fImyaddr\fR and \fImyport\fR arguments allow a client to specify an +address for the local end of the connection. If \fImyaddr\fR is NULL, then +an interface is chosen automatically by the operating system. +If \fImyport\fR is 0, then a port number is chosen at random by +the operating system. +.PP +If \fIasync\fR is zero, the call to \fBTcl_OpenTcpClient\fR returns only +after the client socket has either successfully connected to the server, or +the attempted connection has failed. +If \fIasync\fR is nonzero the socket is connected asynchronously and the +returned channel may not yet be connected to the server when the call to +\fBTcl_OpenTcpClient\fR returns. If the channel is in blocking mode and an +input or output operation is done on the channel before the connection is +completed or fails, that operation will wait until the connection either +completes successfully or fails. If the channel is in nonblocking mode, the +input or output operation will return immediately and a subsequent call to +\fBTcl_InputBlocked\fR on the channel will return nonzero. +.PP +The returned channel is opened for reading and writing. +If an error occurs in opening the socket, \fBTcl_OpenTcpClient\fR returns +NULL and records a POSIX error code that can be retrieved +with \fBTcl_GetErrno\fR. +In addition, if \fIinterp\fR is non-NULL, an error message +is left in the interpreter's result. +.PP +The newly created channel is not registered in the supplied interpreter; to +register it, use \fBTcl_RegisterChannel\fR. +If one of the standard channels, \fBstdin, stdout\fR or \fBstderr\fR was +previously closed, the act of creating the new channel also assigns it as a +replacement for the standard channel. + +.SH TCL_MAKETCPCLIENTCHANNEL +.PP +\fBTcl_MakeTcpClientChannel\fR creates a \fBTcl_Channel\fR around an +existing, platform specific, handle for a client TCP socket. +.PP +The newly created channel is not registered in the supplied interpreter; to +register it, use \fBTcl_RegisterChannel\fR. +If one of the standard channels, \fBstdin, stdout\fR or \fBstderr\fR was +previously closed, the act of creating the new channel also assigns it as a +replacement for the standard channel. + +.SH TCL_OPENTCPSERVER +.PP +\fBTcl_OpenTcpServer\fR opens a TCP socket on the local host on a specified +\fIport\fR and uses the Tcl event mechanism to accept requests from clients +to connect to it. The \fImyaddr\fP argument specifies the network interface. +If \fImyaddr\fP is NULL the special address INADDR_ANY should be used to +allow connections from any network interface. +Each time a client connects to this socket, Tcl creates a channel +for the new connection and invokes \fIproc\fR with information about +the channel. \fIProc\fR must match the following prototype: +.CS +typedef void Tcl_TcpAcceptProc( + ClientData \fIclientData\fR, + Tcl_Channel \fIchannel\fR, + char *\fIhostName\fR, + int \fIport\fP); +.CE +.PP +The \fIclientData\fR argument will be the same as the \fIclientData\fR +argument to \fBTcl_OpenTcpServer\fR, \fIchannel\fR will be the handle +for the new channel, \fIhostName\fR points to a string containing +the name of the client host making the connection, and \fIport\fP +will contain the client's port number. +The new channel +is opened for both input and output. +If \fIproc\fR raises an error, the connection is closed automatically. +\fIProc\fR has no return value, but if it wishes to reject the +connection it can close \fIchannel\fR. +.PP +\fBTcl_OpenTcpServer\fR normally returns a pointer to a channel +representing the server socket. +If an error occurs, \fBTcl_OpenTcpServer\fR returns NULL and +records a POSIX error code that can be retrieved with \fBTcl_GetErrno\fR. +In addition, if the interpreter is non-NULL, an error message +is left in the interpreter's result. +.PP +The channel returned by \fBTcl_OpenTcpServer\fR cannot be used for +either input or output. +It is simply a handle for the socket used to accept connections. +The caller can close the channel to shut down the server and disallow +further connections from new clients. +.PP +TCP server channels operate correctly only in applications that dispatch +events through \fBTcl_DoOneEvent\fR or through Tcl commands such as +\fBvwait\fR; otherwise Tcl will never notice that a connection request from +a remote client is pending. +.PP +The newly created channel is not registered in the supplied interpreter; to +register it, use \fBTcl_RegisterChannel\fR. +If one of the standard channels, \fBstdin, stdout\fR or \fBstderr\fR was +previously closed, the act of creating the new channel also assigns it as a +replacement for the standard channel. + +.VS +.SH "PLATFORM ISSUES" +.PP +On Unix platforms, the socket handle is a Unix file descriptor as +returned by the \fBsocket\fR system call. On the Windows platform, the +socket handle is a \fBSOCKET\fR as defined in the WinSock API. On the +Macintosh platform, the socket handle is a \fBStreamPtr\fR. +.VE + +.SH "SEE ALSO" +Tcl_OpenFileChannel(3), Tcl_RegisterChannel(3), vwait(n) + +.SH KEYWORDS +client, server, TCP diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/ParseCmd.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/ParseCmd.3 new file mode 100644 index 0000000000000000000000000000000000000000..bc4d3b663439748c7f06cdf1cd4db28598116911 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/ParseCmd.3 @@ -0,0 +1,438 @@ +'\" +'\" Copyright (c) 1997 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: ParseCmd.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_ParseCommand 3 8.3 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_ParseCommand, Tcl_ParseExpr, Tcl_ParseBraces, Tcl_ParseQuotedString, Tcl_ParseVarName, Tcl_ParseVar, Tcl_FreeParse, Tcl_EvalTokens \- parse Tcl scripts and expressions +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +int +\fBTcl_ParseCommand\fR(\fIinterp, string, numBytes, nested, parsePtr\fR) +.sp +int +\fBTcl_ParseExpr\fR(\fIinterp, string, numBytes, parsePtr\fR) +.sp +int +\fBTcl_ParseBraces\fR(\fIinterp, string, numBytes, parsePtr, append, termPtr\fR) +.sp +int +\fBTcl_ParseQuotedString\fR(\fIinterp, string, numBytes, parsePtr, append, termPtr\fR) +.sp +int +\fBTcl_ParseVarName\fR(\fIinterp, string, numBytes, parsePtr, append\fR) +.sp +char * +\fBTcl_ParseVar\fR(\fIinterp, string, termPtr\fR) +.sp +\fBTcl_FreeParse\fR(\fIusedParsePtr\fR) +.sp +Tcl_Obj * +\fBTcl_EvalTokens\fR(\fIinterp, tokenPtr, numTokens\fR) +.SH ARGUMENTS +.AS Tcl_Interp *usedParsePtr +.AP Tcl_Interp *interp out +For procedures other than \fBTcl_FreeParse\fR and \fBTcl_EvalTokens\fR, +used only for error reporting; +if NULL, then no error messages are left after errors. +For \fBTcl_EvalTokens\fR, determines the context for evaluating the +script and also is used for error reporting; must not be NULL. +.AP char *string in +Pointer to first character in string to parse. +.AP int numBytes in +Number of bytes in \fIstring\fR, not including any terminating null +character. If less than 0 then the script consists of all characters +in \fIstring\fR up to the first null character. +.AP int nested in +Non-zero means that the script is part of a command substitution so an +unquoted close bracket should be treated as a command terminator. If zero, +close brackets have no special meaning. +.AP int append in +Non-zero means that \fI*parsePtr\fR already contains valid tokens; the new +tokens should be appended to those already present. Zero means that +\fI*parsePtr\fR is uninitialized; any information in it is ignored. +This argument is normally 0. +.AP Tcl_Parse *parsePtr out +Points to structure to fill in with information about the parsed +command, expression, variable name, etc. +Any previous information in this structure +is ignored, unless \fIappend\fR is non-zero in a call to +\fBTcl_ParseBraces\fR, \fBTcl_ParseQuotedString\fR, +or \fBTcl_ParseVarName\fR. +.AP char **termPtr out +If not NULL, points to a location where +\fBTcl_ParseBraces\fR, \fBTcl_ParseQuotedString\fR, and +\fBTcl_ParseVar\fR will store a pointer to the character +just after the terminating character (the close-brace, the last +character of the variable name, or the close-quote (respectively)) +if the parse was successful. +.AP Tcl_Parse *usedParsePtr in +Points to structure that was filled in by a previous call to +\fBTcl_ParseCommand\fR, \fBTcl_ParseExpr\fR, \fBTcl_ParseVarName\fR, etc. +.BE + +.SH DESCRIPTION +.PP +These procedures parse Tcl commands or portions of Tcl commands such as +expressions or references to variables. +Each procedure takes a pointer to a script (or portion thereof) +and fills in the structure pointed to by \fIparsePtr\fR +with a collection of tokens describing the information that was parsed. +The procedures normally return \fBTCL_OK\fR. +However, if an error occurs then they return \fBTCL_ERROR\fR, +leave an error message in \fIinterp's\fR result +(if \fIinterp\fR is not NULL), +and leave nothing in \fIparsePtr\fR. +.PP +\fBTcl_ParseCommand\fR is a procedure that parses Tcl +scripts. Given a pointer to a script, it +parses the first command from the script. If the command was parsed +successfully, \fBTcl_ParseCommand\fR returns \fBTCL_OK\fR and fills in the +structure pointed to by \fIparsePtr\fR with information about the +structure of the command (see below for details). +If an error occurred in parsing the command then +\fBTCL_ERROR\fR is returned, an error message is left in \fIinterp\fR's +result, and no information is left at \fI*parsePtr\fR. +.PP +\fBTcl_ParseExpr\fR parses Tcl expressions. +Given a pointer to a script containing an expression, +\fBTcl_ParseCommand\fR parses the expression. +If the expression was parsed successfully, +\fBTcl_ParseExpr\fR returns \fBTCL_OK\fR and fills in the +structure pointed to by \fIparsePtr\fR with information about the +structure of the expression (see below for details). +If an error occurred in parsing the command then +\fBTCL_ERROR\fR is returned, an error message is left in \fIinterp\fR's +result, and no information is left at \fI*parsePtr\fR. +.PP +\fBTcl_ParseBraces\fR parses a string or command argument +enclosed in braces such as +\fB{hello}\fR or \fB{string \\t with \\t tabs}\fR +from the beginning of its argument \fIstring\fR. +The first character of \fIstring\fR must be \fB{\fR. +If the braced string was parsed successfully, +\fBTcl_ParseBraces\fR returns \fBTCL_OK\fR, +fills in the structure pointed to by \fIparsePtr\fR +with information about the structure of the string +(see below for details), +and stores a pointer to the character just after the terminating \fB}\fR +in the location given by \fI*termPtr\fR. +If an error occurrs while parsing the string +then \fBTCL_ERROR\fR is returned, +an error message is left in \fIinterp\fR's result, +and no information is left at \fI*parsePtr\fR or \fI*termPtr\fR. +.PP +\fBTcl_ParseQuotedString\fR parses a double-quoted string such as +\fB"sum is [expr $a+$b]"\fR +from the beginning of the argument \fIstring\fR. +The first character of \fIstring\fR must be \fB"\fR. +If the double-quoted string was parsed successfully, +\fBTcl_ParseQuotedString\fR returns \fBTCL_OK\fR, +fills in the structure pointed to by \fIparsePtr\fR +with information about the structure of the string +(see below for details), +and stores a pointer to the character just after the terminating \fB"\fR +in the location given by \fI*termPtr\fR. +If an error occurrs while parsing the string +then \fBTCL_ERROR\fR is returned, +an error message is left in \fIinterp\fR's result, +and no information is left at \fI*parsePtr\fR or \fI*termPtr\fR. +.PP +\fBTcl_ParseVarName\fR parses a Tcl variable reference such as +\fB$abc\fR or \fB$x([expr $index + 1])\fR from the beginning of its +\fIstring\fR argument. +The first character of \fIstring\fR must be \fB$\fR. +If a variable name was parsed successfully, \fBTcl_ParseVarName\fR +returns \fBTCL_OK\fR and fills in the structure pointed to by +\fIparsePtr\fR with information about the structure of the variable name +(see below for details). If an error +occurrs while parsing the command then \fBTCL_ERROR\fR is returned, an +error message is left in \fIinterp\fR's result (if \fIinterp\fR isn't +NULL), and no information is left at \fI*parsePtr\fR. +.PP +\fBTcl_ParseVar\fR parse a Tcl variable reference such as \fB$abc\fR +or \fB$x([expr $index + 1])\fR from the beginning of its \fIstring\fR +argument. The first character of \fIstring\fR must be \fB$\fR. If +the variable name is parsed successfully, \fBTcl_ParseVar\fR returns a +pointer to the string value of the variable. If an error occurs while +parsing, then NULL is returned and an error message is left in +\fIinterp\fR's result. +.PP +The information left at \fI*parsePtr\fR +by \fBTcl_ParseCommand\fR, \fBTcl_ParseExpr\fR, \fBTcl_ParseBraces\fR, +\fBTcl_ParseQuotedString\fR, and \fBTcl_ParseVarName\fR +may include dynamically allocated memory. +If these five parsing procedures return \fBTCL_OK\fR +then the caller must invoke \fBTcl_FreeParse\fR to release +the storage at \fI*parsePtr\fR. +These procedures ignore any existing information in +\fI*parsePtr\fR (unless \fIappend\fR is non-zero), +so if repeated calls are being made to any of them +then \fBTcl_FreeParse\fR must be invoked once after each call. +.PP +\fBTcl_EvalTokens\fR evaluates a sequence of parse tokens from a Tcl_Parse +structure. The tokens typically consist +of all the tokens in a word or all the tokens that make up the index for +a reference to an array variable. \fBTcl_EvalTokens\fR performs the +substitutions requested by the tokens, concatenates the +resulting values, and returns the result in a new Tcl_Obj. The +reference count of the object returned as result has been +incremented, so the caller must +invoke \fBTcl_DecrRefCount\fR when it is finished with the object. +If an error occurs while evaluating the tokens (such as a reference to +a non-existent variable) then the return value is NULL and an error +message is left in \fIinterp\fR's result. + +.SH "TCL_PARSE STRUCTURE" +.PP +\fBTcl_ParseCommand\fR, \fBTcl_ParseExpr\fR, \fBTcl_ParseBraces\fR, +\fBTcl_ParseQuotedString\fR, and \fBTcl_ParseVarName\fR +return parse information in two data structures, Tcl_Parse and Tcl_Token: +.CS +typedef struct Tcl_Parse { + char *\fIcommentStart\fR; + int \fIcommentSize\fR; + char *\fIcommandStart\fR; + int \fIcommandSize\fR; + int \fInumWords\fR; + Tcl_Token *\fItokenPtr\fR; + int \fInumTokens\fR; + ... +} Tcl_Parse; + +typedef struct Tcl_Token { + int \fItype\fR; + char *\fIstart\fR; + int \fIsize\fR; + int \fInumComponents\fR; +} Tcl_Token; +.CE +.PP +The first five fields of a Tcl_Parse structure +are filled in only by \fBTcl_ParseCommand\fR. +These fields are not used by the other parsing procedures. +.PP +\fBTcl_ParseCommand\fR fills in a Tcl_Parse structure +with information that describes one Tcl command and any comments that +precede the command. +If there are comments, +the \fIcommentStart\fR field points to the \fB#\fR character that begins +the first comment and \fIcommentSize\fR indicates the number of bytes +in all of the comments preceding the command, including the newline +character that terminates the last comment. +If the command is not preceded by any comments, \fIcommentSize\fR is 0. +\fBTcl_ParseCommand\fR also sets the \fIcommandStart\fR field +to point to the first character of the first +word in the command (skipping any comments and leading space) and +\fIcommandSize\fR gives the total number of bytes in the command, +including the character pointed to by \fIcommandStart\fR up to and +including the newline, close bracket, or semicolon character that +terminates the command. The \fInumWords\fR field gives the +total number of words in the command. +.PP +All parsing procedures set the remaining fields, +\fItokenPtr\fR and \fInumTokens\fR. +The \fItokenPtr\fR field points to the first in an array of Tcl_Token +structures that describe the components of the entity being parsed. +The \fInumTokens\fR field gives the total number of tokens +present in the array. +Each token contains four fields. +The \fItype\fR field selects one of several token types +that are described below. The \fIstart\fR field +points to the first character in the token and the \fIsize\fR field +gives the total number of characters in the token. Some token types, +such as \fBTCL_TOKEN_WORD\fR and \fBTCL_TOKEN_VARIABLE\fR, consist of +several component tokens, which immediately follow the parent token; +the \fInumComponents\fR field describes how many of these there are. +The \fItype\fR field has one of the following values: +.TP 20 +\fBTCL_TOKEN_WORD\fR +This token ordinarily describes one word of a command +but it may also describe a quoted or braced string in an expression. +The token describes a component of the script that is +the result of concatenating together a sequence of subcomponents, +each described by a separate subtoken. +The token starts with the first non-blank +character of the component (which may be a double-quote or open brace) +and includes all characters in the component up to but not including the +space, semicolon, close bracket, close quote, or close brace that +terminates the component. The \fInumComponents\fR field counts the total +number of sub-tokens that make up the word, including sub-tokens +of \fBTCL_TOKEN_VARIABLE\fR and \fBTCL_TOKEN_BS\fR tokens. +.TP +\fBTCL_TOKEN_SIMPLE_WORD\fR +This token has the same meaning as \fBTCL_TOKEN_WORD\fR, except that +the word is guaranteed to consist of a single \fBTCL_TOKEN_TEXT\fR +sub-token. The \fInumComponents\fR field is always 1. +.TP +\fBTCL_TOKEN_TEXT\fR +The token describes a range of literal text that is part of a word. +The \fInumComponents\fR field is always 0. +.TP +\fBTCL_TOKEN_BS\fR +The token describes a backslash sequence such as \fB\en\fR or \fB\e0xa3\fR. +The \fInumComponents\fR field is always 0. +.TP +\fBTCL_TOKEN_COMMAND\fR +The token describes a command whose result result must be substituted into +the word. The token includes the square brackets that surround the +command. The \fInumComponents\fR field is always 0 (the nested command +is not parsed; call \fBTcl_ParseCommand\fR recursively if you want to +see its tokens). +.TP +\fBTCL_TOKEN_VARIABLE\fR +The token describes a variable substitution, including the +\fB$\fR, variable name, and array index (if there is one) up through the +close parenthesis that terminates the index. This token is followed +by one or more additional tokens that describe the variable name and +array index. If \fInumComponents\fR is 1 then the variable is a +scalar and the next token is a \fBTCL_TOKEN_TEXT\fR token that gives the +variable name. If \fInumComponents\fR is greater than 1 then the +variable is an array: the first sub-token is a \fBTCL_TOKEN_TEXT\fR +token giving the array name and the remaining sub-tokens are +\fBTCL_TOKEN_TEXT\fR, \fBTCL_TOKEN_BS\fR, \fBTCL_TOKEN_COMMAND\fR, and +\fBTCL_TOKEN_VARIABLE\fR tokens that must be concatenated to produce the +array index. The \fInumComponents\fR field includes nested sub-tokens +that are part of \fBTCL_TOKEN_VARIABLE\fR tokens in the array index. +.TP +\fBTCL_TOKEN_SUB_EXPR\fR +The token describes one subexpression of an expression +(or an entire expression). +A subexpression may consist of a value +such as an integer literal, variable substitution, +or parenthesized subexpression; +it may also consist of an operator and its operands. +The token starts with the first non-blank character of the subexpression +up to but not including the space, brace, close-paren, or bracket +that terminates the subexpression. +This token is followed by one or more additional tokens +that describe the subexpression. +If the first sub-token after the \fBTCL_TOKEN_SUB_EXPR\fR token +is a \fBTCL_TOKEN_OPERATOR\fR token, +the subexpression consists of an operator and its token operands. +If the operator has no operands, the subexpression consists of +just the \fBTCL_TOKEN_OPERATOR\fR token. +Each operand is described by a \fBTCL_TOKEN_SUB_EXPR\fR token. +Otherwise, the subexpression is a value described by +one of the token types \fBTCL_TOKEN_WORD\fR, \fBTCL_TOKEN_TEXT\fR, +\fBTCL_TOKEN_BS\fR, \fBTCL_TOKEN_COMMAND\fR, +\fBTCL_TOKEN_VARIABLE\fR, and \fBTCL_TOKEN_SUB_EXPR\fR. +The \fInumComponents\fR field +counts the total number of sub-tokens that make up the subexpression; +this includes the sub-tokens for any nested \fBTCL_TOKEN_SUB_EXPR\fR tokens. +.TP +\fBTCL_TOKEN_OPERATOR\fR +The token describes one operator of an expression +such as \fB&&\fR or \fBhypot\fR. +An \fBTCL_TOKEN_OPERATOR\fR token is always preceeded by a +\fBTCL_TOKEN_SUB_EXPR\fR token +that describes the operator and its operands; +the \fBTCL_TOKEN_SUB_EXPR\fR token's \fInumComponents\fR field +can be used to determine the number of operands. +A binary operator such as \fB*\fR +is followed by two \fBTCL_TOKEN_SUB_EXPR\fR tokens +that describe its operands. +A unary operator like \fB-\fR +is followed by a single \fBTCL_TOKEN_SUB_EXPR\fR token +for its operand. +If the operator is a math function such as \fBlog10\fR, +the \fBTCL_TOKEN_OPERATOR\fR token will give its name and +the following \fBTCL_TOKEN_SUB_EXPR\fR tokens will describe +its operands; +if there are no operands (as with \fBrand\fR), +no \fBTCL_TOKEN_SUB_EXPR\fR tokens follow. +There is one trinary operator, \fB?\fR, +that appears in if-then-else subexpressions +such as \fIx\fB?\fIy\fB:\fIz\fR; +in this case, the \fB?\fR \fBTCL_TOKEN_OPERATOR\fR token +is followed by three \fBTCL_TOKEN_SUB_EXPR\fR tokens for the operands +\fIx\fR, \fIy\fR, and \fIz\fR. +The \fInumComponents\fR field for a \fBTCL_TOKEN_OPERATOR\fR token +is always 0. +.PP +After \fBTcl_ParseCommand\fR returns, the first token pointed to by +the \fItokenPtr\fR field of the +Tcl_Parse structure always has type \fBTCL_TOKEN_WORD\fR or +\fBTCL_TOKEN_SIMPLE_WORD\fR. It is followed by the sub-tokens +that must be concatenated to produce the value of that word. +The next token is the \fBTCL_TOKEN_WORD\fR or \fBTCL_TOKEN_SIMPLE_WORD\fR +token for the second word, followed by sub-tokens for that +word, and so on until all \fInumWords\fR have been accounted +for. +.PP +After \fBTcl_ParseExpr\fR returns, the first token pointed to by +the \fItokenPtr\fR field of the +Tcl_Parse structure always has type \fBTCL_TOKEN_SUB_EXPR\fR. +It is followed by the sub-tokens that must be evaluated +to produce the value of the expression. +Only the token information in the Tcl_Parse structure +is modified: the \fIcommentStart\fR, \fIcommentSize\fR, +\fIcommandStart\fR, and \fIcommandSize\fR fields are not modified +by \fBTcl_ParseExpr\fR. +.PP +After \fBTcl_ParseBraces\fR returns, +the array of tokens pointed to by the \fItokenPtr\fR field of the +Tcl_Parse structure will contain a single \fBTCL_TOKEN_TEXT\fR token +if the braced string does not contain any backslash-newlines. +If the string does contain backslash-newlines, +the array of tokens will contain one or more +\fBTCL_TOKEN_TEXT\fR or \fBTCL_TOKEN_BS\fR sub-tokens +that must be concatenated to produce the value of the string. +If the braced string was just \fB{}\fR +(that is, the string was empty), +the single \fBTCL_TOKEN_TEXT\fR token will have a \fIsize\fR field +containing zero; +this ensures that at least one token appears +to describe the braced string. +Only the token information in the Tcl_Parse structure +is modified: the \fIcommentStart\fR, \fIcommentSize\fR, +\fIcommandStart\fR, and \fIcommandSize\fR fields are not modified +by \fBTcl_ParseBraces\fR. +.PP +After \fBTcl_ParseQuotedString\fR returns, +the array of tokens pointed to by the \fItokenPtr\fR field of the +Tcl_Parse structure depends on the contents of the quoted string. +It will consist of one or more \fBTCL_TOKEN_TEXT\fR, \fBTCL_TOKEN_BS\fR, +\fBTCL_TOKEN_COMMAND\fR, and \fBTCL_TOKEN_VARIABLE\fR sub-tokens. +The array always contains at least one token; +for example, if the argument \fIstring\fR is empty, +the array returned consists of a single \fBTCL_TOKEN_TEXT\fR token +with a zero \fIsize\fR field. +Only the token information in the Tcl_Parse structure +is modified: the \fIcommentStart\fR, \fIcommentSize\fR, +\fIcommandStart\fR, and \fIcommandSize\fR fields are not modified. +.PP +After \fBTcl_ParseVarName\fR returns, the first token pointed to by +the \fItokenPtr\fR field of the +Tcl_Parse structure always has type \fBTCL_TOKEN_VARIABLE\fR. It +is followed by the sub-tokens that make up the variable name as +described above. The total length of the variable name is +contained in the \fIsize\fR field of the first token. +As in \fBTcl_ParseExpr\fR, +only the token information in the Tcl_Parse structure +is modified by \fBTcl_ParseVarName\fR: +the \fIcommentStart\fR, \fIcommentSize\fR, +\fIcommandStart\fR, and \fIcommandSize\fR fields are not modified. +.PP +All of the character pointers in the +Tcl_Parse and Tcl_Token structures refer +to characters in the \fIstring\fR argument passed to +\fBTcl_ParseCommand\fR, \fBTcl_ParseExpr\fR, \fBTcl_ParseBraces\fR, +\fBTcl_ParseQuotedString\fR, and \fBTcl_ParseVarName\fR. +.PP +There are additional fields in the Tcl_Parse structure after the +\fInumTokens\fR field, but these are for the private use of +\fBTcl_ParseCommand\fR, \fBTcl_ParseExpr\fR, \fBTcl_ParseBraces\fR, +\fBTcl_ParseQuotedString\fR, and \fBTcl_ParseVarName\fR; they should not be +referenced by code outside of these procedures. + +.SH KEYWORDS +backslash substitution, braces, command, expression, parse, token, variable substitution diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/PkgRequire.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/PkgRequire.3 new file mode 100644 index 0000000000000000000000000000000000000000..f0a83068d2291a0ef8145e13abed87ab4caf04ac --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/PkgRequire.3 @@ -0,0 +1,87 @@ +'\" +'\" Copyright (c) 1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: PkgRequire.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_PkgRequire 3 7.5 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_PkgRequire, Tcl_PkgRequireEx, Tcl_PkgPresent, Tcl_PkgPresentEx, Tcl_PkgProvide, Tcl_PkgProvideEx \- package version control +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +char * +\fBTcl_PkgRequire\fR(\fIinterp, name, version, exact\fR) +.sp +char * +\fBTcl_PkgRequireEx\fR(\fIinterp, name, version, exact, clientDataPtr\fR) +.sp +char * +\fBTcl_PkgPresent\fR(\fIinterp, name, version, exact\fR) +.sp +char * +\fBTcl_PkgPresentEx\fR(\fIinterp, name, version, exact, clientDataPtr\fR) +.sp +int +\fBTcl_PkgProvide\fR(\fIinterp, name, version\fR) +.sp +int +\fBTcl_PkgProvideEx\fR(\fIinterp, name, version, clientData\fR) +.SH ARGUMENTS +.AS Tcl_FreeProc clientDataPtr +.AP Tcl_Interp *interp in +Interpreter where package is needed or available. +.AP char *name in +Name of package. +.AP char *version in +A version string consisting of one or more decimal numbers +separated by dots. +.AP int exact in +Non-zero means that only the particular version specified by +\fIversion\fR is acceptable. +Zero means that newer versions than \fIversion\fR are also +acceptable as long as they have the same major version number +as \fIversion\fR. +.AP ClientData clientData in +Arbitrary value to be associated with the package. +.AP ClientData *clientDataPtr out +Pointer to place to store the value associated with the matching +package. It is only changed if the pointer is not NULL and the +function completed successfully. +.BE + +.SH DESCRIPTION +.PP +These procedures provide C-level interfaces to Tcl's package and +version management facilities. +.PP +\fBTcl_PkgRequire\fR is equivalent to the \fBpackage require\fR +command, \fBTcl_PkgPresent\fR is equivalent to the \fBpackage present\fR +command, and \fBTcl_PkgProvide\fR is equivalent to the +\fBpackage provide\fR command. +.PP +See the documentation for the Tcl commands for details on what these +procedures do. +.PP +If \fBTcl_PkgPresent\fR or \fBTcl_PkgRequire\fR complete successfully +they return a pointer to the version string for the version of the package +that is provided in the interpreter (which may be different than +\fIversion\fR); if an error occurs they return NULL and leave an error +message in the interpreter's result. +.PP +\fBTcl_PkgProvide\fR returns TCL_OK if it completes successfully; +if an error occurs it returns TCL_ERROR and leaves an error message +in the interpreter's result. +.PP +\fBTcl_PkgProvideEx\fR, \fBTcl_PkgPresentEx\fR and \fBTcl_PkgRequireEx\fR +allow the setting and retrieving of the client data associated with +the package. In all other respects they are equivalent to the matching +functions. + +.SH KEYWORDS +package, present, provide, require, version diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Preserve.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Preserve.3 new file mode 100644 index 0000000000000000000000000000000000000000..8836c4892179b42c673cc12be3fa00ee4d284350 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Preserve.3 @@ -0,0 +1,103 @@ +'\" +'\" Copyright (c) 1990 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: Preserve.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_Preserve 3 7.5 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_Preserve, Tcl_Release, Tcl_EventuallyFree \- avoid freeing storage while it's being used +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +\fBTcl_Preserve\fR(\fIclientData\fR) +.sp +\fBTcl_Release\fR(\fIclientData\fR) +.sp +\fBTcl_EventuallyFree\fR(\fIclientData, freeProc\fR) +.SH ARGUMENTS +.AS Tcl_FreeProc clientData +.AP ClientData clientData in +Token describing structure to be freed or reallocated. Usually a pointer +to memory for structure. +.AP Tcl_FreeProc *freeProc in +Procedure to invoke to free \fIclientData\fR. +.BE + +.SH DESCRIPTION +.PP +These three procedures help implement a simple reference count mechanism +for managing storage. They are designed to solve a problem +having to do with widget deletion, but are also useful in many other +situations. When a widget is deleted, its +widget record (the structure holding information specific to the +widget) must be returned to the storage allocator. +However, it's possible that the widget record is in active use +by one of the procedures on the stack at the time of the deletion. +This can happen, for example, if the command associated with a button +widget causes the button to be destroyed: an X event causes an +event-handling C procedure in the button to be invoked, which in +turn causes the button's associated Tcl command to be executed, +which in turn causes the button to be deleted, which in turn causes +the button's widget record to be de-allocated. +Unfortunately, when the Tcl command returns, the button's +event-handling procedure will need to reference the +button's widget record. +Because of this, the widget record must not be freed as part of the +deletion, but must be retained until the event-handling procedure has +finished with it. +In other situations where the widget is deleted, it may be possible +to free the widget record immediately. +.PP +\fBTcl_Preserve\fR and \fBTcl_Release\fR +implement short-term reference counts for their \fIclientData\fR +argument. +The \fIclientData\fR argument identifies an object and usually +consists of the address of a structure. +The reference counts guarantee that an object will not be freed +until each call to \fBTcl_Preserve\fR for the object has been +matched by calls to \fBTcl_Release\fR. +There may be any number of unmatched \fBTcl_Preserve\fR calls +in effect at once. +.PP +\fBTcl_EventuallyFree\fR is invoked to free up its \fIclientData\fR +argument. +It checks to see if there are unmatched \fBTcl_Preserve\fR calls +for the object. +If not, then \fBTcl_EventuallyFree\fR calls \fIfreeProc\fR immediately. +Otherwise \fBTcl_EventuallyFree\fR records the fact that \fIclientData\fR +needs eventually to be freed. +When all calls to \fBTcl_Preserve\fR have been matched with +calls to \fBTcl_Release\fR then \fIfreeProc\fR will be called by +\fBTcl_Release\fR to do the cleanup. +.PP +All the work of freeing the object is carried out by \fIfreeProc\fR. +\fIFreeProc\fR must have arguments and result that match the +type \fBTcl_FreeProc\fR: +.CS +typedef void Tcl_FreeProc(char *\fIblockPtr\fR); +.CE +The \fIblockPtr\fR argument to \fIfreeProc\fR will be the +same as the \fIclientData\fR argument to \fBTcl_EventuallyFree\fR. +The type of \fIblockPtr\fR (\fBchar *\fR) is different than the type of the +\fIclientData\fR argument to \fBTcl_EventuallyFree\fR for historical +reasons, but the value is the same. +.PP +This mechanism can be used to solve the problem described above +by placing \fBTcl_Preserve\fR and \fBTcl_Release\fR calls around +actions that may cause undesired storage re-allocation. The +mechanism is intended only for short-term use (i.e. while procedures +are pending on the stack); it will not work efficiently as a +mechanism for long-term reference counts. +The implementation does not depend in any way on the internal +structure of the objects being freed; it keeps the reference +counts in a separate structure. + +.SH KEYWORDS +free, reference count, storage diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/PrintDbl.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/PrintDbl.3 new file mode 100644 index 0000000000000000000000000000000000000000..d26b1e58f9553d0f6c265e52b4ad08d3dbabeb31 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/PrintDbl.3 @@ -0,0 +1,47 @@ +'\" +'\" Copyright (c) 1989-1993 The Regents of the University of California. +'\" Copyright (c) 1994-1997 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: PrintDbl.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_PrintDouble 3 8.0 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_PrintDouble \- Convert floating value to string +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +\fBTcl_PrintDouble\fR(\fIinterp, value, dst\fR) +.SH ARGUMENTS +.AS Tcl_Interp *interp +.AP Tcl_Interp *interp in +.VS +Before Tcl 8.0, the \fBtcl_precision\fR variable in this interpreter +controlled the conversion. As of Tcl 8.0, this argument is ignored and +the conversion is controlled by the \fBtcl_precision\fR variable +that is now shared by all interpreters. +.VE +.AP double value in +Floating-point value to be converted. +.AP char *dst out +Where to store string representing \fIvalue\fR. Must have at +least TCL_DOUBLE_SPACE characters of storage. +.BE + +.SH DESCRIPTION +.PP +\fBTcl_PrintDouble\fR generates a string that represents the value +of \fIvalue\fR and stores it in memory at the location given by +\fIdst\fR. It uses \fB%g\fR format to generate the string, with one +special twist: the string is guaranteed to contain either +a ``.'' or an ``e'' so that it doesn't look like an integer. Where +\fB%g\fR would generate an integer with no decimal point, \fBTcl_PrintDouble\fR +adds ``.0''. + +.SH KEYWORDS +conversion, double-precision, floating-point, string diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/RecEvalObj.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/RecEvalObj.3 new file mode 100644 index 0000000000000000000000000000000000000000..a70c6b3acb24708825007898e98a0ca5c47bb27f --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/RecEvalObj.3 @@ -0,0 +1,55 @@ +'\" +'\" Copyright (c) 1997 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: RecEvalObj.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_RecordAndEvalObj 3 8.0 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_RecordAndEvalObj \- save command on history list before evaluating +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +int +\fBTcl_RecordAndEvalObj\fR(\fIinterp, cmdPtr, flags\fR) +.SH ARGUMENTS +.AS Tcl_Interp *interp; +.AP Tcl_Interp *interp in +Tcl interpreter in which to evaluate command. +.AP Tcl_Obj *cmdPtr in +Points to a Tcl object containing a command (or sequence of commands) +to execute. +.AP int flags in +An OR'ed combination of flag bits. TCL_NO_EVAL means record the +command but don't evaluate it. TCL_EVAL_GLOBAL means evaluate +the command at global level instead of the current stack level. +.BE + +.SH DESCRIPTION +.PP +\fBTcl_RecordAndEvalObj\fR is invoked to record a command as an event +on the history list and then execute it using \fBTcl_EvalObjEx\fR +(or \fBTcl_GlobalEvalObj\fR if the TCL_EVAL_GLOBAL bit is set +in \fIflags\fR). +It returns a completion code such as TCL_OK just like \fBTcl_EvalObjEx\fR, +as well as a result object containing additional information +(a result value or error message) +that can be retrieved using \fBTcl_GetObjResult\fR. +If you don't want the command recorded on the history list then +you should invoke \fBTcl_EvalObjEx\fR instead of \fBTcl_RecordAndEvalObj\fR. +Normally \fBTcl_RecordAndEvalObj\fR is only called with top-level +commands typed by the user, since the purpose of history is to +allow the user to re-issue recently-invoked commands. +If the \fIflags\fR argument contains the TCL_NO_EVAL bit then +the command is recorded without being evaluated. + +.SH "SEE ALSO" +Tcl_EvalObjEx, Tcl_GetObjResult + +.SH KEYWORDS +command, event, execute, history, interpreter, object, record diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/RecordEval.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/RecordEval.3 new file mode 100644 index 0000000000000000000000000000000000000000..d1fb1ea225a96d49d8f252981c1b8ddc948a7a97 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/RecordEval.3 @@ -0,0 +1,57 @@ +'\" +'\" Copyright (c) 1989-1993 The Regents of the University of California. +'\" Copyright (c) 1994-1997 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: RecordEval.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_RecordAndEval 3 7.4 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_RecordAndEval \- save command on history list before evaluating +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +int +\fBTcl_RecordAndEval\fR(\fIinterp, cmd, flags\fR) +.SH ARGUMENTS +.AS Tcl_Interp *interp; +.AP Tcl_Interp *interp in +Tcl interpreter in which to evaluate command. +.AP char *cmd in +Command (or sequence of commands) to execute. +.AP int flags in +An OR'ed combination of flag bits. TCL_NO_EVAL means record the +command but don't evaluate it. TCL_EVAL_GLOBAL means evaluate +the command at global level instead of the current stack level. +.BE + +.SH DESCRIPTION +.PP +\fBTcl_RecordAndEval\fR is invoked to record a command as an event +on the history list and then execute it using \fBTcl_Eval\fR +(or \fBTcl_GlobalEval\fR if the TCL_EVAL_GLOBAL bit is set in \fIflags\fR). +It returns a completion code such as TCL_OK just like \fBTcl_Eval\fR +and it leaves information in the interpreter's result. +If you don't want the command recorded on the history list then +you should invoke \fBTcl_Eval\fR instead of \fBTcl_RecordAndEval\fR. +Normally \fBTcl_RecordAndEval\fR is only called with top-level +commands typed by the user, since the purpose of history is to +allow the user to re-issue recently-invoked commands. +If the \fIflags\fR argument contains the TCL_NO_EVAL bit then +the command is recorded without being evaluated. +.PP +Note that \fBTcl_RecordAndEval\fR has been largely replaced by the +object-based procedure \fBTcl_RecordAndEvalObj\fR. +That object-based procedure records and optionally executes +a command held in a Tcl object instead of a string. + +.SH "SEE ALSO" +Tcl_RecordAndEvalObj + +.SH KEYWORDS +command, event, execute, history, interpreter, record diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/RegExp.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/RegExp.3 new file mode 100644 index 0000000000000000000000000000000000000000..64493a42b279762a80029d804a9c9bb89d57b21c --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/RegExp.3 @@ -0,0 +1,346 @@ +'\" +'\" Copyright (c) 1994 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" Copyright (c) 1998-1999 Scriptics Corportation +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: RegExp.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_RegExpMatch 3 8.1 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_RegExpMatch, Tcl_RegExpCompile, Tcl_RegExpExec, Tcl_RegExpRange, Tcl_GetRegExpFromObj, Tcl_RegExpMatchObj, Tcl_RegExpExecObj, Tcl_RegExpGetInfo \- Pattern matching with regular expressions +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +int +\fBTcl_RegExpMatchObj\fR(\fIinterp\fR, \fIstrObj\fR, \fIpatObj\fR) +.sp +int +\fBTcl_RegExpMatch\fR(\fIinterp\fR, \fIstring\fR, \fIpattern\fR) +.sp +Tcl_RegExp +\fBTcl_RegExpCompile\fR(\fIinterp\fR, \fIpattern\fR) +.sp +int +\fBTcl_RegExpExec\fR(\fIinterp\fR, \fIregexp\fR, \fIstring\fR, \fIstart\fR) +.sp +\fBTcl_RegExpRange\fR(\fIregexp\fR, \fIindex\fR, \fIstartPtr\fR, \fIendPtr\fR) +.VS 8.1 +.sp +Tcl_RegExp +\fBTcl_GetRegExpFromObj\fR(\fIinterp\fR, \fIpatObj\fR, \fIcflags\fR) +.sp +int +\fBTcl_RegExpExecObj\fR(\fIinterp\fR, \fIregexp\fR, \fIobjPtr\fR, \fIoffset\fR, \fInmatches\fR, \fIeflags\fR) +.sp +\fBTcl_RegExpGetInfo\fR(\fIregexp\fR, \fIinfoPtr\fR) +.VE 8.1 + +.SH ARGUMENTS +.AS Tcl_Interp *interp +.AP Tcl_Interp *interp in +Tcl interpreter to use for error reporting. The interpreter may be +NULL if no error reporting is desired. +.VS 8.1 +.AP Tcl_Obj *strObj in/out +Refers to the object from which to get the string to search. The +internal representation of the object may be converted to a form that +can be efficiently searched. +.AP Tcl_Obj *patObj in/out +Refers to the object from which to get a regular expression. The +compiled regular expression is cached in the object. +.VE 8.1 +.AP char *string in +String to check for a match with a regular expression. +.AP char *pattern in +String in the form of a regular expression pattern. +.AP Tcl_RegExp regexp in +Compiled regular expression. Must have been returned previously +by \fBTcl_GetRegExpFromObj\fR or \fBTcl_RegExpCompile\fR. +.AP char *start in +If \fIstring\fR is just a portion of some other string, this argument +identifies the beginning of the larger string. +If it isn't the same as \fIstring\fR, then no \fB^\fR matches +will be allowed. +.AP int index in +Specifies which range is desired: 0 means the range of the entire +match, 1 or greater means the range that matched a parenthesized +sub-expression. +.AP char **startPtr out +The address of the first character in the range is stored here, or +NULL if there is no such range. +.AP char **endPtr out +The address of the character just after the last one in the range +is stored here, or NULL if there is no such range. +.VS 8.1 +.AP int cflags in +OR-ed combination of compilation flags. See below for more information. +.AP Tcl_Obj *objPtr in/out +An object which contains the string to check for a match with a +regular expression. +.AP int offset in +The character offset into the string where matching should begin. +The value of the offset has no impact on \fB^\fR matches. This +behavior is controlled by \fIeflags\fR. +.AP int nmatches in +The number of matching subexpressions that should be remembered for +later use. If this value is 0, then no subexpression match +information will be computed. If the value is -1, then +all of the matching subexpressions will be remembered. Any other +value will be taken as the maximum number of subexpressions to +remember. +.AP int eflags in +OR-ed combination of the values TCL_REG_NOTBOL and TCL_REG_NOTEOL. +See below for more information. +.AP Tcl_RegExpInfo *infoPtr out +The address of the location where information about a previous match +should be stored by \fBTcl_RegExpGetInfo\fR. +.VE 8.1 +.BE + +.SH DESCRIPTION +.PP +\fBTcl_RegExpMatch\fR determines whether its \fIpattern\fR argument +matches \fIregexp\fR, where \fIregexp\fR is interpreted +as a regular expression using the rules in the \fBre_syntax\fR +reference page. +If there is a match then \fBTcl_RegExpMatch\fR returns 1. +If there is no match then \fBTcl_RegExpMatch\fR returns 0. +If an error occurs in the matching process (e.g. \fIpattern\fR +is not a valid regular expression) then \fBTcl_RegExpMatch\fR +returns \-1 and leaves an error message in the interpreter result. +.VS 8.1.2 +\fBTcl_RegExpMatchObj\fR is similar to \fBTcl_RegExpMatch\fR except it +operates on the Tcl objects \fIstrObj\fR and \fIpatObj\fR instead of +UTF strings. +\fBTcl_RegExpMatchObj\fR is generally more efficient than +\fBTcl_RegExpMatch\fR, so it is the preferred interface. +.VE 8.1.2 +.PP +\fBTcl_RegExpCompile\fR, \fBTcl_RegExpExec\fR, and \fBTcl_RegExpRange\fR +provide lower-level access to the regular expression pattern matcher. +\fBTcl_RegExpCompile\fR compiles a regular expression string into +the internal form used for efficient pattern matching. +The return value is a token for this compiled form, which can be +used in subsequent calls to \fBTcl_RegExpExec\fR or \fBTcl_RegExpRange\fR. +If an error occurs while compiling the regular expression then +\fBTcl_RegExpCompile\fR returns NULL and leaves an error message +in the interpreter result. +Note: the return value from \fBTcl_RegExpCompile\fR is only valid +up to the next call to \fBTcl_RegExpCompile\fR; it is not safe to +retain these values for long periods of time. +.PP +\fBTcl_RegExpExec\fR executes the regular expression pattern matcher. +It returns 1 if \fIstring\fR contains a range of characters that +match \fIregexp\fR, 0 if no match is found, and +\-1 if an error occurs. +In the case of an error, \fBTcl_RegExpExec\fR leaves an error +message in the interpreter result. +When searching a string for multiple matches of a pattern, +it is important to distinguish between the start of the original +string and the start of the current search. +For example, when searching for the second occurrence of a +match, the \fIstring\fR argument might point to the character +just after the first match; however, it is important for the +pattern matcher to know that this is not the start of the entire string, +so that it doesn't allow \fB^\fR atoms in the pattern to match. +The \fIstart\fR argument provides this information by pointing +to the start of the overall string containing \fIstring\fR. +\fIStart\fR will be less than or equal to \fIstring\fR; if it +is less than \fIstring\fR then no \fB^\fR matches will be allowed. +.PP +\fBTcl_RegExpRange\fR may be invoked after \fBTcl_RegExpExec\fR +returns; it provides detailed information about what ranges of +the string matched what parts of the pattern. +\fBTcl_RegExpRange\fR returns a pair of pointers in \fI*startPtr\fR +and \fI*endPtr\fR that identify a range of characters in +the source string for the most recent call to \fBTcl_RegExpExec\fR. +\fIIndex\fR indicates which of several ranges is desired: +if \fIindex\fR is 0, information is returned about the overall range +of characters that matched the entire pattern; otherwise, +information is returned about the range of characters that matched the +\fIindex\fR'th parenthesized subexpression within the pattern. +If there is no range corresponding to \fIindex\fR then NULL +is stored in \fI*startPtr\fR and \fI*endPtr\fR. +.PP +.VS 8.1 +\fBTcl_GetRegExpFromObj\fR, \fBTcl_RegExpExecObj\fR, and +\fBTcl_RegExpGetInfo\fR are object interfaces that provide the most +direct control of Henry Spencer's regular expression library. For +users that need to modify compilation and execution options directly, +it is recommended that you use these interfaces instead of calling the +internal regexp functions. These interfaces handle the details of UTF +to Unicode translations as well as providing improved performance +through caching in the pattern and string objects. +.PP +\fBTcl_GetRegExpFromObj\fR attepts to return a compiled regular +expression from the \fIpatObj\fR. If the object does not already +contain a compiled regular expression it will attempt to create one +from the string in the object and assign it to the internal +representation of the \fIpatObj\fR. The return value of this function +is of type \fBTcl_RegExp\fR. The return value is a token for this +compiled form, which can be used in subsequent calls to +\fBTcl_RegExpExecObj\fR or \fBTcl_RegExpGetInfo\fR. If an error +occurs while compiling the regular expression then +\fBTcl_GetRegExpFromObj\fR returns NULL and leaves an error message in +the interpreter result. The regular expression token can be used as +long as the internal representation of \fIpatObj\fR refers to the +compiled form. The \fIeflags\fR argument is a bitwise OR of +zero or more of the following flags that control the compilation of +\fIpatObj\fR: +.RS 2 +.TP +\fBTCL_REG_ADVANCED\fR +Compile advanced regular expressions (`AREs'). This mode corresponds to +the normal regular expression syntax accepted by the Tcl regexp and +regsub commands. +.TP +\fBTCL_REG_EXTENDED\fR +Compile extended regular expressions (`EREs'). This mode corresponds +to the regular expression syntax recognized by Tcl 8.0 and earlier +versions. +.TP +\fBTCL_REG_BASIC\fR +Compile basic regular expressions (`BREs'). This mode corresponds +to the regular expression syntax recognized by common Unix utilities +like \fBsed\fR and \fBgrep\fR. This is the default if no flags are +specified. +.TP +\fBTCL_REG_EXPANDED\fR +Compile the regular expression (basic, extended, or advanced) using an +expanded syntax that allows comments and whitespace. This mode causes +non-backslashed non-bracket-expression white +space and #-to-end-of-line comments to be ignored. +.TP +\fBTCL_REG_QUOTE\fR +Compile a literal string, with all characters treated as ordinary characters. +.TP +\fBTCL_REG_NOCASE\fR +Compile for matching that ignores upper/lower case distinctions. +.TP +\fBTCL_REG_NEWLINE\fR +Compile for newline-sensitive matching. By default, newline is a +completely ordinary character with no special meaning in either +regular expressions or strings. With this flag, `[^' bracket +expressions and `.' never match newline, `^' matches an empty string +after any newline in addition to its normal function, and `$' matches +an empty string before any newline in addition to its normal function. +\fBREG_NEWLINE\fR is the bitwise OR of \fBREG_NLSTOP\fR and +\fBREG_NLANCH\fR. +.TP +\fBTCL_REG_NLSTOP\fR +Compile for partial newline-sensitive matching, +with the behavior of +`[^' bracket expressions and `.' affected, +but not the behavior of `^' and `$'. In this mode, `[^' bracket +expressions and `.' never match newline. +.TP +\fBTCL_REG_NLANCH\fR +Compile for inverse partial newline-sensitive matching, +with the behavior of +of `^' and `$' (the ``anchors'') affected, but not the behavior of +`[^' bracket expressions and `.'. In this mode `^' matches an empty string +after any newline in addition to its normal function, and `$' matches +an empty string before any newline in addition to its normal function. +.TP +\fBTCL_REG_NOSUB\fR +Compile for matching that reports only success or failure, +not what was matched. This reduces compile overhead and may improve +performance. Subsequent calls to \fBTcl_RegExpGetInfo\fR or +\fBTcl_RegExpRange\fR will not report any match information. +.TP +\fBTCL_REG_CANMATCH\fR +Compile for matching that reports the potential to complete a partial +match given more text (see below). +.RE +.PP +Only one of +\fBTCL_REG_EXTENDED\fR, +\fBTCL_REG_ADVANCED\fR, +\fBTCL_REG_BASIC\fR, and +\fBTCL_REG_QUOTE\fR may be specified. +.PP +\fBTcl_RegExpExecObj\fR executes the regular expression pattern +matcher. It returns 1 if \fIobjPtr\fR contains a range of characters +that match \fIregexp\fR, 0 if no match is found, and \-1 if an error +occurs. In the case of an error, \fBTcl_RegExpExecObj\fR leaves an +error message in the interpreter result. The \fInmatches\fR value +indicates to the matcher how many subexpressions are of interest. If +\fInmatches\fR is 0, then no subexpression match information is +recorded, which may allow the matcher to make various optimizations. +If the value is -1, then all of the subexpressions in the pattern are +remembered. If the value is a positive integer, then only that number +of subexpressions will be remembered. Matching begins at the +specified Unicode character index given by \fIoffset\fR. Unlike +\fBTcl_RegExpExec\fR, the behavior of anchors is not affected by the +offset value. Instead the behavior of the anchors is explicitly +controlled by the \fIeflags\fR argument, which is a bitwise OR of +zero or more of the following flags: +.RS 2 +.TP +\fBTCL_REG_NOTBOL\fR +The starting character will not be treated as the beginning of a +line or the beginning of the string, so `^' will not match there. +Note that this flag has no effect on how `\fB\eA\fR' matches. +.TP +\fBTCL_REG_NOTEOL\fR +The last character in the string will not be treated as the end of a +line or the end of the string, so '$' will not match there. +Note that this flag has no effect on how `\fB\eZ\fR' matches. +.RE +.PP +\fBTcl_RegExpGetInfo\fR retrieves information about the last match +performed with a given regular expression \fIregexp\fR. The +\fIinfoPtr\fR argument contains a pointer to a structure that is +defined as follows: +.PP +.CS +typedef struct Tcl_RegExpInfo { + int \fInsubs\fR; + Tcl_RegExpIndices *\fImatches\fR; + long \fIextendStart\fR; +} Tcl_RegExpInfo; +.CE +.PP +The \fInsubs\fR field contains a count of the number of parenthesized +subexpressions within the regular expression. If the \fBTCL_REG_NOSUB\fR +was used, then this value will be zero. The \fImatches\fR field +points to an array of \fInsubs\fR values that indicate the bounds of each +subexpression matched. The first element in the array refers to the +range matched by the entire regular expression, and subsequent elements +refer to the parenthesized subexpressions in the order that they +appear in the pattern. Each element is a structure that is defined as +follows: +.PP +.CS +typedef struct Tcl_RegExpIndices { + long \fIstart\fR; + long \fIend\fR; +} Tcl_RegExpIndices; +.CE +.PP +The \fIstart\fR and \fIend\fR values are Unicode character indices +relative to the offset location within \fIobjPtr\fR where matching began. +The \fIstart\fR index identifies the first character of the matched +subexpression. The \fIend\fR index identifies the first character +after the matched subexpression. If the subexpression matched the +empty string, then \fIstart\fR and \fIend\fR will be equal. If the +subexpression did not participate in the match, then \fIstart\fR and +\fIend\fR will be set to -1. +.PP +The \fIextendStart\fR field in \fBTcl_RegExpInfo\fR is only set if the +\fBTCL_REG_CANMATCH\fR flag was used. It indicates the first +character in the string where a match could occur. If a match was +found, this will be the same as the beginning of the current match. +If no match was found, then it indicates the earliest point at which a +match might occur if additional text is appended to the string. +.VE 8.1 +.SH "SEE ALSO" +re_syntax(n) +.SH KEYWORDS +match, pattern, regular expression, string, subexpression, Tcl_RegExpIndices, Tcl_RegExpInfo diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/SaveResult.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/SaveResult.3 new file mode 100644 index 0000000000000000000000000000000000000000..b9291a037ea7a8c79f9b4d8a41b8e1a27e967a09 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/SaveResult.3 @@ -0,0 +1,65 @@ +'\" +'\" Copyright (c) 1997 by Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: SaveResult.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_SaveResult 3 8.1 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_SaveResult, Tcl_RestoreResult, Tcl_DiscardResult \- save and restore an interpreter's result +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +\fBTcl_SaveResult(\fIinterp, statePtr\fB)\fR +.sp +\fBTcl_RestoreResult(\fIinterp, statePtr\fB)\fR +.sp +\fBTcl_DiscardResult(\fIstatePtr\fB)\fR +.SH ARGUMENTS +.AS Tcl_SavedResult statePtr +.AP Tcl_Interp *interp in +Interpreter for which state should be saved. +.AP Tcl_SavedResult *statePtr in +Pointer to location where interpreter result should be saved or restored. +.BE + +.SH DESCRIPTION +.PP +These routines allows a C procedure to take a snapshot of the current +interpreter result so that it can be restored after a call +to \fBTcl_Eval\fR or some other routine that modifies the interpreter +result. These routines are passed a pointer to a structure that is +used to store enough information to restore the interpreter result +state. This structure can be allocated on the stack of the calling +procedure. These routines do not save the state of any error +information in the interpreter (e.g. the \fBerrorCode\fR or +\fBerrorInfo\fR variables). +.PP +\fBTcl_SaveResult\fR moves the string and object results +of \fIinterp\fR into the location specified by \fIstatePtr\fR. +\fBTcl_SaveResult\fR clears the result for \fIinterp\fR and +leaves the result in its normal empty initialized state. +.PP +\fBTcl_RestoreResult\fR moves the string and object results from +\fIstatePtr\fR back into \fIinterp\fR. Any result or error that was +already in the interpreter will be cleared. The \fIstatePtr\fR is left +in an uninitialized state and cannot be used until another call to +\fBTcl_SaveResult\fR. +.PP +\fBTcl_DiscardResult\fR releases the saved interpreter state +stored at \fBstatePtr\fR. The state structure is left in an +uninitialized state and cannot be used until another call to +\fBTcl_SaveResult\fR. +.PP +Once \fBTcl_SaveResult\fR is called to save the interpreter +result, either \fBTcl_RestoreResult\fR or +\fBTcl_DiscardResult\fR must be called to properly clean up the +memory associated with the saved state. + +.SH KEYWORDS +result, state, interp diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/SetErrno.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/SetErrno.3 new file mode 100644 index 0000000000000000000000000000000000000000..946d1c6fb091df70db681a0ea773a123de87f5e4 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/SetErrno.3 @@ -0,0 +1,61 @@ +'\" +'\" Copyright (c) 1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: SetErrno.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +.so man.macros +.TH Tcl_SetErrno 3 8.3 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_SetErrno, Tcl_GetErrno, Tcl_ErrnoId, Tcl_ErrnoMsg \- manipulate errno to store and retrieve error codes +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +void +\fBTcl_SetErrno\fR(\fIerrorCode\fR) +.sp +int +\fBTcl_GetErrno\fR() +.sp +char * +\fBTcl_ErrnoId\fR() +.sp +char * +\fBTcl_ErrnoMsg\fR() +.sp +.SH ARGUMENTS +.AS Tcl_Interp *errorCode in +.AP int errorCode in +A POSIX error code such as \fBENOENT\fR. +.BE + +.SH DESCRIPTION +.PP +\fBTcl_SetErrno\fR and \fBTcl_GetErrno\fR provide portable access +to the \fBerrno\fR variable, which is used to record a POSIX error +code after system calls and other operations such as \fBTcl_Gets\fR. +These procedures are necessary because global variable accesses cannot +be made across module boundaries on some platforms. +.PP +\fBTcl_SetErrno\fR sets the \fBerrno\fR variable to the value of the +\fIerrorCode\fR argument +C procedures that wish to return error information to their callers +via \fBerrno\fR should call \fBTcl_SetErrno\fR rather than setting +\fBerrno\fR directly. +.PP +\fBTcl_GetErrno\fR returns the current value of \fBerrno\fR. +Procedures wishing to access \fBerrno\fR should call this procedure +instead of accessing \fBerrno\fR directly. +.PP +\fBTcl_ErrnoId\fR and \fBTcl_ErrnoMsg\fR return a string +representation of the current \fBerrno\fR value. \fBTcl_ErrnoId\fR +returns a machine-readable textual identifier such as +"EACCES". \fBTcl_ErrnoMsg\fR returns a human-readable string such as +"permission denied". The strings returned by these functions are +statically allocated and the caller must not free or modify them. + +.SH KEYWORDS +errno, error code, global variables diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/SetRecLmt.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/SetRecLmt.3 new file mode 100644 index 0000000000000000000000000000000000000000..0b20d909e2ffd78021a8c36cc25fb9ae8a191191 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/SetRecLmt.3 @@ -0,0 +1,55 @@ +'\" +'\" Copyright (c) 1989-1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: SetRecLmt.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_SetRecursionLimit 3 7.0 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_SetRecursionLimit \- set maximum allowable nesting depth in interpreter +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +int +\fBTcl_SetRecursionLimit\fR(\fIinterp, depth\fR) +.SH ARGUMENTS +.AS Tcl_Interp *interp +.AP Tcl_Interp *interp in +Interpreter whose recursion limit is to be set. +Must be greater than zero. +.AP int depth in +New limit for nested calls to \fBTcl_Eval\fR for \fIinterp\fR. +.BE + +.SH DESCRIPTION +.PP +At any given time Tcl enforces a limit on the number of recursive +calls that may be active for \fBTcl_Eval\fR and related procedures +such as \fBTcl_GlobalEval\fR. +Any call to \fBTcl_Eval\fR that exceeds this depth is aborted with +an error. +By default the recursion limit is 1000. +.PP +\fBTcl_SetRecursionLimit\fR may be used to change the maximum +allowable nesting depth for an interpreter. +The \fIdepth\fR argument specifies a new limit for \fIinterp\fR, +and \fBTcl_SetRecursionLimit\fR returns the old limit. +To read out the old limit without modifying it, invoke +\fBTcl_SetRecursionLimit\fR with \fIdepth\fR equal to 0. +.PP +The \fBTcl_SetRecursionLimit\fR only sets the size of the Tcl +call stack: it cannot by itself prevent stack overflows on the +C stack being used by the application. If your machine has a +limit on the size of the C stack, you may get stack overflows +before reaching the limit set by \fBTcl_SetRecursionLimit\fR. +If this happens, see if there is a mechanism in your system for +increasing the maximum size of the C stack. + +.SH KEYWORDS +nesting depth, recursion diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/SetResult.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/SetResult.3 new file mode 100644 index 0000000000000000000000000000000000000000..e1a0ee452d7a71dabb90343a6d2d768094537115 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/SetResult.3 @@ -0,0 +1,225 @@ +'\" +'\" Copyright (c) 1989-1993 The Regents of the University of California. +'\" Copyright (c) 1994-1997 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: SetResult.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_SetResult 3 8.0 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_SetObjResult, Tcl_GetObjResult, Tcl_SetResult, Tcl_GetStringResult, Tcl_AppendResult, Tcl_AppendResultVA, Tcl_AppendElement, Tcl_ResetResult, Tcl_FreeResult \- manipulate Tcl result +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +\fBTcl_SetObjResult\fR(\fIinterp, objPtr\fR) +.sp +Tcl_Obj * +\fBTcl_GetObjResult\fR(\fIinterp\fR) +.sp +\fBTcl_SetResult\fR(\fIinterp, string, freeProc\fR) +.sp +char * +\fBTcl_GetStringResult\fR(\fIinterp\fR) +.sp +\fBTcl_AppendResult\fR(\fIinterp, string, string, ... , \fB(char *) NULL\fR) +.sp +\fBTcl_AppendResultVA\fR(\fIinterp, argList\fR) +.sp +\fBTcl_AppendElement\fR(\fIinterp, string\fR) +.sp +\fBTcl_ResetResult\fR(\fIinterp\fR) +.sp +\fBTcl_FreeResult\fR(\fIinterp\fR) +.SH ARGUMENTS +.AS Tcl_FreeProc freeProc +.AP Tcl_Interp *interp out +Interpreter whose result is to be modified or read. +.AP Tcl_Obj *objPtr in +Object value to become result for \fIinterp\fR. +.AP char *string in +String value to become result for \fIinterp\fR or to be +appended to the existing result. +.AP Tcl_FreeProc *freeProc in +Address of procedure to call to release storage at +\fIstring\fR, or \fBTCL_STATIC\fR, \fBTCL_DYNAMIC\fR, or +\fBTCL_VOLATILE\fR. +.AP va_list argList in +An argument list which must have been initialised using +\fBTCL_VARARGS_START\fR, and cleared using \fBva_end\fR. +.BE + +.SH DESCRIPTION +.PP +The procedures described here are utilities for manipulating the +result value in a Tcl interpreter. +The interpreter result may be either a Tcl object or a string. +For example, \fBTcl_SetObjResult\fR and \fBTcl_SetResult\fR +set the interpreter result to, respectively, an object and a string. +Similarly, \fBTcl_GetObjResult\fR and \fBTcl_GetStringResult\fR +return the interpreter result as an object and as a string. +The procedures always keep the string and object forms +of the interpreter result consistent. +For example, if \fBTcl_SetObjResult\fR is called to set +the result to an object, +then \fBTcl_GetStringResult\fR is called, +it will return the object's string value. +.PP +\fBTcl_SetObjResult\fR +arranges for \fIobjPtr\fR to be the result for \fIinterp\fR, +replacing any existing result. +The result is left pointing to the object +referenced by \fIobjPtr\fR. +\fIobjPtr\fR's reference count is incremented +since there is now a new reference to it from \fIinterp\fR. +The reference count for any old result object +is decremented and the old result object is freed if no +references to it remain. +.PP +\fBTcl_GetObjResult\fR returns the result for \fIinterp\fR as an object. +The object's reference count is not incremented; +if the caller needs to retain a long-term pointer to the object +they should use \fBTcl_IncrRefCount\fR to increment its reference count +in order to keep it from being freed too early or accidently changed. +.PP +\fBTcl_SetResult\fR +arranges for \fIstring\fR to be the result for the current Tcl +command in \fIinterp\fR, replacing any existing result. +The \fIfreeProc\fR argument specifies how to manage the storage +for the \fIstring\fR argument; +it is discussed in the section +\fBTHE TCL_FREEPROC ARGUMENT TO TCL_SETRESULT\fR below. +If \fIstring\fR is \fBNULL\fR, then \fIfreeProc\fR is ignored +and \fBTcl_SetResult\fR +re-initializes \fIinterp\fR's result to point to an empty string. +.PP +\fBTcl_GetStringResult\fR returns the result for \fIinterp\fR as an string. +If the result was set to an object by a \fBTcl_SetObjResult\fR call, +the object form will be converted to a string and returned. +If the object's string representation contains null bytes, +this conversion will lose information. +For this reason, programmers are encouraged to +write their code to use the new object API procedures +and to call \fBTcl_GetObjResult\fR instead. +.PP +\fBTcl_ResetResult\fR clears the result for \fIinterp\fR +and leaves the result in its normal empty initialized state. +If the result is an object, +its reference count is decremented and the result is left +pointing to an unshared object representing an empty string. +If the result is a dynamically allocated string, its memory is free*d +and the result is left as a empty string. +\fBTcl_ResetResult\fR also clears the error state managed by +\fBTcl_AddErrorInfo\fR, \fBTcl_AddObjErrorInfo\fR, +and \fBTcl_SetErrorCode\fR. + +.SH "OLD STRING PROCEDURES" +.PP +Use of the following procedures is deprecated +since they manipulate the Tcl result as a string. +Procedures such as \fBTcl_SetObjResult\fR +that manipulate the result as an object +can be significantly more efficient. +.PP +\fBTcl_AppendResult\fR makes it easy to build up Tcl results in pieces. +It takes each of its \fIstring\fR arguments and appends them in order +to the current result associated with \fIinterp\fR. +If the result is in its initialized empty state (e.g. a command procedure +was just invoked or \fBTcl_ResetResult\fR was just called), +then \fBTcl_AppendResult\fR sets the result to the concatenation of +its \fIstring\fR arguments. +\fBTcl_AppendResult\fR may be called repeatedly as additional pieces +of the result are produced. +\fBTcl_AppendResult\fR takes care of all the +storage management issues associated with managing \fIinterp\fR's +result, such as allocating a larger result area if necessary. +It also converts the current interpreter result from an object +to a string, if necessary, before appending the argument strings. +Any number of \fIstring\fR arguments may be passed in a single +call; the last argument in the list must be a NULL pointer. +.PP +\fBTcl_AppendResultVA\fR is the same as \fBTcl_AppendResult\fR except that +instead of taking a variable number of arguments it takes an argument list. +.PP +\fBTcl_AppendElement\fR is similar to \fBTcl_AppendResult\fR in +that it allows results to be built up in pieces. +However, \fBTcl_AppendElement\fR takes only a single \fIstring\fR +argument and it appends that argument to the current result +as a proper Tcl list element. +\fBTcl_AppendElement\fR adds backslashes or braces if necessary +to ensure that \fIinterp\fR's result can be parsed as a list and that +\fIstring\fR will be extracted as a single element. +Under normal conditions, \fBTcl_AppendElement\fR will add a space +character to \fIinterp\fR's result just before adding the new +list element, so that the list elements in the result are properly +separated. +However if the new list element is the first in a list or sub-list +(i.e. \fIinterp\fR's current result is empty, or consists of the +single character ``{'', or ends in the characters `` {'') then no +space is added. +.PP +\fBTcl_FreeResult\fR performs part of the work +of \fBTcl_ResetResult\fR. +It frees up the memory associated with \fIinterp\fR's result. +It also sets \fIinterp->freeProc\fR to zero, but doesn't +change \fIinterp->result\fR or clear error state. +\fBTcl_FreeResult\fR is most commonly used when a procedure +is about to replace one result value with another. + +.SH "DIRECT ACCESS TO INTERP->RESULT IS DEPRECATED" +.PP +It used to be legal for programs to +directly read and write \fIinterp->result\fR +to manipulate the interpreter result. +Direct access to \fIinterp->result\fR is now strongly deprecated +because it can make the result's string and object forms inconsistent. +Programs should always read the result +using the procedures \fBTcl_GetObjResult\fR or \fBTcl_GetStringResult\fR, +and write the result using \fBTcl_SetObjResult\fR or \fBTcl_SetResult\fR. + +.SH "THE TCL_FREEPROC ARGUMENT TO TCL_SETRESULT" +.PP +\fBTcl_SetResult\fR's \fIfreeProc\fR argument specifies how +the Tcl system is to manage the storage for the \fIstring\fR argument. +If \fBTcl_SetResult\fR or \fBTcl_SetObjResult\fR are called +at a time when \fIinterp\fR holds a string result, +they do whatever is necessary to dispose of the old string result +(see the \fBTcl_Interp\fR manual entry for details on this). +.PP +If \fIfreeProc\fR is \fBTCL_STATIC\fR it means that \fIstring\fR +refers to an area of static storage that is guaranteed not to be +modified until at least the next call to \fBTcl_Eval\fR. +If \fIfreeProc\fR +is \fBTCL_DYNAMIC\fR it means that \fIstring\fR was allocated with a call +to \fBTcl_Alloc\fR and is now the property of the Tcl system. +\fBTcl_SetResult\fR will arrange for the string's storage to be +released by calling \fBTcl_Free\fR when it is no longer needed. +If \fIfreeProc\fR is \fBTCL_VOLATILE\fR it means that \fIstring\fR +points to an area of memory that is likely to be overwritten when +\fBTcl_SetResult\fR returns (e.g. it points to something in a stack frame). +In this case \fBTcl_SetResult\fR will make a copy of the string in +dynamically allocated storage and arrange for the copy to be the +result for the current Tcl command. +.PP +If \fIfreeProc\fR isn't one of the values \fBTCL_STATIC\fR, +\fBTCL_DYNAMIC\fR, and \fBTCL_VOLATILE\fR, then it is the address +of a procedure that Tcl should call to free the string. +This allows applications to use non-standard storage allocators. +When Tcl no longer needs the storage for the string, it will +call \fIfreeProc\fR. \fIFreeProc\fR should have arguments and +result that match the type \fBTcl_FreeProc\fR: +.CS +typedef void Tcl_FreeProc(char *\fIblockPtr\fR); +.CE +When \fIfreeProc\fR is called, its \fIblockPtr\fR will be set to +the value of \fIstring\fR passed to \fBTcl_SetResult\fR. + +.SH "SEE ALSO" +Tcl_AddErrorInfo, Tcl_CreateObjCommand, Tcl_SetErrorCode, Tcl_Interp + +.SH KEYWORDS +append, command, element, list, object, result, return value, interpreter diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/SetVar.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/SetVar.3 new file mode 100644 index 0000000000000000000000000000000000000000..2253fc56b0932e7b0fcf8a31f26b64300a48f595 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/SetVar.3 @@ -0,0 +1,261 @@ +'\" +'\" Copyright (c) 1989-1993 The Regents of the University of California. +'\" Copyright (c) 1994-1997 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: SetVar.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_SetVar 3 8.1 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_SetVar2Ex, Tcl_SetVar, Tcl_SetVar2, Tcl_ObjSetVar2, Tcl_GetVar2Ex, Tcl_GetVar, Tcl_GetVar2, Tcl_ObjGetVar2, Tcl_UnsetVar, Tcl_UnsetVar2 \- manipulate Tcl variables +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +.VS 8.1 +Tcl_Obj * +\fBTcl_SetVar2Ex\fR(\fIinterp, name1, name2, newValuePtr, flags\fR) +.VE +.sp +char * +\fBTcl_SetVar\fR(\fIinterp, varName, newValue, flags\fR) +.sp +char * +\fBTcl_SetVar2\fR(\fIinterp, name1, name2, newValue, flags\fR) +.sp +Tcl_Obj * +\fBTcl_ObjSetVar2\fR(\fIinterp, part1Ptr, part2Ptr, newValuePtr, flags\fR) +.sp +.VS 8.1 +Tcl_Obj * +\fBTcl_GetVar2Ex\fR(\fIinterp, name1, name2, flags\fR) +.VE +.sp +char * +\fBTcl_GetVar\fR(\fIinterp, varName, flags\fR) +.sp +char * +\fBTcl_GetVar2\fR(\fIinterp, name1, name2, flags\fR) +.sp +Tcl_Obj * +\fBTcl_ObjGetVar2\fR(\fIinterp, part1Ptr, part2Ptr, flags\fR) +.sp +int +\fBTcl_UnsetVar\fR(\fIinterp, varName, flags\fR) +.sp +int +\fBTcl_UnsetVar2\fR(\fIinterp, name1, name2, flags\fR) +.SH ARGUMENTS +.AS Tcl_Interp *newValuePtr +.AP Tcl_Interp *interp in +Interpreter containing variable. +.AP char *name1 in +Contains the name of an array variable (if \fIname2\fR is non-NULL) +or (if \fIname2\fR is NULL) either the name of a scalar variable +or a complete name including both variable name and index. +May include \fB::\fR namespace qualifiers +to specify a variable in a particular namespace. +.AP char *name2 in +If non-NULL, gives name of element within array; in this +case \fIname1\fR must refer to an array variable. +.AP Tcl_Obj *newValuePtr in +.VS 8.1 +Points to a Tcl object containing the new value for the variable. +.VE +.AP int flags in +OR-ed combination of bits providing additional information. See below +for valid values. +.AP char *varName in +Name of variable. +May include \fB::\fR namespace qualifiers +to specify a variable in a particular namespace. +May refer to a scalar variable or an element of +an array. +If the name references an element of an array, then the name +must be in writable memory: Tcl will make temporary modifications +to it while looking up the name. +.AP char *newValue in +New value for variable, specified as a NULL-terminated string. +A copy of this value is stored in the variable. +.AP Tcl_Obj *part1Ptr in +Points to a Tcl object containing the variable's name. +The name may include a series of \fB::\fR namespace qualifiers +to specify a variable in a particular namespace. +May refer to a scalar variable or an element of an array variable. +.AP Tcl_Obj *part2Ptr in +If non-NULL, points to an object containing the name of an element +within an array and \fIpart1Ptr\fR must refer to an array variable. +.BE + +.SH DESCRIPTION +.PP +These procedures are used to create, modify, read, and delete +Tcl variables from C code. +.PP +.VS 8.1 +\fBTcl_SetVar2Ex\fR, \fBTcl_SetVar\fR, \fBTcl_SetVar2\fR, and +\fBTcl_ObjSetVar2\fR +will create a new variable or modify an existing one. +These procedures set the given variable to the value +given by \fInewValuePtr\fR or \fInewValue\fR and return a +pointer to the variable's new value, which is stored in Tcl's +variable structure. +\fBTcl_SetVar2Ex\fR and \fBTcl_ObjSetVar2\fR take the new value as a +Tcl_Obj and return +a pointer to a Tcl_Obj. \fBTcl_SetVar\fR and \fBTcl_SetVar2\fR +take the new value as a string and return a string; they are +usually less efficient than \fBTcl_ObjSetVar2\fR. Note that the +return value may be different than the \fInewValuePtr\fR or +.VE +\fInewValue\fR argument, due to modifications made by write traces. +If an error occurs in setting the variable (e.g. an array +variable is referenced without giving an index into the array) +NULL is returned and an error message is left in \fIinterp\fR's +result if the \fBTCL_LEAVE_ERR_MSG\fR \fIflag\fR bit is set. +.PP +.VS 8.1 +\fBTcl_GetVar2Ex\fR, \fBTcl_GetVar\fR, \fBTcl_GetVar2\fR, and +\fBTcl_ObjGetVar2\fR +return the current value of a variable. +The arguments to these procedures are treated in the same way +as the arguments to the procedures described above. +Under normal circumstances, the return value is a pointer +to the variable's value. For \fBTcl_GetVar2Ex\fR and +\fBTcl_ObjGetVar2\fR the value is +returned as a pointer to a Tcl_Obj. For \fBTcl_GetVar\fR and +\fBTcl_GetVar2\fR the value is returned as a string; this is +usually less efficient, so \fBTcl_GetVar2Ex\fR or \fBTcl_ObjGetVar2\fR +are preferred. +.VE +If an error occurs while reading the variable (e.g. the variable +doesn't exist or an array element is specified for a scalar +variable), then NULL is returned and an error message is left +in \fIinterp\fR's result if the \fBTCL_LEAVE_ERR_MSG\fR \fIflag\fR +bit is set. +.PP +\fBTcl_UnsetVar\fR and \fBTcl_UnsetVar2\fR may be used to remove +a variable, so that future attempts to read the variable will return +an error. +The arguments to these procedures are treated in the same way +as the arguments to the procedures above. +If the variable is successfully removed then TCL_OK is returned. +If the variable cannot be removed because it doesn't exist then +TCL_ERROR is returned and an error message is left +in \fIinterp\fR's result if the \fBTCL_LEAVE_ERR_MSG\fR \fIflag\fR +bit is set. +If an array element is specified, the given element is removed +but the array remains. +If an array name is specified without an index, then the entire +array is removed. +.PP +The name of a variable may be specified to these procedures in +four ways: +.IP [1] +If \fBTcl_SetVar\fR, \fBTcl_GetVar\fR, or \fBTcl_UnsetVar\fR +is invoked, the variable name is given as +a single string, \fIvarName\fR. +If \fIvarName\fR contains an open parenthesis and ends with a +close parenthesis, then the value between the parentheses is +treated as an index (which can have any string value) and +the characters before the first open +parenthesis are treated as the name of an array variable. +If \fIvarName\fR doesn't have parentheses as described above, then +the entire string is treated as the name of a scalar variable. +.IP [2] +If the \fIname1\fR and \fIname2\fR arguments are provided and +\fIname2\fR is non-NULL, then an array element is specified and +the array name and index have +already been separated by the caller: \fIname1\fR contains the +name and \fIname2\fR contains the index. +.VS 8.1 +An error is generated +if \fIname1\fR contains an open parenthesis and ends with a +close parenthesis (array element) and \fIname2\fR is non-NULL. +.IP [3] +If \fIname2\fR is NULL, \fIname1\fR is treated just like +\fIvarName\fR in case [1] above (it can be either a scalar or an array +element variable name). +.VE +.PP +The \fIflags\fR argument may be used to specify any of several +options to the procedures. +It consists of an OR-ed combination of the following bits. +.TP +\fBTCL_GLOBAL_ONLY\fR +Under normal circumstances the procedures look up variables as follows. +If a procedure call is active in \fIinterp\fR, +the variable is looked up at the current level of procedure call. +Otherwise, the variable is looked up first in the current namespace, +then in the global namespace. +However, if this bit is set in \fIflags\fR then the variable +is looked up only in the global namespace +even if there is a procedure call active. +If both \fBTCL_GLOBAL_ONLY\fR and \fBTCL_NAMESPACE_ONLY\fR are given, +\fBTCL_GLOBAL_ONLY\fR is ignored. +.TP +\fBTCL_NAMESPACE_ONLY\fR +If this bit is set in \fIflags\fR then the variable +is looked up only in the current namespace; if a procedure is active +its variables are ignored, and the global namespace is also ignored unless +it is the current namespace. +.TP +\fBTCL_LEAVE_ERR_MSG\fR +If an error is returned and this bit is set in \fIflags\fR, then +an error message will be left in the interpreter's result, +where it can be retrieved with \fBTcl_GetObjResult\fR +or \fBTcl_GetStringResult\fR. +If this flag bit isn't set then no error message is left +and the interpreter's result will not be modified. +.TP +\fBTCL_APPEND_VALUE\fR +If this bit is set then \fInewValuePtr\fR or \fInewValue\fR is +appended to the current value instead of replacing it. +If the variable is currently undefined, then the bit is ignored. +This bit is only used by the \fBTcl_Set*\fR procedures. +.TP +\fBTCL_LIST_ELEMENT\fR +If this bit is set, then \fInewValue\fR is converted to a valid +Tcl list element before setting (or appending to) the variable. +A separator space is appended before the new list element unless +the list element is going to be the first element in a list or +sublist (i.e. the variable's current value is empty, or contains +the single character ``{'', or ends in `` }''). +.PP +\fBTcl_GetVar\fR and \fBTcl_GetVar2\fR +return the current value of a variable. +The arguments to these procedures are treated in the same way +as the arguments to \fBTcl_SetVar\fR and \fBTcl_SetVar2\fR. +Under normal circumstances, the return value is a pointer +to the variable's value (which is stored in Tcl's variable +structure and will not change before the next call to \fBTcl_SetVar\fR +or \fBTcl_SetVar2\fR). +\fBTcl_GetVar\fR and \fBTcl_GetVar2\fR use the flag bits TCL_GLOBAL_ONLY +and TCL_LEAVE_ERR_MSG, both of +which have +the same meaning as for \fBTcl_SetVar\fR. +If an error occurs in reading the variable (e.g. the variable +doesn't exist or an array element is specified for a scalar +variable), then NULL is returned. +.PP +\fBTcl_UnsetVar\fR and \fBTcl_UnsetVar2\fR may be used to remove +a variable, so that future calls to \fBTcl_GetVar\fR or \fBTcl_GetVar2\fR +for the variable will return an error. +The arguments to these procedures are treated in the same way +as the arguments to \fBTcl_GetVar\fR and \fBTcl_GetVar2\fR. +If the variable is successfully removed then TCL_OK is returned. +If the variable cannot be removed because it doesn't exist then +TCL_ERROR is returned. +If an array element is specified, the given element is removed +but the array remains. +If an array name is specified without an index, then the entire +array is removed. + +.SH "SEE ALSO" +Tcl_GetObjResult, Tcl_GetStringResult, Tcl_TraceVar + +.SH KEYWORDS +array, get variable, interpreter, object, scalar, set, unset, variable diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Sleep.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Sleep.3 new file mode 100644 index 0000000000000000000000000000000000000000..48ea6adb45804b394fafd483848cf9d1dac68611 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Sleep.3 @@ -0,0 +1,37 @@ +'\" +'\" Copyright (c) 1990 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: Sleep.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_Sleep 3 7.5 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_Sleep \- delay execution for a given number of milliseconds +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +\fBTcl_Sleep\fR(\fIms\fR) +.SH ARGUMENTS +.AP int ms in +Number of milliseconds to sleep. +.BE + +.SH DESCRIPTION +.PP +This procedure delays the calling process by the number of +milliseconds given by the \fIms\fR parameter and returns +after that time has elapsed. It is typically used for things +like flashing a button, where the delay is short and the +application needn't do anything while it waits. For longer +delays where the application needs to respond to other events +during the delay, the procedure \fBTcl_CreateTimerHandler\fR +should be used instead of \fBTcl_Sleep\fR. + +.SH KEYWORDS +sleep, time, wait diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/SourceRCFile.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/SourceRCFile.3 new file mode 100644 index 0000000000000000000000000000000000000000..9c6e374a370074683ddd81152ae10c678ee56aa3 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/SourceRCFile.3 @@ -0,0 +1,38 @@ +'\" +'\" Copyright (c) 1998-2000 by Scriptics Corporation. +'\" All rights reserved. +'\" +'\" RCS: @(#) $Id: SourceRCFile.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +'\" +.so man.macros +.TH Tcl_SourceRCFile 3 8.3 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_SourceRCFile \- source the Tcl rc file +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +void +\fBTcl_SourceRCFile\fR(\fIinterp\fR) +.SH ARGUMENTS +.AP Tcl_Interp *interp in +Tcl interpreter to source rc file into. +.BE + +.SH DESCRIPTION +.PP +\fBTcl_SourceRCFile\fR is used to source the Tcl rc file at startup. +It is typically invoked by Tcl_Main or Tk_Main. The name of the file +sourced is obtained from the global variable \fBtcl_rcFileName\fR in +the interpreter given by \fIinterp\fR. If this variable is not +defined, or if the file it indicates cannot be found, no action is +taken. +.PP +On the Macintosh, after sourcing the rc file, this function will +additionally source the TEXT resource indicated by the global variable +\fBtcl_rcRsrcName\fR in \fIinterp\fR. + +.SH KEYWORDS +application-specific initialization, main program, rc file diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/SplitList.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/SplitList.3 new file mode 100644 index 0000000000000000000000000000000000000000..45488f1dea68544b02eb9f8658f5a297c15bb66b --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/SplitList.3 @@ -0,0 +1,175 @@ +'\" +'\" Copyright (c) 1989-1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: SplitList.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_SplitList 3 8.0 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_SplitList, Tcl_Merge, Tcl_ScanElement, Tcl_ConvertElement, Tcl_ScanCountedElement, Tcl_ConvertCountedElement \- manipulate Tcl lists +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +int +\fBTcl_SplitList\fR(\fIinterp, list, argcPtr, argvPtr\fR) +.sp +char * +\fBTcl_Merge\fR(\fIargc, argv\fR) +.sp +int +\fBTcl_ScanElement\fR(\fIsrc, flagsPtr\fR) +.sp +int +\fBTcl_ScanCountedElement\fR(\fIsrc, length, flagsPtr\fR) +.sp +int +\fBTcl_ConvertElement\fR(\fIsrc, dst, flags\fR) +.sp +int +\fBTcl_ConvertCountedElement\fR(\fIsrc, length, dst, flags\fR) +.SH ARGUMENTS +.AS Tcl_Interp ***argvPtr +.AP Tcl_Interp *interp out +Interpreter to use for error reporting. If NULL, then no error message +is left. +.AP char *list in +Pointer to a string with proper list structure. +.AP int *argcPtr out +Filled in with number of elements in \fIlist\fR. +.AP char ***argvPtr out +\fI*argvPtr\fR will be filled in with the address of an array of +pointers to the strings that are the extracted elements of \fIlist\fR. +There will be \fI*argcPtr\fR valid entries in the array, followed by +a NULL entry. +.AP int argc in +Number of elements in \fIargv\fR. +.AP char **argv in +Array of strings to merge together into a single list. +Each string will become a separate element of the list. +.AP char *src in +String that is to become an element of a list. +.AP int *flagsPtr in +Pointer to word to fill in with information about \fIsrc\fR. +The value of *\fIflagsPtr\fR must be passed to \fBTcl_ConvertElement\fR. +.AP int length in +Number of bytes in string \fIsrc\fR. +.AP char *dst in +Place to copy converted list element. Must contain enough characters +to hold converted string. +.AP int flags in +Information about \fIsrc\fR. Must be value returned by previous +call to \fBTcl_ScanElement\fR, possibly OR-ed +with \fBTCL_DONT_USE_BRACES\fR. +.BE + +.SH DESCRIPTION +.PP +These procedures may be used to disassemble and reassemble Tcl lists. +\fBTcl_SplitList\fR breaks a list up into its constituent elements, +returning an array of pointers to the elements using +\fIargcPtr\fR and \fIargvPtr\fR. +While extracting the arguments, \fBTcl_SplitList\fR obeys the usual +rules for backslash substitutions and braces. The area of +memory pointed to by \fI*argvPtr\fR is dynamically allocated; in +addition to the array of pointers, it +also holds copies of all the list elements. It is the caller's +responsibility to free up all of this storage. +For example, suppose that you have called \fBTcl_SplitList\fR with +the following code: +.CS +int argc, code; +char *string; +char **argv; +\&... +code = Tcl_SplitList(interp, string, &argc, &argv); +.CE +Then you should eventually free the storage with a call like the +following: +.CS +Tcl_Free((char *) argv); +.CE +.PP +\fBTcl_SplitList\fR normally returns \fBTCL_OK\fR, which means the list was +successfully parsed. +If there was a syntax error in \fIlist\fR, then \fBTCL_ERROR\fR is returned +and the interpreter's result will point to an error message describing the +problem (if \fIinterp\fR was not NULL). +If \fBTCL_ERROR\fR is returned then no memory is allocated and \fI*argvPtr\fR +is not modified. +.PP +\fBTcl_Merge\fR is the inverse of \fBTcl_SplitList\fR: it +takes a collection of strings given by \fIargc\fR +and \fIargv\fR and generates a result string +that has proper list structure. +This means that commands like \fBindex\fR may be used to +extract the original elements again. +In addition, if the result of \fBTcl_Merge\fR is passed to \fBTcl_Eval\fR, +it will be parsed into \fIargc\fR words whose values will +be the same as the \fIargv\fR strings passed to \fBTcl_Merge\fR. +\fBTcl_Merge\fR will modify the list elements with braces and/or +backslashes in order to produce proper Tcl list structure. +The result string is dynamically allocated +using \fBTcl_Alloc\fR; the caller must eventually release the space +using \fBTcl_Free\fR. +.PP +If the result of \fBTcl_Merge\fR is passed to \fBTcl_SplitList\fR, +the elements returned by \fBTcl_SplitList\fR will be identical to +those passed into \fBTcl_Merge\fR. +However, the converse is not true: if \fBTcl_SplitList\fR +is passed a given string, and the resulting \fIargc\fR and +\fIargv\fR are passed to \fBTcl_Merge\fR, the resulting string +may not be the same as the original string passed to \fBTcl_SplitList\fR. +This is because \fBTcl_Merge\fR may use backslashes and braces +differently than the original string. +.PP +\fBTcl_ScanElement\fR and \fBTcl_ConvertElement\fR are the +procedures that do all of the real work of \fBTcl_Merge\fR. +\fBTcl_ScanElement\fR scans its \fIsrc\fR argument +and determines how to use backslashes and braces +when converting it to a list element. +It returns an overestimate of the number of characters +required to represent \fIsrc\fR as a list element, and +it stores information in \fI*flagsPtr\fR that is needed +by \fBTcl_ConvertElement\fR. +.PP +\fBTcl_ConvertElement\fR is a companion procedure to \fBTcl_ScanElement\fR. +It does the actual work of converting a string to a list element. +Its \fIflags\fR argument must be the same as the value returned +by \fBTcl_ScanElement\fR. +\fBTcl_ConvertElement\fR writes a proper list element to memory +starting at *\fIdst\fR and returns a count of the total number +of characters written, which will be no more than the result +returned by \fBTcl_ScanElement\fR. +\fBTcl_ConvertElement\fR writes out only the actual list element +without any leading or trailing spaces: it is up to the caller to +include spaces between adjacent list elements. +.PP +\fBTcl_ConvertElement\fR uses one of two different approaches to +handle the special characters in \fIsrc\fR. Wherever possible, it +handles special characters by surrounding the string with braces. +This produces clean-looking output, but can't be used in some situations, +such as when \fIsrc\fR contains unmatched braces. +In these situations, \fBTcl_ConvertElement\fR handles special +characters by generating backslash sequences for them. +The caller may insist on the second approach by OR-ing the +flag value returned by \fBTcl_ScanElement\fR with +\fBTCL_DONT_USE_BRACES\fR. +Although this will produce an uglier result, it is useful in some +special situations, such as when \fBTcl_ConvertElement\fR is being +used to generate a portion of an argument for a Tcl command. +In this case, surrounding \fIsrc\fR with curly braces would cause +the command not to be parsed correctly. +.PP +\fBTcl_ScanCountedElement\fR and \fBTcl_ConvertCountedElement\fR are +the same as \fBTcl_ScanElement\fR and \fBTcl_ConvertElement\fR, except +the length of string \fIsrc\fR is specified by the \fIlength\fR +argument, and the string may contain embedded nulls. + +.SH KEYWORDS +backslash, convert, element, list, merge, split, strings diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/SplitPath.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/SplitPath.3 new file mode 100644 index 0000000000000000000000000000000000000000..e14e7bcd493bb63862c549a05820ca383ccd1f27 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/SplitPath.3 @@ -0,0 +1,93 @@ +'\" +'\" Copyright (c) 1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: SplitPath.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_SplitPath 3 7.5 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_SplitPath, Tcl_JoinPath, Tcl_GetPathType \- manipulate platform-dependent file paths +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +\fBTcl_SplitPath\fR(\fIpath, argcPtr, argvPtr\fR) +.sp +char * +\fBTcl_JoinPath\fR(\fIargc, argv, resultPtr\fR) +.sp +Tcl_PathType +\fBTcl_GetPathType\fR(\fIpath\fR) +.SH ARGUMENTS +.AS Tcl_DString ***argvPtr +.AP char *path in +File path in a form appropriate for the current platform (see the +\fBfilename\fR manual entry for acceptable forms for path names). +.AP int *argcPtr out +Filled in with number of path elements in \fIpath\fR. +.AP char ***argvPtr out +\fI*argvPtr\fR will be filled in with the address of an array of +pointers to the strings that are the extracted elements of \fIpath\fR. +There will be \fI*argcPtr\fR valid entries in the array, followed by +a NULL entry. +.AP int argc in +Number of elements in \fIargv\fR. +.AP char **argv in +Array of path elements to merge together into a single path. +.AP Tcl_DString *resultPtr in/out +A pointer to an initialized \fBTcl_DString\fR to which the result of +\fBTcl_JoinPath\fR will be appended. +.BE + +.SH DESCRIPTION +.PP +These procedures may be used to disassemble and reassemble file +paths in a platform independent manner: they provide C-level access to +the same functionality as the \fBfile split\fR, \fBfile join\fR, and +\fBfile pathtype\fR commands. +.PP +\fBTcl_SplitPath\fR breaks a path into its constituent elements, +returning an array of pointers to the elements using \fIargcPtr\fR and +\fIargvPtr\fR. The area of memory pointed to by \fI*argvPtr\fR is +dynamically allocated; in addition to the array of pointers, it also +holds copies of all the path elements. It is the caller's +responsibility to free all of this storage. +For example, suppose that you have called \fBTcl_SplitPath\fR with the +following code: +.CS +int argc; +char *path; +char **argv; +\&... +Tcl_SplitPath(string, &argc, &argv); +.CE +Then you should eventually free the storage with a call like the +following: +.CS +Tcl_Free((char *) argv); +.CE +.PP +\fBTcl_JoinPath\fR is the inverse of \fBTcl_SplitPath\fR: it takes a +collection of path elements given by \fIargc\fR and \fIargv\fR and +generates a result string that is a properly constructed path. The +result string is appended to \fIresultPtr\fR. \fIResultPtr\fR must +refer to an initialized \fBTcl_DString\fR. +.PP +If the result of \fBTcl_SplitPath\fR is passed to \fBTcl_JoinPath\fR, +the result will refer to the same location, but may not be in the same +form. This is because \fBTcl_SplitPath\fR and \fBTcl_JoinPath\fR +eliminate duplicate path separators and return a normalized form for +each platform. +.PP +\fBTcl_GetPathType\fR returns the type of the specified \fIpath\fR, +where \fBTcl_PathType\fR is one of \fBTCL_PATH_ABSOLUTE\fR, +\fBTCL_PATH_RELATIVE\fR, or \fBTCL_PATH_VOLUME_RELATIVE\fR. See the +\fBfilename\fR manual entry for a description of the path types for +each platform. + +.SH KEYWORDS +file, filename, join, path, split, type diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/StaticPkg.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/StaticPkg.3 new file mode 100644 index 0000000000000000000000000000000000000000..8e45f9c08d0b267596683f25856556aae8ce2740 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/StaticPkg.3 @@ -0,0 +1,69 @@ +'\" +'\" Copyright (c) 1995-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: StaticPkg.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_StaticPackage 3 7.5 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_StaticPackage \- make a statically linked package available via the \fBload\fR command +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +\fBTcl_StaticPackage\fR(\fIinterp, pkgName, initProc, safeInitProc\fR) +.SH ARGUMENTS +.AS Tcl_PackageInitProc *safeInitProc +.AP Tcl_Interp *interp in +If not NULL, points to an interpreter into which the package has +already been loaded (i.e., the caller has already invoked the +appropriate initialization procedure). NULL means the package +hasn't yet been incorporated into any interpreter. +.AP char *pkgName in +Name of the package; should be properly capitalized (first letter +upper-case, all others lower-case). +.AP Tcl_PackageInitProc *initProc in +Procedure to invoke to incorporate this package into a trusted +interpreter. +.AP Tcl_PackageInitProc *safeInitProc in +Procedure to call to incorporate this package into a safe interpreter +(one that will execute untrusted scripts). NULL means the package +can't be used in safe interpreters. +.BE + +.SH DESCRIPTION +.PP +This procedure may be invoked to announce that a package has been +linked statically with a Tcl application and, optionally, that it +has already been loaded into an interpreter. +Once \fBTcl_StaticPackage\fR has been invoked for a package, it +may be loaded into interpreters using the \fBload\fR command. +\fBTcl_StaticPackage\fR is normally invoked only by the \fBTcl_AppInit\fR +procedure for the application, not by packages for themselves +(\fBTcl_StaticPackage\fR should only be invoked for statically +loaded packages, and code in the package itself should not need +to know whether the package is dynamically or statically loaded). +.PP +When the \fBload\fR command is used later to load the package into +an interpreter, one of \fIinitProc\fR and \fIsafeInitProc\fR will +be invoked, depending on whether the target interpreter is safe +or not. +\fIinitProc\fR and \fIsafeInitProc\fR must both match the +following prototype: +.CS +typedef int Tcl_PackageInitProc(Tcl_Interp *\fIinterp\fR); +.CE +The \fIinterp\fR argument identifies the interpreter in which the package +is to be loaded. The initialization procedure must return \fBTCL_OK\fR or +\fBTCL_ERROR\fR to indicate whether or not it completed successfully; in +the event of an error it should set the interpreter's result to point to an +error message. The result or error from the initialization procedure will +be returned as the result of the \fBload\fR command that caused the +initialization procedure to be invoked. + +.SH KEYWORDS +initialization procedure, package, static linking diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/StrMatch.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/StrMatch.3 new file mode 100644 index 0000000000000000000000000000000000000000..a53d8d6854cbb2b5174134d02b9bae3b2c1e80d0 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/StrMatch.3 @@ -0,0 +1,52 @@ +'\" +'\" Copyright (c) 1989-1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: StrMatch.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_StringMatch 3 8.1 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_StringMatch, Tcl_StringCaseMatch \- test whether a string matches a pattern +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +int +\fBTcl_StringMatch\fR(\fIstring\fR, \fIpattern\fR) +.sp +int +\fBTcl_StringCaseMatch\fR(\fIstring\fR, \fIpattern\fR, \fInocase\fR) +.SH ARGUMENTS +.AP char *string in +String to test. +.AP char *pattern in +Pattern to match against string. May contain special +characters from the set *?\e[]. +.AP int nocase in +Specifies whether the match should be done case-sensitive (0) or +case-insensitive (1). +.BE + +.SH DESCRIPTION +.PP +This utility procedure determines whether a string matches +a given pattern. If it does, then \fBTcl_StringMatch\fR returns +1. Otherwise \fBTcl_StringMatch\fR returns 0. The algorithm +used for matching is the same algorithm used in the ``string match'' +Tcl command and is similar to the algorithm used by the C-shell +for file name matching; see the Tcl manual entry for details. +.VS 8.1 +.PP +In \fBTcl_StringCaseMatch\fR, the algorithm is the same, but you have +the option to make the matching case-insensitive. If you choose this +(by passing \fBnocase\fR as 1), then the string and pattern are +essentially matched in the lower case. +.VE 8.1 + +.SH KEYWORDS +match, pattern, string diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/StringObj.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/StringObj.3 new file mode 100644 index 0000000000000000000000000000000000000000..6797d8f79ca095b4b1de58516b29463b2737d56a --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/StringObj.3 @@ -0,0 +1,246 @@ +'\" +'\" Copyright (c) 1994-1997 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: StringObj.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_StringObj 3 8.1 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_NewStringObj, Tcl_NewUnicodeObj, Tcl_SetStringObj, Tcl_SetUnicodeObj, Tcl_GetStringFromObj, Tcl_GetString, Tcl_GetUnicode, Tcl_GetUniChar, Tcl_GetCharLength, Tcl_GetRange, Tcl_AppendToObj, Tcl_AppendUnicodeToObj, Tcl_AppendStringsToObj, Tcl_AppendStringsToObjVA, Tcl_AppendObjToObj, Tcl_SetObjLength, Tcl_ConcatObj \- manipulate Tcl objects as strings +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +Tcl_Obj * +\fBTcl_NewStringObj\fR(\fIbytes, length\fR) +.VS 8.1.2 +.sp +Tcl_Obj * +\fBTcl_NewUnicodeObj\fR(\fIunicode, numChars\fR) +.VE +.sp +void +\fBTcl_SetStringObj\fR(\fIobjPtr, bytes, length\fR) +.VS 8.1.2 +.sp +void +\fBTcl_SetUnicodeObj\fR(\fIobjPtr, unicode, numChars\fR) +.VE +.sp +char * +\fBTcl_GetStringFromObj\fR(\fIobjPtr, lengthPtr\fR) +.sp +char * +\fBTcl_GetString\fR(\fIobjPtr\fR) +.VS 8.1.2 +.sp +Tcl_UniChar * +\fBTcl_GetUnicode\fR(\fIobjPtr\fR) +.sp +Tcl_UniChar +\fBTcl_GetUniChar\fR(\fIobjPtr, index\fR) +.sp +int +\fBTcl_GetCharLength\fR(\fIobjPtr\fR) +.sp +Tcl_Obj * +\fBTcl_GetRange\fR(\fIobjPtr, first, last\fR) +.VE +.sp +void +\fBTcl_AppendToObj\fR(\fIobjPtr, bytes, length\fR) +.VS 8.1.2 +.sp +void +\fBTcl_AppendUnicodeToObj\fR(\fIobjPtr, unicode, numChars\fR) +.VE +.sp +void +\fBTcl_AppendObjToObj\fR(\fIobjPtr, appendObjPtr\fR) +.sp +void +\fBTcl_AppendStringsToObj\fR(\fIobjPtr, string, string, ... \fB(char *) NULL\fR) +.sp +void +\fBTcl_AppendStringsToObjVA\fR(\fIobjPtr, argList\fR) +.sp +void +\fBTcl_SetObjLength\fR(\fIobjPtr, newLength\fR) +.sp +Tcl_Obj * +\fBTcl_ConcatObj\fR(\fIobjc, objv\fR) +.SH ARGUMENTS +.AS Tcl_Interp *appendObjPtr in/out +.AP char *bytes in +Points to the first byte of an array of bytes +used to set or append to a string object. +This byte array may contain embedded null bytes +unless \fIlength\fR is negative. +.AP int length in +The number of bytes to copy from \fIbytes\fR when +initializing, setting, or appending to a string object. +If negative, all bytes up to the first null are used. +.AP Tcl_UniChar *unicode in +Points to the first byte of an array of Unicode characters +used to set or append to a string object. +This byte array may contain embedded null characters +unless \fInumChars\fR is negative. +.VS 8.1.2 +.AP int numChars in +The number of Unicode characters to copy from \fIunicode\fR when +initializing, setting, or appending to a string object. +If negative, all characters up to the first null character are used. +.AP int index in +The index of the Unicode character to return. +.AP int first in +The index of the first Unicode character in the Unicode range to be +returned as a new object. +.AP int last in +The index of the last Unicode character in the Unicode range to be +returned as a new object. +.VE +.AP Tcl_Obj *objPtr in/out +Points to an object to manipulate. +.AP Tcl_Obj *appendObjPtr in +The object to append to \fIobjPtr\fR in \fBTcl_AppendObjToObj\fR. +.AP int *lengthPtr out +If non-NULL, the location where \fBTcl_GetStringFromObj\fR will store +the the length of an object's string representation. +.AP char *string in +Null-terminated string value to append to \fIobjPtr\fR. +.AP va_list argList in +An argument list which must have been initialised using +\fBTCL_VARARGS_START\fR, and cleared using \fBva_end\fR. +.AP int newLength in +New length for the string value of \fIobjPtr\fR, not including the +final NULL character. +.AP int objc in +The number of elements to concatenate. +.AP Tcl_Obj *objv[] in +The array of objects to concatenate. +.BE + +.SH DESCRIPTION +.PP +The procedures described in this manual entry allow Tcl objects to +be manipulated as string values. They use the internal representation +of the object to store additional information to make the string +manipulations more efficient. In particular, they make a series of +append operations efficient by allocating extra storage space for the +string so that it doesn't have to be copied for each append. +.VS 8.1.2 +Also, indexing and length computations are optimized because the +Unicode string representation is calculated and cached as needed. +.VE +.PP +.VS 8.1.2 +\fBTcl_NewStringObj\fR and \fBTcl_SetStringObj\fR create a new object +or modify an existing object to hold a copy of the string given by +\fIbytes\fR and \fIlength\fR. \fBTcl_NewUnicodeObj\fR and +\fBTcl_SetUnicodeObj\fR create a new object or modify an existing +object to hold a copy of the Unicode string given by \fIunicode\fR and +\fInumChars\fR. \fBTcl_NewStringObj\fR and \fBTcl_NewUnicodeObj\fR +return a pointer to a newly created object with reference count zero. +All four procedures set the object to hold a copy of the specified +string. \fBTcl_SetStringObj\fR and \fBTcl_SetUnicodeObj\fR free any +old string representation as well as any old internal representation +of the object. +.VE +.PP +\fBTcl_GetStringFromObj\fR and \fBTcl_GetString\fR return an object's +string representation. This is given by the returned byte pointer and +(for \fBTcl_GetStringFromObj\fR) length, which is stored in +\fIlengthPtr\fR if it is non-NULL. If the object's UTF string +representation is invalid (its byte pointer is NULL), the string +representation is regenerated from the object's internal +representation. The storage referenced by the returned byte pointer +is owned by the object manager and should not be modified by the +caller. The procedure \fBTcl_GetString\fR is used in the common case +where the caller does not need the length of the string +representation. +.PP +.VS 8.1.2 +\fBTcl_GetUnicode\fR returns an object's value as a Unicode string. +\fBTcl_GetUniChar\fR returns the \fIindex\fR'th character in the +object's Unicode representation. +.PP +\fBTcl_GetRange\fR returns a newly created object comprised of the +characters between \fIfirst\fR and \fIlast\fR (inclusive) in the +object's Unicode representation. If the object's Unicode +representation is invalid, the Unicode representation is regenerated +from the object's string representation. +.PP +\fBTcl_GetCharLength\fR returns the number of characters (as opposed +to bytes) in the string object. +.PP +\fBTcl_AppendToObj\fR appends the data given by \fIbytes\fR and +\fIlength\fR to the string representation of the object specified by +\fIobjPtr\fR. If the object has an invalid string representation, +then an attempt is made to convert \fIbytes\fR is to the Unicode +format. If the conversion is successful, then the converted form of +\fIbytes\fR is appended to the object's Unicode representation. +Otherwise, the object's Unicode representation is invalidated and +converted to the UTF format, and \fIbytes\fR is appended to the +object's new string representation. +.PP +\fBTcl_AppendUnicodeToObj\fR appends the Unicode string given by +\fIunicode\fR and \fInumChars\fR to the object specified by +\fIobjPtr\fR. If the object has an invalid Unicode representation, +then \fIunicode\fR is converted to the UTF format and appended to the +object's string representation. Appends are optimized to handle +repeated appends relatively efficiently (it overallocates the string +or Unicode space to avoid repeated reallocations and copies of +object's string value). +.PP +\fBTcl_AppendObjToObj\fR is similar to \fBTcl_AppendToObj\fR, but it +appends the string or Unicode value (whichever exists and is best +suited to be appended to \fIobjPtr\fR) of \fIappendObjPtr\fR to +\fIobjPtr\fR. +.VE +.PP +\fBTcl_AppendStringsToObj\fR is similar to \fBTcl_AppendToObj\fR +except that it can be passed more than one value to append and +each value must be a null-terminated string (i.e. none of the +values may contain internal null characters). Any number of +\fIstring\fR arguments may be provided, but the last argument +must be a NULL pointer to indicate the end of the list. +.PP +\fBTcl_AppendStringsToObjVA\fR is the same as \fBTcl_AppendStringsToObj\fR +except that instead of taking a variable number of arguments it takes an +argument list. +.PP +The \fBTcl_SetObjLength\fR procedure changes the length of the +string value of its \fIobjPtr\fR argument. If the \fInewLength\fR +argument is greater than the space allocated for the object's +string, then the string space is reallocated and the old value +is copied to the new space; the bytes between the old length of +the string and the new length may have arbitrary values. +If the \fInewLength\fR argument is less than the current length +of the object's string, with \fIobjPtr->length\fR is reduced without +reallocating the string space; the original allocated size for the +string is recorded in the object, so that the string length can be +enlarged in a subsequent call to \fBTcl_SetObjLength\fR without +reallocating storage. In all cases \fBTcl_SetObjLength\fR leaves +a null character at \fIobjPtr->bytes[newLength]\fR. +.PP +The \fBTcl_ConcatObj\fR function returns a new string object whose +value is the space-separated concatenation of the string +representations of all of the objects in the \fIobjv\fR +array. \fBTcl_ConcatObj\fR eliminates leading and trailing white space +as it copies the string representations of the \fIobjv\fR array to the +result. If an element of the \fIobjv\fR array consists of nothing but +white space, then that object is ignored entirely. This white-space +removal was added to make the output of the \fBconcat\fR command +cleaner-looking. \fBTcl_ConcatObj\fR returns a pointer to a +newly-created object whose ref count is zero. + +.SH "SEE ALSO" +Tcl_NewObj, Tcl_IncrRefCount, Tcl_DecrRefCount + +.SH KEYWORDS +append, internal representation, object, object type, string object, +string type, string representation, concat, concatenate, unicode diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/TCL_MEM_DEBUG.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/TCL_MEM_DEBUG.3 new file mode 100644 index 0000000000000000000000000000000000000000..8d891fbbc61416c16c84bc5120852014642ff8f5 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/TCL_MEM_DEBUG.3 @@ -0,0 +1,82 @@ +'\" +'\" Copyright (c) 1992-1999 Karl Lehenbauer and Mark Diekhans. +'\" Copyright (c) 2000 by Scriptics Corporation. +'\" All rights reserved. +'\" +'\" RCS: @(#) $Id: TCL_MEM_DEBUG.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH TCL_MEM_DEBUG 3 8.1 Tcl "Tcl Library Procedures" +.BS +.SH NAME +TCL_MEM_DEBUG \- Compile-time flag to enable Tcl memory debugging. + +.SH DESCRIPTION +When Tcl is compiled with \fBTCL_MEM_DEBUG\fR defined, a powerful set +of memory debugging aids are included in the compiled binary. This +includes C and Tcl functions which can aid with debugging +memory leaks, memory allocation overruns, and other memory related +errors. + +.SH ENABLING MEMORY DEBUGGING +.PP +To enable memory debugging, Tcl should be recompiled from scratch with +\fBTCL_MEM_DEBUG\fR defined. This will also compile in a non-stub +version of \fBTcl_InitMemory\fR to add the \fBmemory\fR command to Tcl. +.PP +\fBTCL_MEM_DEBUG\fR must be either left defined for all modules or undefined +for all modules that are going to be linked together. If they are not, link +errors will occur, with either \fBTclDbCkfree\fR and \fBTcl_DbCkalloc\fR or +\fBTcl_Ckalloc\fR and \fBTcl_Ckfree\fR being undefined. +.PP +Once memory debugging support has been compiled into Tcl, the C +functions \fBTcl_ValidateAllMemory\fR, and \fBTcl_DumpActiveMemory\fR, +and the Tcl \fBmemory\fR command can be used to validate and examine +memory usage. + +.SH GUARD ZONES +.PP +When memory debugging is enabled, whenever a call to \fBckalloc\fR is +made, slightly more memory than requested is allocated so the memory debugging +code can keep track of the allocated memory, and eight-byte ``guard +zones'' are placed in front of and behind the space that will be +returned to the caller. (The sizes of the guard zones are defined by the +C #define \fBLOW_GUARD_SIZE\fR and #define \fBHIGH_GUARD_SIZE\fR +in the file \fIgeneric/tclCkalloc.c\fR -- it can +be extended if you suspect large overwrite problems, at some cost in +performance.) A known pattern is written into the guard zones and, on +a call to \fBckfree\fR, the guard zones of the space being freed are +checked to see if either zone has been modified in any way. If one +has been, the guard bytes and their new contents are identified, and a +``low guard failed'' or ``high guard failed'' message is issued. The +``guard failed'' message includes the address of the memory packet and +the file name and line number of the code that called \fBckfree\fR. +This allows you to detect the common sorts of one-off problems, where +not enough space was allocated to contain the data written, for +example. + +.SH DEBUGGING DIFFICULT MEMORY CORRUPTION PROBLEMS +.PP +Normally, Tcl compiled with memory debugging enabled will make it easy +to isolate a corruption problem. Turning on memory validation with +the memory command can help isolate difficult problems. If you +suspect (or know) that corruption is occurring before the Tcl +interpreter comes up far enough for you to issue commands, you can set +\fBMEM_VALIDATE\fR define, recompile tclCkalloc.c and rebuild Tcl. +This will enable memory validation from the first call to +\fBckalloc\fR, again, at a large performance impact. +.PP +If you are desperate and validating memory on every call to +\fBckalloc\fR and \fBckfree\fR isn't enough, you can explicitly call +\fBTcl_ValidateAllMemory\fR directly at any point. It takes a \fIchar +*\fR and an \fIint\fR which are normally the filename and line number +of the caller, but they can actually be anything you want. Remember +to remove the calls after you find the problem. + +.SH "SEE ALSO" +memory, Tcl_ValidateAllMemory, Tcl_DumpActiveMemory + +.SH KEYWORDS +memory, debug + + diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Tcl.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Tcl.n new file mode 100644 index 0000000000000000000000000000000000000000..8f3534a413e250d28629b70b7e0404c21c87f278 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Tcl.n @@ -0,0 +1,195 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: Tcl.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl n "8.1" Tcl "Tcl Built-In Commands" +.BS +.SH NAME +Tcl \- Summary of Tcl language syntax. +.BE + +.SH DESCRIPTION +.PP +The following rules define the syntax and semantics of the Tcl language: +.IP [1] +A Tcl script is a string containing one or more commands. +Semi-colons and newlines are command separators unless quoted as +described below. +Close brackets are command terminators during command substitution +(see below) unless quoted. +.IP [2] +A command is evaluated in two steps. +First, the Tcl interpreter breaks the command into \fIwords\fR +and performs substitutions as described below. +These substitutions are performed in the same way for all +commands. +The first word is used to locate a command procedure to +carry out the command, then all of the words of the command are +passed to the command procedure. +The command procedure is free to interpret each of its words +in any way it likes, such as an integer, variable name, list, +or Tcl script. +Different commands interpret their words differently. +.IP [3] +Words of a command are separated by white space (except for +newlines, which are command separators). +.IP [4] +If the first character of a word is double-quote (``"'') then +the word is terminated by the next double-quote character. +If semi-colons, close brackets, or white space characters +(including newlines) appear between the quotes then they are treated +as ordinary characters and included in the word. +Command substitution, variable substitution, and backslash substitution +are performed on the characters between the quotes as described below. +The double-quotes are not retained as part of the word. +.IP [5] +If the first character of a word is an open brace (``{'') then +the word is terminated by the matching close brace (``}''). +Braces nest within the word: for each additional open +brace there must be an additional close brace (however, +if an open brace or close brace within the word is +quoted with a backslash then it is not counted in locating the +matching close brace). +No substitutions are performed on the characters between the +braces except for backslash-newline substitutions described +below, nor do semi-colons, newlines, close brackets, +or white space receive any special interpretation. +The word will consist of exactly the characters between the +outer braces, not including the braces themselves. +.IP [6] +If a word contains an open bracket (``['') then Tcl performs +\fIcommand substitution\fR. +To do this it invokes the Tcl interpreter recursively to process +the characters following the open bracket as a Tcl script. +The script may contain any number of commands and must be terminated +by a close bracket (``]''). +The result of the script (i.e. the result of its last command) is +substituted into the word in place of the brackets and all of the +characters between them. +There may be any number of command substitutions in a single word. +Command substitution is not performed on words enclosed in braces. +.IP [7] +If a word contains a dollar-sign (``$'') then Tcl performs \fIvariable +substitution\fR: the dollar-sign and the following characters are +replaced in the word by the value of a variable. +Variable substitution may take any of the following forms: +.RS +.TP 15 +\fB$\fIname\fR +\fIName\fR is the name of a scalar variable; the name is terminated +by any character that isn't a letter, digit, or underscore. +.TP 15 +\fB$\fIname\fB(\fIindex\fB)\fR +\fIName\fR gives the name of an array variable and \fIindex\fR gives +the name of an element within that array. +\fIName\fR must contain only letters, digits, and underscores. +Command substitutions, variable substitutions, and backslash +substitutions are performed on the characters of \fIindex\fR. +.TP 15 +\fB${\fIname\fB}\fR +\fIName\fR is the name of a scalar variable. It may contain any +characters whatsoever except for close braces. +.LP +There may be any number of variable substitutions in a single word. +Variable substitution is not performed on words enclosed in braces. +.RE +.IP [8] +If a backslash (``\e'') appears within a word then +\fIbackslash substitution\fR occurs. +In all cases but those described below the backslash is dropped and +the following character is treated as an ordinary +character and included in the word. +This allows characters such as double quotes, close brackets, +and dollar signs to be included in words without triggering +special processing. +The following table lists the backslash sequences that are +handled specially, along with the value that replaces each sequence. +.RS +.TP 7 +\e\fBa\fR +Audible alert (bell) (0x7). +.TP 7 +\e\fBb\fR +Backspace (0x8). +.TP 7 +\e\fBf\fR +Form feed (0xc). +.TP 7 +\e\fBn\fR +Newline (0xa). +.TP 7 +\e\fBr\fR +Carriage-return (0xd). +.TP 7 +\e\fBt\fR +Tab (0x9). +.TP 7 +\e\fBv\fR +Vertical tab (0xb). +.TP 7 +\e\fB\fIwhiteSpace\fR +. +A single space character replaces the backslash, newline, and all spaces +and tabs after the newline. This backslash sequence is unique in that it +is replaced in a separate pre-pass before the command is actually parsed. +This means that it will be replaced even when it occurs between braces, +and the resulting space will be treated as a word separator if it isn't +in braces or quotes. +.TP 7 +\e\e +Backslash (``\e''). +.VS 8.1 br +.TP 7 +\e\fIooo\fR +. +The digits \fIooo\fR (one, two, or three of them) give an eight-bit octal +value for the Unicode character that will be inserted. The upper bits of the +Unicode character will be 0. +.TP 7 +\e\fBx\fIhh\fR +. +The hexadecimal digits \fIhh\fR give an eight-bit hexadecimal value for the +Unicode character that will be inserted. Any number of hexadecimal digits +may be present; however, all but the last two are ignored (the result is +always a one-byte quantity). The upper bits of the Unicode character will +be 0. +.TP 7 +\e\fBu\fIhhhh\fR +. +The hexadecimal digits \fIhhhh\fR (one, two, three, or four of them) give a +sixteen-bit hexadecimal value for the Unicode character that will be +inserted. +.VE +.LP +Backslash substitution is not performed on words enclosed in braces, +except for backslash-newline as described above. +.RE +.IP [9] +If a hash character (``#'') appears at a point where Tcl is +expecting the first character of the first word of a command, +then the hash character and the characters that follow it, up +through the next newline, are treated as a comment and ignored. +The comment character only has significance when it appears +at the beginning of a command. +.IP [10] +Each character is processed exactly once by the Tcl interpreter +as part of creating the words of a command. +For example, if variable substitution occurs then no further +substitutions are performed on the value of the variable; the +value is inserted into the word verbatim. +If command substitution occurs then the nested command is +processed entirely by the recursive call to the Tcl interpreter; +no substitutions are performed before making the recursive +call and no additional substitutions are performed on the result +of the nested script. +.IP [11] +Substitutions do not affect the word boundaries of a command. +For example, during variable substitution the entire value of +the variable becomes part of a single word, even if the variable's +value contains spaces. diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Tcl_Main.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Tcl_Main.3 new file mode 100644 index 0000000000000000000000000000000000000000..a52bf6ee3c19f583aba9f44ef86649e6bf3b8d7e --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Tcl_Main.3 @@ -0,0 +1,81 @@ +'\" +'\" Copyright (c) 1994 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" Copyright (c) 2000 Ajuba Solutions. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: Tcl_Main.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_Main 3 8.3.4 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_Main, Tcl_SetMainLoop \- main program and event loop definition for Tcl-based applications +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +\fBTcl_Main\fR(\fIargc, argv, appInitProc\fR) +.sp +\fBTcl_SetMainLoop\fR(\fImainLoopProc\fR) +.SH ARGUMENTS +.AS Tcl_AppInitProc *appInitProc +.AP int argc in +Number of elements in \fIargv\fR. +.AP char *argv[] in +Array of strings containing command-line arguments. +.AP Tcl_AppInitProc *appInitProc in +Address of an application-specific initialization procedure. +The value for this argument is usually \fBTcl_AppInit\fR. +.AP Tcl_MainLoopProc *mainLoopProc in +Address of an application-specific event loop procedure. +.BE + +.SH DESCRIPTION +.PP +\fBTcl_Main\fR acts as the main program for most Tcl-based applications. +Starting with Tcl 7.4 it is not called \fBmain\fR anymore because it +is part of the Tcl library and having a function \fBmain\fR +in a library (particularly a shared library) causes problems on many +systems. +Having \fBmain\fR in the Tcl library would also make it hard to use +Tcl in C++ programs, since C++ programs must have special C++ +\fBmain\fR functions. +.PP +Normally each application contains a small \fBmain\fR function that does +nothing but invoke \fBTcl_Main\fR. +\fBTcl_Main\fR then does all the work of creating and running a +\fBtclsh\fR-like application. +.PP +When it is has finished its own initialization, but before +it processes commands, \fBTcl_Main\fR calls the procedure given by +the \fIappInitProc\fR argument. This procedure provides a ``hook'' +for the application to perform its own initialization, such as defining +application-specific commands. The procedure must have an interface +that matches the type \fBTcl_AppInitProc\fR: +.CS +typedef int Tcl_AppInitProc(Tcl_Interp *\fIinterp\fR); +.CE + +\fIAppInitProc\fR is almost always a pointer to \fBTcl_AppInit\fR; for more +details on this procedure, see the documentation for \fBTcl_AppInit\fR. +When the \fIappInitProc\fR is finished, the startup script will be +evaluated. If none exists, then an interactive prompt is provided. +.PP +.VS 8.3.4 +\fBTcl_SetMainLoop\fR allows setting an event loop procedure to be run. +This allows, for example, Tk to be dynamically loaded and set its event +loop. The event loop will run following the startup script. If you +are in interactive mode, setting the main loop procedure will cause the +prompt to become fileevent based and then the loop procedure is called. +The main loop procedure must have an interface that matches the type +\fBTcl_MainLoopProc\fR: +.CS +typedef void Tcl_MainLoopProc(void); +.CE +.VE 8.3.4 + +.SH KEYWORDS +application-specific initialization, command-line arguments, main program diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Thread.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Thread.3 new file mode 100644 index 0000000000000000000000000000000000000000..4f676fb18a1b1c0f1564c7520602571a17c88902 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Thread.3 @@ -0,0 +1,194 @@ +'\" +'\" Copyright (c) 1999 Scriptics Corporation +'\" Copyright (c) 1998 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: Thread.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Threads 3 "8.1" Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_ConditionNotify, Tcl_ConditionWait, Tcl_ConditionFinalize, Tcl_GetThreadData, Tcl_MutexLock, Tcl_MutexUnlock, Tcl_MutexFinalize, Tcl_CreateThread \- Tcl thread support. +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +void +\fBTcl_ConditionNotify\fR(\fIcondPtr\fR) +.sp +void +\fBTcl_ConditionWait\fR(\fIcondPtr, mutexPtr, timePtr\fR) +.sp +void +\fBTcl_ConditionFinalize\fR(\fIcondPtr\fR) +.sp +Void * +\fBTcl_GetThreadData\fR(\fIkeyPtr, size\fR) +.sp +void +\fBTcl_MutexLock\fR(\fImutexPtr\fR) +.sp +void +\fBTcl_MutexUnlock\fR(\fImutexPtr\fR) +.sp +void +\fBTcl_MutexFinalize\fR(\fImutexPtr\fR) +.sp +int +\fBTcl_CreateThread\fR(\fIidPtr, threadProc, clientData, stackSize, flags\fR) +.SH ARGUMENTS +.AS Tcl_ThreadDataKey *keyPtr +.AP Tcl_Condition *condPtr in +A condition variable, which must be associated with a mutex lock. +.AP Tcl_Condition *mutexPtr in +A mutex lock. +.AP Tcl_Time *timePtr in +A time limit on the condition wait. NULL to wait forever. +Note that a polling value of 0 seconds doesn't make much sense. +.AP Tcl_ThreadDataKey *keyPtr in +This identifies a block of thread local storage. The key should be +static and process-wide, yet each thread will end up associating +a different block of storage with this key. +.AP int *size in +The size of the thread local storage block. This amount of data +is allocated and initialized to zero the first time each thread +calls \fBTcl_GetThreadData\fR. +.AP Tcl_ThreadId *idPtr out +The refered storage will contain the id of the newly created thread as +returned by the operating system. +.AP Tcl_ThreadId id in +Id of the thread waited upon. +.AP Tcl_ThreadCreateProc threadProc in +This procedure will act as the \fBmain()\fR of the newly created +thread. The specified \fIclientData\fR will be its sole argument. +.AP ClientData clientData in +Arbitrary information. Passed as sole argument to the \fIthreadProc\fR. +.AP int stackSize in +The size of the stack given to the new thread. +.AP int flags in +Bitmask containing flags allowing the caller to modify behaviour of +the new thread. +.AP int *result out +The refered storage is used to place the exit code of the thread +waited upon into it. +.BE +.SH INTRODUCTION +Beginning with the 8.1 release, the Tcl core is thread safe, which +allows you to incorporate Tcl into multithreaded applications without +customizing the Tcl core. To enable Tcl multithreading support, +you must include the \fB--enable-threads\fR option to \fBconfigure\fR +when you configure and compile your Tcl core. +.PP +An important contstraint of the Tcl threads implementation is that +\fIonly the thread that created a Tcl interpreter can use that +interpreter\fR. In other words, multiple threads can not access +the same Tcl interpreter. (However, as was the case in previous +releases, a single thread can safely create and use multiple +interpreters.) +.PP +.VS 8.3.1 +Tcl does provide \fBTcl_CreateThread\fR for creating threads. The +caller can determine the size of the stack given to the new thread and +modify the behaviour through the supplied \fIflags\fR. The value +\fBTCL_THREAD_STACK_DEFAULT\fR for the \fIstackSize\fR indicates that +the default size as specified by the operating system is to be used +for the new thread. As for the flags, currently are only the values +\fBTCL_THREAD_NOFLAGS\fR and \fBTCL_THREAD_JOINABLE\fR defined. The +first of them invokes the default behaviour with no +specialities. Using the second value marks the new thread as +\fIjoinable\fR. This means that another thread can wait for the such +marked thread to exit and join it. +.PP +Restrictions: On some unix systems the pthread-library does not +contain the functionality to specify the stacksize of a thread. The +specified value for the stacksize is ignored on these systems. Both +Windows and Macintosh currently do not support joinable threads. This +flag value is therefore ignored on these platforms. +.VE +.PP +Tcl does provide \fBTcl_ExitThread\fR and \fBTcl_FinalizeThread\fR +for terminating threads and invoking optional per-thread exit +handlers. See the \fBTcl_Exit\fR page for more information on these +procedures. +.PP +Tcl provides \fBTcl_ThreadQueueEvent\fR and \fBTcl_ThreadAlert\fR +for handling event queueing in multithreaded applications. See +the \fBNotifier\fR manual page for more information on these procedures. +.PP +In this release, the Tcl language itself provides no support for +creating multithreaded scripts (for example, scripts that could spawn +a Tcl interpreter in a separate thread). If you need to add this +feature at this time, see the \fItclThreadTest.c\fR +file in the Tcl source distribution for an experimental implementation +of a Tcl "Thread" package implementing thread creation and management +commands at the script level. + +.SH DESCRIPTION +A mutex is a lock that is used to serialize all threads through a piece +of code by calling \fBTcl_MutexLock\fR and \fBTcl_MutexUnlock\fR. +If one thread holds a mutex, any other thread calling \fBTcl_MutexLock\fR will +block until \fBTcl_MutexUnlock\fR is called. +.VS +A mutex can be destroyed after its use by calling \fBTcl_MutexFinalize\fR. +The result of locking a mutex twice from the same thread is undefined. +On some platforms it will result in a deadlock. +.VE +The \fBTcl_MutexLock\fR, \fBTcl_MutexUnlock\fR and \fBTcl_MutexFinalize\fR +procedures are defined as empty macros if not compiling with threads enabled. +.PP +A condition variable is used as a signaling mechanism: +a thread can lock a mutex and then wait on a condition variable +with \fBTcl_ConditionWait\fR. This atomically releases the mutex lock +and blocks the waiting thread until another thread calls +\fBTcl_ConditionNotify\fR. The caller of \fBTcl_ConditionNotify\fR should +have the associated mutex held by previously calling \fBTcl_MutexLock\fR, +but this is not enforced. Notifying the +condition variable unblocks all threads waiting on the condition variable, +but they do not proceed until the mutex is released with \fBTcl_MutexUnlock\fR. +The implementation of \fBTcl_ConditionWait\fR automatically locks +the mutex before returning. +.PP +The caller of \fBTcl_ConditionWait\fR should be prepared for spurious +notifications by calling \fBTcl_ConditionWait\fR within a while loop +that tests some invariant. +.PP +.VS +A condition variable can be destroyed after its use by calling +\fBTcl_ConditionFinalize\fR. +.PP +The \fBTcl_ConditionNotify\fR, \fBTcl_ConditionWait\fR and +\fBTcl_ConditionFinalize\fR procedures are defined as empty macros if +not compiling with threads enabled. +.VE +.PP +The \fBTcl_GetThreadData\fR call returns a pointer to a block of +thread-private data. Its argument is a key that is shared by all threads +and a size for the block of storage. The storage is automatically +allocated and initialized to all zeros the first time each thread asks for it. +The storage is automatically deallocated by \fBTcl_FinalizeThread\fR. +.SH INITIALIZATION +.PP +All of these synchronization objects are self initializing. +They are implemented as opaque pointers that should be NULL +upon first use. +The mutexes and condition variables are +.VS +either cleaned up by process exit handlers (if living that long) or +explicitly by calls to \fBTcl_MutexFinalize\fR or +\fBTcl_ConditionFinalize\fR. +.VE +Thread local storage is reclaimed during \fBTcl_FinalizeThread\fR. +.SH "CREATING THREADS" +The API to create threads is not finalized at this time. +There are private facilities to create threads that contain a new +Tcl interpreter, and to send scripts among threads. +Dive into tclThreadTest.c and tclThread.c for examples. +.SH "SEE ALSO" +Tcl_GetCurrentThread, Tcl_ThreadQueueEvent, Tcl_ThreadAlert, +Tcl_ExitThread, Tcl_FinalizeThread, +Tcl_CreateThreadExitHandler, Tcl_DeleteThreadExitHandler +.SH KEYWORDS +thread, mutex, condition variable, thread local storage diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/ToUpper.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/ToUpper.3 new file mode 100644 index 0000000000000000000000000000000000000000..808fc54ceef824029d6a4859e5ea12a3b060dcaf --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/ToUpper.3 @@ -0,0 +1,90 @@ +'\" +'\" Copyright (c) 1997 by Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: ToUpper.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_UtfToUpper 3 "8.1" Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_UniCharToUpper, Tcl_UniCharToLower, Tcl_UniCharToTitle, Tcl_UtfToUpper, Tcl_UtfToLower, Tcl_UtfToTitle \- routines for manipulating the case of Unicode characters and UTF-8 strings. +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +Tcl_UniChar +\fBTcl_UniCharToUpper\fR(\fIch\fR) +.sp +Tcl_UniChar +\fBTcl_UniCharToLower\fR(\fIch\fR) +.sp +Tcl_UniChar +\fBTcl_UniCharToTitle\fR(\fIch\fR) +.sp +int +\fBTcl_UtfToUpper\fR(\fIstr\fR) +.sp +int +\fBTcl_UtfToLower\fR(\fIstr\fR) +.sp +int +\fBTcl_UtfToTitle\fR(\fIstr\fR) +.SH ARGUMENTS +.AS char *str in/out +.AP int ch in +The Tcl_UniChar to be converted. +.AP char *str in/out +Pointer to UTF-8 string to be converted in place. +.BE + +.SH DESCRIPTION +.PP +The first three routines convert the case of individual Unicode characters: +.PP +If \fIch\fR represents a lower-case character, +\fBTcl_UniCharToUpper\fR returns the corresponding upper-case +character. If no upper-case character is defined, it returns the +character unchanged. +.PP +If \fIch\fR represents an upper-case character, +\fBTcl_UniCharToLower\fR returns the corresponding lower-case +character. If no lower-case character is defined, it returns the +character unchanged. +.PP +If \fIch\fR represents a lower-case character, +\fBTcl_UniCharToTitle\fR returns the corresponding title-case +character. If no title-case character is defined, it returns the +corresponding upper-case character. If no upper-case character is +defined, it returns the character unchanged. Title-case is defined +for a small number of characters that have a different appearance when +they are at the beginning of a capitalized word. +.PP +The next three routines convert the case of UTF-8 strings in place in +memory: +.PP +\fBTcl_UtfToUpper\fR changes every UTF-8 character in \fIstr\fR to +upper-case. Because changing the case of a character may change its +size, the byte offset of each character in the resulting string may +differ from its original location. \fBTcl_UtfToUpper\fR writes a null +byte at the end of the converted string. \fBTcl_UtfToUpper\fR returns +the new length of the string in bytes. This new length is guaranteed +to be no longer than the original string length. +.PP +\fBTcl_UtfToLower\fR is the same as \fBTcl_UtfToUpper\fR except it +turns each character in the string into its lower-case equivalent. +.PP +\fBTcl_UtfToTitle\fR is the same as \fBTcl_UtfToUpper\fR except it +turns the first character in the string into its title-case equivalent +and all following characters into their lower-case equivalents. + +.SH BUGS +.PP +At this time, the case conversions are only defined for the ISO8859-1 +characters. Unicode characters above 0x00ff are not modified by these +routines. + +.SH KEYWORDS +utf, unicode, toupper, tolower, totitle, case diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/TraceVar.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/TraceVar.3 new file mode 100644 index 0000000000000000000000000000000000000000..5a832a0a9df0d1cd0bde968f4f3f79612c200db9 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/TraceVar.3 @@ -0,0 +1,366 @@ +'\" +'\" Copyright (c) 1989-1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: TraceVar.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_TraceVar 3 7.4 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_TraceVar, Tcl_TraceVar2, Tcl_UntraceVar, Tcl_UntraceVar2, Tcl_VarTraceInfo, Tcl_VarTraceInfo2 \- monitor accesses to a variable +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +int +\fBTcl_TraceVar(\fIinterp, varName, flags, proc, clientData\fB)\fR +.sp +int +\fBTcl_TraceVar2(\fIinterp, name1, name2, flags, proc, clientData\fB)\fR +.sp +\fBTcl_UntraceVar(\fIinterp, varName, flags, proc, clientData\fB)\fR +.sp +\fBTcl_UntraceVar2(\fIinterp, name1, name2, flags, proc, clientData\fB)\fR +.sp +ClientData +\fBTcl_VarTraceInfo(\fIinterp, varName, flags, proc, prevClientData\fB)\fR +.sp +ClientData +\fBTcl_VarTraceInfo2(\fIinterp, name1, name2, flags, proc, prevClientData\fB)\fR +.SH ARGUMENTS +.AS Tcl_VarTraceProc prevClientData +.AP Tcl_Interp *interp in +Interpreter containing variable. +.AP char *varName in +Name of variable. May refer to a scalar variable, to +an array variable with no index, or to an array variable +with a parenthesized index. +If the name references an element of an array, then it +must be in writable memory: Tcl will make temporary modifications +to it while looking up the name. +.AP int flags in +OR-ed combination of the values TCL_TRACE_READS, TCL_TRACE_WRITES, and +TCL_TRACE_UNSETS, TCL_TRACE_ARRAY, and TCL_GLOBAL_ONLY. +Not all flags are used by all +procedures. See below for more information. +.AP Tcl_VarTraceProc *proc in +Procedure to invoke whenever one of the traced operations occurs. +.AP ClientData clientData in +Arbitrary one-word value to pass to \fIproc\fR. +.AP char *name1 in +Name of scalar or array variable (without array index). +.AP char *name2 in +For a trace on an element of an array, gives the index of the +element. For traces on scalar variables or on whole arrays, +is NULL. +.AP ClientData prevClientData in +If non-NULL, gives last value returned by \fBTcl_VarTraceInfo\fR or +\fBTcl_VarTraceInfo2\fR, so this call will return information about +next trace. If NULL, this call will return information about first +trace. +.BE + +.SH DESCRIPTION +.PP +\fBTcl_TraceVar\fR allows a C procedure to monitor and control +access to a Tcl variable, so that the C procedure is invoked +whenever the variable is read or written or unset. +If the trace is created successfully then \fBTcl_TraceVar\fR returns +TCL_OK. If an error occurred (e.g. \fIvarName\fR specifies an element +of an array, but the actual variable isn't an array) then TCL_ERROR +is returned and an error message is left in the interpreter's result. +.PP +The \fIflags\fR argument to \fBTcl_TraceVar\fR indicates when the +trace procedure is to be invoked and provides information +for setting up the trace. It consists of an OR-ed combination +of any of the following values: +.TP +\fBTCL_GLOBAL_ONLY\fR +Normally, the variable will be looked up at the current level of +procedure call; if this bit is set then the variable will be looked +up at global level, ignoring any active procedures. +.TP +\fBTCL_TRACE_READS\fR +Invoke \fIproc\fR whenever an attempt is made to read the variable. +.TP +\fBTCL_TRACE_WRITES\fR +Invoke \fIproc\fR whenever an attempt is made to modify the variable. +.TP +\fBTCL_TRACE_UNSETS\fR +Invoke \fIproc\fR whenever the variable is unset. +A variable may be unset either explicitly by an \fBunset\fR command, +or implicitly when a procedure returns (its local variables are +automatically unset) or when the interpreter is deleted (all +variables are automatically unset). +.TP +\fBTCL_TRACE_ARRAY\fR +Invoke \fIproc\fR whenever the array command is invoked. +This gives the trace procedure a chance to update the array before +array names or array get is called. Note that this is called +before an array set, but that will trigger write traces. +.PP +Whenever one of the specified operations occurs on the variable, +\fIproc\fR will be invoked. +It should have arguments and result that match the type +\fBTcl_VarTraceProc\fR: +.CS +typedef char *Tcl_VarTraceProc( + ClientData \fIclientData\fR, + Tcl_Interp *\fIinterp\fR, + char *\fIname1\fR, + char *\fIname2\fR, + int \fIflags\fR); +.CE +The \fIclientData\fR and \fIinterp\fR parameters will +have the same values as those passed to \fBTcl_TraceVar\fR when the +trace was created. +\fIClientData\fR typically points to an application-specific +data structure that describes what to do when \fIproc\fR +is invoked. +\fIName1\fR and \fIname2\fR give the name of the traced variable +in the normal two-part form (see the description of \fBTcl_TraceVar2\fR +below for details). +\fIFlags\fR is an OR-ed combination of bits providing several +pieces of information. +One of the bits TCL_TRACE_READS, TCL_TRACE_WRITES, TCL_TRACE_ARRAY, +or TCL_TRACE_UNSETS +will be set in \fIflags\fR to indicate which operation is being performed +on the variable. +The bit TCL_GLOBAL_ONLY will be set whenever the variable being +accessed is a global one not accessible from the current level of +procedure call: the trace procedure will need to pass this flag +back to variable-related procedures like \fBTcl_GetVar\fR if it +attempts to access the variable. +The bit TCL_TRACE_DESTROYED will be set in \fIflags\fR if the trace is +about to be destroyed; this information may be useful to \fIproc\fR +so that it can clean up its own internal data structures (see +the section TCL_TRACE_DESTROYED below for more details). +Lastly, the bit TCL_INTERP_DESTROYED will be set if the entire +interpreter is being destroyed. +When this bit is set, \fIproc\fR must be especially careful in +the things it does (see the section TCL_INTERP_DESTROYED below). +The trace procedure's return value should normally be NULL; see +ERROR RETURNS below for information on other possibilities. +.PP +\fBTcl_UntraceVar\fR may be used to remove a trace. +If the variable specified by \fIinterp\fR, \fIvarName\fR, and \fIflags\fR +has a trace set with \fIflags\fR, \fIproc\fR, and +\fIclientData\fR, then the corresponding trace is removed. +If no such trace exists, then the call to \fBTcl_UntraceVar\fR +has no effect. +The same bits are valid for \fIflags\fR as for calls to \fBTcl_TraceVar\fR. +.PP +\fBTcl_VarTraceInfo\fR may be used to retrieve information about +traces set on a given variable. +The return value from \fBTcl_VarTraceInfo\fR is the \fIclientData\fR +associated with a particular trace. +The trace must be on the variable specified by the \fIinterp\fR, +\fIvarName\fR, and \fIflags\fR arguments (only the TCL_GLOBAL_ONLY +bit from \fIflags\fR is used; other bits are ignored) and its trace procedure +must the same as the \fIproc\fR argument. +If the \fIprevClientData\fR argument is NULL then the return +value corresponds to the first (most recently created) matching +trace, or NULL if there are no matching traces. +If the \fIprevClientData\fR argument isn't NULL, then it should +be the return value from a previous call to \fBTcl_VarTraceInfo\fR. +In this case, the new return value will correspond to the next +matching trace after the one whose \fIclientData\fR matches +\fIprevClientData\fR, or NULL if no trace matches \fIprevClientData\fR +or if there are no more matching traces after it. +This mechanism makes it possible to step through all of the +traces for a given variable that have the same \fIproc\fR. + +.SH "TWO-PART NAMES" +.PP +The procedures \fBTcl_TraceVar2\fR, \fBTcl_UntraceVar2\fR, and +\fBTcl_VarTraceInfo2\fR are identical to \fBTcl_TraceVar\fR, +\fBTcl_UntraceVar\fR, and \fBTcl_VarTraceInfo\fR, respectively, +except that the name of the variable consists of two parts. +\fIName1\fR gives the name of a scalar variable or array, +and \fIname2\fR gives the name of an element within an array. +.VS 8.1 +When \fIname2\fR is NULL, +\fIname1\fR may contain both an array and an element name: +if the name contains an open parenthesis and ends with a +close parenthesis, then the value between the parentheses is +treated as an element name (which can have any string value) and +the characters before the first open +parenthesis are treated as the name of an array variable. +If \fIname2\fR is NULL and \fIname1\fR does not refer +to an array element +.VE +it means that either the variable is +a scalar or the trace is to be set on the entire array rather +than an individual element (see WHOLE-ARRAY TRACES below for +more information). + + +.SH "ACCESSING VARIABLES DURING TRACES" +.PP +During read, write, and array traces, the +trace procedure can read, write, or unset the traced +variable using \fBTcl_GetVar2\fR, \fBTcl_SetVar2\fR, and +other procedures. +While \fIproc\fR is executing, traces are temporarily disabled +for the variable, so that calls to \fBTcl_GetVar2\fR and +\fBTcl_SetVar2\fR will not cause \fIproc\fR or other trace procedures +to be invoked again. +Disabling only occurs for the variable whose trace procedure +is active; accesses to other variables will still be traced. +However, if a variable is unset during a read or write trace then unset +traces will be invoked. +.PP +During unset traces the variable has already been completely +expunged. +It is possible for the trace procedure to read or write the +variable, but this will be a new version of the variable. +Traces are not disabled during unset traces as they are for +read and write traces, but existing traces have been removed +from the variable before any trace procedures are invoked. +If new traces are set by unset trace procedures, these traces +will be invoked on accesses to the variable by the trace +procedures. + +.SH "CALLBACK TIMING" +.PP +When read tracing has been specified for a variable, the trace +procedure will be invoked whenever the variable's value is +read. This includes \fBset\fR Tcl commands, \fB$\fR-notation +in Tcl commands, and invocations of the \fBTcl_GetVar\fR +and \fBTcl_GetVar2\fR procedures. +\fIProc\fR is invoked just before the variable's value is +returned. +It may modify the value of the variable to affect what +is returned by the traced access. +If it unsets the variable then the access will return an error +just as if the variable never existed. +.PP +When write tracing has been specified for a variable, the +trace procedure will be invoked whenever the variable's value +is modified. This includes \fBset\fR commands, +commands that modify variables as side effects (such as +\fBcatch\fR and \fBscan\fR), and calls to the \fBTcl_SetVar\fR +and \fBTcl_SetVar2\fR procedures). +\fIProc\fR will be invoked after the variable's value has been +modified, but before the new value of the variable has been +returned. +It may modify the value of the variable to override the change +and to determine the value actually returned by the traced +access. +If it deletes the variable then the traced access will return +an empty string. +.PP +When array tracing has been specified, the trace procedure +will be invoked at the beginning of the array command implementation, +before any of the operations like get, set, or names have been invoked. +The trace procedure can modify the array elements with \fBTcl_SetVar\fR +and \fBTcl_SetVar2\fR. +.PP +When unset tracing has been specified, the trace procedure +will be invoked whenever the variable is destroyed. +The traces will be called after the variable has been +completely unset. + +.SH "WHOLE-ARRAY TRACES" +.PP +If a call to \fBTcl_TraceVar\fR or \fBTcl_TraceVar2\fR specifies +the name of an array variable without an index into the array, +then the trace will be set on the array as a whole. +This means that \fIproc\fR will be invoked whenever any +element of the array is accessed in the ways specified by +\fIflags\fR. +When an array is unset, a whole-array trace will be invoked +just once, with \fIname1\fR equal to the name of the array +and \fIname2\fR NULL; it will not be invoked once for each +element. + +.SH "MULTIPLE TRACES" +.PP +It is possible for multiple traces to exist on the same variable. +When this happens, all of the trace procedures will be invoked on each +access, in order from most-recently-created to least-recently-created. +When there exist whole-array traces for an array as well as +traces on individual elements, the whole-array traces are invoked +before the individual-element traces. +If a read or write trace unsets the variable then all of the unset +traces will be invoked but the remainder of the read and write traces +will be skipped. + +.SH "ERROR RETURNS" +.PP +Under normal conditions trace procedures should return NULL, indicating +successful completion. +If \fIproc\fR returns a non-NULL value it signifies that an +error occurred. +The return value must be a pointer to a static character string +containing an error message. +If a trace procedure returns an error, no further traces are +invoked for the access and the traced access aborts with the +given message. +Trace procedures can use this facility to make variables +read-only, for example (but note that the value of the variable +will already have been modified before the trace procedure is +called, so the trace procedure will have to restore the correct +value). +.PP +The return value from \fIproc\fR is only used during read and +write tracing. +During unset traces, the return value is ignored and all relevant +trace procedures will always be invoked. + +.SH "RESTRICTIONS" +.PP +A trace procedure can be called at any time, even when there +is a partially-formed result in the interpreter's result area. If +the trace procedure does anything that could damage this result (such +as calling \fBTcl_Eval\fR) then it must save the original values of +the interpreter's \fBresult\fR and \fBfreeProc\fR fields and restore +them before it returns. + +.SH "UNDEFINED VARIABLES" +.PP +It is legal to set a trace on an undefined variable. +The variable will still appear to be undefined until the +first time its value is set. +If an undefined variable is traced and then unset, the unset will fail +with an error (``no such variable''), but the trace +procedure will still be invoked. + +.SH "TCL_TRACE_DESTROYED FLAG" +.PP +In an unset callback to \fIproc\fR, the TCL_TRACE_DESTROYED bit +is set in \fIflags\fR if the trace is being removed as part +of the deletion. +Traces on a variable are always removed whenever the variable +is deleted; the only time TCL_TRACE_DESTROYED isn't set is for +a whole-array trace invoked when only a single element of an +array is unset. + +.SH "TCL_INTERP_DESTROYED" +.PP +When an interpreter is destroyed, unset traces are called for +all of its variables. +The TCL_INTERP_DESTROYED bit will be set in the \fIflags\fR +argument passed to the trace procedures. +Trace procedures must be extremely careful in what they do if +the TCL_INTERP_DESTROYED bit is set. +It is not safe for the procedures to invoke any Tcl procedures +on the interpreter, since its state is partially deleted. +All that trace procedures should do under these circumstances is +to clean up and free their own internal data structures. + +.SH BUGS +.PP +Tcl doesn't do any error checking to prevent trace procedures +from misusing the interpreter during traces with TCL_INTERP_DESTROYED +set. +.PP +Array traces are not yet integrated with the Tcl "info exists" command, +nor is there Tcl-level access to array traces. + +.SH KEYWORDS +clientData, trace, variable diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Translate.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Translate.3 new file mode 100644 index 0000000000000000000000000000000000000000..712c69713ffba3f916f189fbd8da9405c19dd3c4 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Translate.3 @@ -0,0 +1,66 @@ +'\" +'\" Copyright (c) 1989-1993 The Regents of the University of California. +'\" Copyright (c) 1994-1998 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: Translate.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_TranslateFileName 3 8.1 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_TranslateFileName \- convert file name to native form and replace tilde with home directory +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +char * +\fBTcl_TranslateFileName\fR(\fIinterp\fR, \fIname\fR, \fIbufferPtr\fR) +.SH ARGUMENTS +.AS Tcl_DString *bufferPtr +.AP Tcl_Interp *interp in +Interpreter in which to report an error, if any. +.AP char *name in +File name, which may start with a ``~''. +.AP Tcl_DString *bufferPtr in/out +If needed, this dynamic string is used to store the new file name. +At the time of the call it should be uninitialized or free. The +caller must eventually call \fBTcl_DStringFree\fR to free up +anything stored here. +.BE + +.SH DESCRIPTION +.PP +This utility procedure translates a file name to a form suitable for +passing to the local operating system. It converts network names into +native form and does tilde substitution. +.PP +If +\fBTcl_TranslateFileName\fR has to do tilde substitution or translate +the name then it uses +the dynamic string at \fI*bufferPtr\fR to hold the new string it +generates. +After \fBTcl_TranslateFileName\fR returns a non-NULL result, the caller must +eventually invoke \fBTcl_DStringFree\fR to free any information +placed in \fI*bufferPtr\fR. The caller need not know whether or +not \fBTcl_TranslateFileName\fR actually used the string; \fBTcl_TranslateFileName\fR +initializes \fI*bufferPtr\fR even if it doesn't use it, so the call to +\fBTcl_DStringFree\fR will be safe in either case. +.PP +If an error occurs (e.g. because there was no user by the given +name) then NULL is returned and an error message will be left +in the interpreter's result. +When an error occurs, \fBTcl_TranslateFileName\fR +frees the dynamic string itself so that the caller need not call +\fBTcl_DStringFree\fR. +.PP +The caller is responsible for making sure that the interpreter's result +has its default empty value when \fBTcl_TranslateFileName\fR is invoked. + +.SH "SEE ALSO" +filename + +.SH KEYWORDS +file name, home directory, tilde, translate, user diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/UpVar.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/UpVar.3 new file mode 100644 index 0000000000000000000000000000000000000000..5b827a6736330f78ced1367aa2d0161ada22b1a1 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/UpVar.3 @@ -0,0 +1,75 @@ +'\" +'\" Copyright (c) 1994 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: UpVar.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_UpVar 3 7.4 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_UpVar, Tcl_UpVar2 \- link one variable to another +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +int +\fBTcl_UpVar(\fIinterp, frameName, sourceName, destName, flags\fB)\fR +.sp +int +\fBTcl_UpVar2(\fIinterp, frameName, name1, name2, destName, flags\fB)\fR +.SH ARGUMENTS +.AS Tcl_VarTraceProc prevClientData +.AP Tcl_Interp *interp in +Interpreter containing variables; also used for error reporting. +.AP char *frameName in +Identifies the stack frame containing source variable. +May have any of the forms accepted by +the \fBupvar\fR command, such as \fB#0\fR or \fB1\fR. +.AP char *sourceName in +Name of source variable, in the frame given by \fIframeName\fR. +May refer to a scalar variable or to an array variable with a +parenthesized index. +.AP char *destName in +Name of destination variable, which is to be linked to source +variable so that references to \fIdestName\fR +refer to the other variable. Must not currently exist except as +an upvar-ed variable. +.AP int flags in +Either TCL_GLOBAL_ONLY or 0; if non-zero, then \fIdestName\fR is +a global variable; otherwise it is a local to the current procedure +(or global if no procedure is active). +.AP char *name1 in +First part of source variable's name (scalar name, or name of array +without array index). +.AP char *name2 in +If source variable is an element of an array, gives the index of the element. +For scalar source variables, is NULL. +.BE + +.SH DESCRIPTION +.PP +\fBTcl_UpVar\fR and \fBTcl_UpVar2\fR provide the same functionality +as the \fBupvar\fR command: they make a link from a source variable +to a destination variable, so that references to the destination are +passed transparently through to the source. +The name of the source variable may be specified either as a single +string such as \fBxyx\fR or \fBa(24)\fR (by calling \fBTcl_UpVar\fR) +or in two parts where the array name has been separated from the +element name (by calling \fBTcl_UpVar2\fR). +The destination variable name is specified in a single string; it +may not be an array element. +.PP +Both procedures return either TCL_OK or TCL_ERROR, and they +leave an error message in the interpreter's result if an error occurs. +.PP +As with the \fBupvar\fR command, the source variable need not exist; +if it does exist, unsetting it later does not destroy the link. The +destination variable may exist at the time of the call, but if so +it must exist as a linked variable. + +.SH KEYWORDS +linked variable, upvar, variable diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Utf.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Utf.3 new file mode 100644 index 0000000000000000000000000000000000000000..13a6b9e1799d78319a4f947a44df89fe32ff972d --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/Utf.3 @@ -0,0 +1,232 @@ +'\" +'\" Copyright (c) 1997 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: Utf.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Utf 3 "8.1" Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_UniChar, Tcl_UniCharToUtf, Tcl_UtfToUniChar, Tcl_UniCharToUtfDString, Tcl_UtfToUniCharDString, Tcl_UniCharLen, Tcl_UniCharNcmp, Tcl_UtfCharComplete, Tcl_NumUtfChars, Tcl_UtfFindFirst, Tcl_UtfFindLast, Tcl_UtfNext, Tcl_UtfPrev, Tcl_UniCharAtIndex, Tcl_UtfAtIndex, Tcl_UtfBackslash \- routines for manipulating UTF-8 strings. +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +typedef ... Tcl_UniChar; +.sp +int +\fBTcl_UniCharToUtf\fR(\fIch, buf\fR) +.sp +int +\fBTcl_UtfToUniChar\fR(\fIsrc, chPtr\fR) +.sp +char * +\fBTcl_UniCharToUtfDString\fR(\fIuniStr, numChars, dstPtr\fR) +.sp +Tcl_UniChar * +\fBTcl_UtfToUniCharDString\fR(\fIsrc, len, dstPtr\fR) +.sp +int +\fBTcl_UniCharLen\fR(\fIuniStr\fR) +.sp +int +\fBTcl_UniCharNcmp\fR(\fIuniStr, uniStr, num\fR) +.sp +int +\fBTcl_UtfNcmp\fR(\fIsrc, src, num\fR) +.sp +int +\fBTcl_UtfNcasecmp\fR(\fIsrc, src, num\fR) +.sp +int +\fBTcl_UtfCharComplete\fR(\fIsrc, len\fR) +.sp +int +\fBTcl_NumUtfChars\fR(\fIsrc, len\fR) +.sp +char * +\fBTcl_UtfFindFirst\fR(\fIsrc, ch\fR) +.sp +char * +\fBTcl_UtfFindLast\fR(\fIsrc, ch\fR) +.sp +char * +\fBTcl_UtfNext\fR(\fIsrc\fR) +.sp +char * +\fBTcl_UtfPrev\fR(\fIsrc, start\fR) +.sp +Tcl_UniChar +\fBTcl_UniCharAtIndex\fR(\fIsrc, index\fR) +.sp +char * +\fBTcl_UtfAtIndex\fR(\fIsrc, index\fR) +.sp +int +\fBTcl_UtfBackslash\fR(\fIsrc, readPtr, dst\fR) +.SH ARGUMENTS +.AS "CONST Tcl_UniChar" numChars in/out +.AP char *buf out +Buffer in which the UTF-8 representation of the Tcl_UniChar is stored. At most +TCL_UTF_MAX bytes are stored in the buffer. +.AP int ch in +The Tcl_UniChar to be converted or examined. +.AP Tcl_UniChar *chPtr out +Filled with the Tcl_UniChar represented by the head of the UTF-8 string. +.AP "CONST char" *src in +Pointer to a UTF-8 string. +.AP "CONST Tcl_UniChar" *uniStr in +A NULL-terminated Unicode string. +.AP int len in +The length of the UTF-8 string in bytes (not UTF-8 characters). If +negative, all bytes up to the first null byte are used. +.AP int numChars in +The length of the Unicode string in characters. Must be greater than or +equal to 0. +.AP "Tcl_DString" *dstPtr in/out +A pointer to a previously-initialized \fBTcl_DString\fR. +.AP "unsigned long" num in +The number of characters to compare. +.AP "CONST char" *start in +Pointer to the beginning of a UTF-8 string. +.AP int index in +The index of a character (not byte) in the UTF-8 string. +.AP int *readPtr out +If non-NULL, filled with the number of bytes in the backslash sequence, +including the backslash character. +.AP char *dst out +Buffer in which the bytes represented by the backslash sequence are stored. +At most TCL_UTF_MAX bytes are stored in the buffer. +.BE + +.SH DESCRIPTION +.PP +These routines convert between UTF-8 strings and Tcl_UniChars. A +Tcl_UniChar is a Unicode character represented as an unsigned, fixed-size +quantity. A UTF-8 character is a Unicode character represented as +a varying-length sequence of up to TCL_UTF_MAX bytes. A multibyte UTF-8 +sequence consists of a lead byte followed by some number of trail bytes. +.PP +\fBTCL_UTF_MAX\fR is the maximum number of bytes that it takes to +represent one Unicode character in the UTF-8 representation. +.PP +\fBTcl_UniCharToUtf\fR stores the Tcl_UniChar \fIch\fR as a UTF-8 string +in starting at \fIbuf\fR. The return value is the number of bytes stored +in \fIbuf\fR. +.PP +\fBTcl_UtfToUniChar\fR reads one UTF-8 character starting at \fIsrc\fR +and stores it as a Tcl_UniChar in \fI*chPtr\fR. The return value is the +number of bytes read from \fIsrc\fR.. The caller must ensure that the +source buffer is long enough such that this routine does not run off the +end and dereference non-existent or random memory; if the source buffer +is known to be null terminated, this will not happen. If the input is +not in proper UTF-8 format, \fBTcl_UtfToUniChar\fR will store the first +byte of \fIsrc\fR in \fI*chPtr\fR as a Tcl_UniChar between 0x0000 and +0x00ff and return 1. +.PP +\fBTcl_UniCharToUtfDString\fR converts the given Unicode string +to UTF-8, storing the result in a previously-initialized \fBTcl_DString\fR. +You must specify the length of the given Unicode string. +The return value is a pointer to the UTF-8 representation of the +Unicode string. Storage for the return value is appended to the +end of the \fBTcl_DString\fR. +.PP +\fBTcl_UtfToUniCharDString\fR coverts the given UTF-8 string to Unicode, +storing the result in the previously-initialized \fBTcl_Dstring\fR. +you may either specify the length of the given UTF-8 string or "-1", +in which case \fBTcl_UtfToUniCharDString\fR uses \fBstrlen\fR to +calculate the length. The return value is a pointer to the Unicode +representation of the UTF-8 string. Storage for the return value +is appended to the end of the \fBTcl_DString\fR. The Unicode string +is terminated with a Unicode NULL character. +.PP +\fBTcl_UniCharLen\fR corresponds to \fBstrlen\fR for Unicode +characters. It accepts a NULL-terminated Unicode string and returns +the number of Unicode characters (not bytes) in that string. +.PP +\fBTcl_UniCharNcmp\fR corresponds to \fBstrncmp\fR for Unicode +characters. It accepts two NULL-terminated Unicode strings +and the number of characters to compare. (Both strings are +assumed to be at least \fIlen\fR characters long.) +\fBTcl_UniCharNcmp\fR compares the two strings character-by-character +according to the Unicode character ordering. It returns an integer +greater than, equal to, +or less than 0 if the first string is greater than, equal to, or +less than the second string respectively. +.PP +\fBTcl_UtfNcmp\fR corresponds to \fBstrncmp\fR for UTF-8 strings. It +accepts two NULL-terminated UTF-8 strings and the number of characters +to compare. (Both strings are assumed to be at least \fIlen\fR +characters long.) \fBTcl_UtfNcmp\fR compares the two strings +character-by-character according to the Unicode character ordering. +It returns an integer greater than, equal to, or less than 0 if the +first string is greater than, equal to, or less than the second string +respectively. +.PP +\fBTcl_UtfNcasecmp\fR corresponds to \fBstrncasecmp\fR for UTF-8 +strings. It is similar to \fBTcl_UtfNcmp\fR except comparisons ignore +differences in case when comparing upper, lower or title case +characters. +.PP +\fBTcl_UtfCharComplete\fR returns 1 if the source UTF-8 string \fIsrc\fR +of length \fIlen\fR bytes is long enough to be decoded by +\fBTcl_UtfToUniChar\fR, or 0 otherwise. This function does not guarantee +that the UTF-8 string is properly formed. This routine is used by +procedures that are operating on a byte at a time and need to know if a +full Tcl_UniChar has been seen. +.PP +\fBTcl_NumUtfChars\fR corresponds to \fBstrlen\fR for UTF-8 strings. It +returns the number of Tcl_UniChars that are represented by the UTF-8 string +\fIsrc\fR. The length of the source string is \fIlen\fR bytes. If the +length is negative, all bytes up to the first NULL byte are used. +.PP +\fBTcl_UtfFindFirst\fR corresponds to \fBstrchr\fR for UTF-8 strings. It +returns a pointer to the first occurance of the Tcl_UniChar \fIch\fR +in the NULL-terminated UTF-8 string \fIsrc\fR. The NULL terminator is +considered part of the UTF-8 string. +.PP +\fBTcl_UtfFindLast\fR corresponds to \fBstrrchr\fR for UTF-8 strings. It +returns a pointer to the last occurance of the Tcl_UniChar \fIch\fR +in the NULL terminated UTF-8 string \fIsrc\fR. The NULL terminator is +considered part of the UTF-8 string. +.PP +Given \fIsrc\fR, a pointer to some location in a UTF-8 string, +\fBTcl_UtfNext\fR returns a pointer to the next UTF-8 character in the +string. The caller must not ask for the next character after the last +character in the string. +.PP +Given \fIsrc\fR, a pointer to some location in a UTF-8 string, +\fBTcl_UtfPrev\fR returns a pointer to the previous UTF-8 character in the +string. This function will not back up to a position before \fIstart\fR, +the start of the UTF-8 string. If \fIsrc\fR was already at \fIstart\fR, the +return value will be \fIstart\fR. +.PP +\fBTcl_UniCharAtIndex\fR corresponds to a C string array dereference or the +Pascal Ord() function. It returns the Tcl_UniChar represented at the +specified character (not byte) \fIindex\fR in the UTF-8 string +\fIsrc\fR. The source string must contain at least \fIindex\fR +characters. Behavior is undefined if a negative \fIindex\fR is given. +.PP +\fBTcl_UtfAtIndex\fR returns a pointer to the specified character (not +byte) \fIindex\fR in the UTF-8 string \fIsrc\fR. The source string must +contain at least \fIindex\fR characters. This is equivalent to calling +\fBTcl_UtfNext\fR \fIindex\fR times. If a negative \fIindex\fR is given, +the return pointer points to the first character in the source string. +.PP +\fBTcl_UtfBackslash\fR is a utility procedure used by several of the Tcl +commands. It parses a backslash sequence and stores the properly formed +UTF-8 character represented by the backslash sequence in the output +buffer \fIdst\fR. At most TCL_UTF_MAX bytes are stored in the buffer. +\fBTcl_UtfBackslash\fR modifies \fI*readPtr\fR to contain the number +of bytes in the backslash sequence, including the backslash character. +The return value is the number of bytes stored in the output buffer. +.PP +See the \fBTcl\fR manual entry for information on the valid backslash +sequences. All of the sequences described in the Tcl manual entry are +supported by \fBTcl_UtfBackslash\fR. + +.SH KEYWORDS +utf, unicode, backslash diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/WrongNumArgs.3 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/WrongNumArgs.3 new file mode 100644 index 0000000000000000000000000000000000000000..ff975d3cdb3912d588615e368c7484d0909e7a7d --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/WrongNumArgs.3 @@ -0,0 +1,78 @@ +'\" +'\" Copyright (c) 1994-1997 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: WrongNumArgs.3,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH Tcl_WrongNumArgs 3 8.0 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_WrongNumArgs \- generate standard error message for wrong number of arguments +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +\fBTcl_WrongNumArgs\fR(\fIinterp, objc, objv, message\fR) +.SH ARGUMENTS +.AS Tcl_Interp "*CONST objv[]" +.AP Tcl_Interp interp in +Interpreter in which error will be reported: error message gets stored +in its result object. +.AP int objc in +Number of leading arguments from \fIobjv\fR to include in error +message. +.AP Tcl_Obj "*CONST\ objv[]" in +Arguments to command that had the wrong number of arguments. +.AP char *message in +Additional error information to print after leading arguments +from \fIobjv\fR. This typically gives the acceptable syntax +of the command. This argument may be NULL. +.BE + +.SH DESCRIPTION +.PP +\fBTcl_WrongNumArgs\fR is a utility procedure that is invoked by +command procedures when they discover that they have received the +wrong number of arguments. \fBTcl_WrongNumArgs\fR generates a +standard error message and stores it in the result object of +\fIinterp\fR. The message includes the \fIobjc\fR initial +elements of \fIobjv\fR plus \fImessage\fR. For example, if +\fIobjv\fR consists of the values \fBfoo\fR and \fBbar\fR, +\fIobjc\fR is 1, and \fImessage\fR is ``\fBfileName count\fR'' +then \fIinterp\fR's result object will be set to the following +string: +.CS +wrong # args: should be "foo fileName count" +.CE +If \fIobjc\fR is 2, the result will be set to the following string: +.CS +wrong # args: should be "foo bar fileName count" +.CE +\fIObjc\fR is usually 1, but may be 2 or more for commands like +\fBstring\fR and the Tk widget commands, which use the first argument +as a subcommand. +.PP +Some of the objects in the \fIobjv\fR array may be abbreviations for +a subcommand. The command +\fBTcl_GetIndexFromObj\fR will convert the abbreviated string object +into an \fIindexObject\fR. If an error occurs in the parsing of the +subcommand we would like to use the full subcommand name rather than +the abbreviation. If the \fBTcl_WrongNumArgs\fR command finds any +\fIindexObjects\fR in the \fIobjv\fR array it will use the full subcommand +name in the error message instead of the abbreviated name that was +origionally passed in. Using the above example, lets assume that +\fIbar\fR is actually an abbreviation for \fIbarfly\fR and the object +is now an indexObject becasue it was passed to +\fBTcl_GetIndexFromObj\fR. In this case the error message would be: +.CS +wrong # args: should be "foo barfly fileName count" +.CE + +.SH "SEE ALSO" +Tcl_GetIndexFromObj + +.SH KEYWORDS +command, error message, wrong number of arguments diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/after.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/after.n new file mode 100644 index 0000000000000000000000000000000000000000..eb82b0b53e61d9ed4ef7bd5d1136614ac8cc42eb --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/after.n @@ -0,0 +1,109 @@ +'\" +'\" Copyright (c) 1990-1994 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: after.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH after n 7.5 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +after \- Execute a command after a time delay +.SH SYNOPSIS +\fBafter \fIms\fR +.sp +\fBafter \fIms \fR?\fIscript script script ...\fR? +.sp +\fBafter cancel \fIid\fR +.sp +\fBafter cancel \fIscript script script ...\fR +.sp +\fBafter idle \fR?\fIscript script script ...\fR? +.sp +\fBafter info \fR?\fIid\fR? +.BE + +.SH DESCRIPTION +.PP +This command is used to delay execution of the program or to execute +a command in background sometime in the future. It has several forms, +depending on the first argument to the command: +.TP +\fBafter \fIms\fR +\fIMs\fR must be an integer giving a time in milliseconds. +The command sleeps for \fIms\fR milliseconds and then returns. +While the command is sleeping the application does not respond to +events. +.TP +\fBafter \fIms \fR?\fIscript script script ...\fR? +In this form the command returns immediately, but it arranges +for a Tcl command to be executed \fIms\fR milliseconds later as an +event handler. +The command will be executed exactly once, at the given time. +The delayed command is formed by concatenating all the \fIscript\fR +arguments in the same fashion as the \fBconcat\fR command. +The command will be executed at global level (outside the context +of any Tcl procedure). +If an error occurs while executing the delayed command then the +\fBbgerror\fR mechanism is used to report the error. +The \fBafter\fR command returns an identifier that can be used +to cancel the delayed command using \fBafter cancel\fR. +.TP +\fBafter cancel \fIid\fR +Cancels the execution of a delayed command that +was previously scheduled. +\fIId\fR indicates which command should be canceled; it must have +been the return value from a previous \fBafter\fR command. +If the command given by \fIid\fR has already been executed then +the \fBafter cancel\fR command has no effect. +.TP +\fBafter cancel \fIscript script ...\fR +This command also cancels the execution of a delayed command. +The \fIscript\fR arguments are concatenated together with space +separators (just as in the \fBconcat\fR command). +If there is a pending command that matches the string, it is +cancelled and will never be executed; if no such command is +currently pending then the \fBafter cancel\fR command has no effect. +.TP +\fBafter idle \fIscript \fR?\fIscript script ...\fR? +Concatenates the \fIscript\fR arguments together with space +separators (just as in the \fBconcat\fR command), and arranges +for the resulting script to be evaluated later as an idle callback. +The script will be run exactly once, the next time the event +loop is entered and there are no events to process. +The command returns an identifier that can be used +to cancel the delayed command using \fBafter cancel\fR. +If an error occurs while executing the script then the +\fBbgerror\fR mechanism is used to report the error. +.TP +\fBafter info \fR?\fIid\fR? +This command returns information about existing event handlers. +If no \fIid\fR argument is supplied, the command returns +a list of the identifiers for all existing +event handlers created by the \fBafter\fR command for this +interpreter. +If \fIid\fR is supplied, it specifies an existing handler; +\fIid\fR must have been the return value from some previous call +to \fBafter\fR and it must not have triggered yet or been cancelled. +In this case the command returns a list with two elements. +The first element of the list is the script associated +with \fIid\fR, and the second element is either +\fBidle\fR or \fBtimer\fR to indicate what kind of event +handler it is. +.LP +The \fBafter \fIms\fR and \fBafter idle\fR forms of the command +assume that the application is event driven: the delayed commands +will not be executed unless the application enters the event loop. +In applications that are not normally event-driven, such as +\fBtclsh\fR, the event loop can be entered with the \fBvwait\fR +and \fBupdate\fR commands. + +.SH "SEE ALSO" +bgerror(n), concat(n), update(n), vwait(n) + +.SH KEYWORDS +cancel, delay, idle callback, sleep, time diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/append.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/append.n new file mode 100644 index 0000000000000000000000000000000000000000..2947c00342c7096d342fe12288eba8427c638649 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/append.n @@ -0,0 +1,35 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: append.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH append n "" Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +append \- Append to variable +.SH SYNOPSIS +\fBappend \fIvarName \fR?\fIvalue value value ...\fR? +.BE + +.SH DESCRIPTION +.PP +Append all of the \fIvalue\fR arguments to the current value +of variable \fIvarName\fR. If \fIvarName\fR doesn't exist, +it is given a value equal to the concatenation of all the +\fIvalue\fR arguments. +This command provides an efficient way to build up long +variables incrementally. +For example, ``\fBappend a $b\fR'' is much more efficient than +``\fBset a $a$b\fR'' if \fB$a\fR is long. + +.SH "SEE ALSO" +concat(n), lappend(n) + +.SH KEYWORDS +append, variable diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/array.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/array.n new file mode 100644 index 0000000000000000000000000000000000000000..ac736e455bcd89c66e0316d4d459d2db0021b73a --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/array.n @@ -0,0 +1,125 @@ +'\" +'\" Copyright (c) 1993-1994 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: array.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH array n 8.3 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +array \- Manipulate array variables +.SH SYNOPSIS +\fBarray \fIoption arrayName\fR ?\fIarg arg ...\fR? +.BE + +.SH DESCRIPTION +.PP +This command performs one of several operations on the +variable given by \fIarrayName\fR. +Unless otherwise specified for individual commands below, +\fIarrayName\fR must be the name of an existing array variable. +The \fIoption\fR argument determines what action is carried +out by the command. +The legal \fIoptions\fR (which may be abbreviated) are: +.TP +\fBarray anymore \fIarrayName searchId\fR +Returns 1 if there are any more elements left to be processed +in an array search, 0 if all elements have already been +returned. +\fISearchId\fR indicates which search on \fIarrayName\fR to +check, and must have been the return value from a previous +invocation of \fBarray startsearch\fR. +This option is particularly useful if an array has an element +with an empty name, since the return value from +\fBarray nextelement\fR won't indicate whether the search +has been completed. +.TP +\fBarray donesearch \fIarrayName searchId\fR +This command terminates an array search and destroys all the +state associated with that search. \fISearchId\fR indicates +which search on \fIarrayName\fR to destroy, and must have +been the return value from a previous invocation of +\fBarray startsearch\fR. Returns an empty string. +.TP +\fBarray exists \fIarrayName\fR +Returns 1 if \fIarrayName\fR is an array variable, 0 if there +is no variable by that name or if it is a scalar variable. +.TP +\fBarray get \fIarrayName\fR ?\fIpattern\fR? +Returns a list containing pairs of elements. The first +element in each pair is the name of an element in \fIarrayName\fR +and the second element of each pair is the value of the +array element. The order of the pairs is undefined. +If \fIpattern\fR is not specified, then all of the elements of the +array are included in the result. +If \fIpattern\fR is specified, then only those elements whose names +match \fIpattern\fR (using the matching rules of +\fBstring match\fR) are included. +If \fIarrayName\fR isn't the name of an array variable, or if +the array contains no elements, then an empty list is returned. +.TP +\fBarray names \fIarrayName\fR ?\fIpattern\fR? +Returns a list containing the names of all of the elements in +the array that match \fIpattern\fR (using the matching +rules of \fBstring match\fR). +If \fIpattern\fR is omitted then the command returns all of +the element names in the array. +If there are no (matching) elements in the array, or if \fIarrayName\fR +isn't the name of an array variable, then an empty string is +returned. +.TP +\fBarray nextelement \fIarrayName searchId\fR +Returns the name of the next element in \fIarrayName\fR, or +an empty string if all elements of \fIarrayName\fR have +already been returned in this search. The \fIsearchId\fR +argument identifies the search, and must have +been the return value of an \fBarray startsearch\fR command. +Warning: if elements are added to or deleted from the array, +then all searches are automatically terminated just as if +\fBarray donesearch\fR had been invoked; this will cause +\fBarray nextelement\fR operations to fail for those searches. +.TP +\fBarray set \fIarrayName list\fR +Sets the values of one or more elements in \fIarrayName\fR. +\fIlist\fR must have a form like that returned by \fBarray get\fR, +consisting of an even number of elements. +Each odd-numbered element in \fIlist\fR is treated as an element +name within \fIarrayName\fR, and the following element in \fIlist\fR +is used as a new value for that array element. +If the variable \fIarrayName\fR does not already exist +and \fIlist\fR is empty, +\fIarrayName\fR is created with an empty array value. +.TP +\fBarray size \fIarrayName\fR +Returns a decimal string giving the number of elements in the +array. +If \fIarrayName\fR isn't the name of an array then 0 is returned. +.TP +\fBarray startsearch \fIarrayName\fR +This command initializes an element-by-element search through the +array given by \fIarrayName\fR, such that invocations of the +\fBarray nextelement\fR command will return the names of the +individual elements in the array. +When the search has been completed, the \fBarray donesearch\fR +command should be invoked. +The return value is a +search identifier that must be used in \fBarray nextelement\fR +and \fBarray donesearch\fR commands; it allows multiple +searches to be underway simultaneously for the same array. +.VS 8.3 +.TP +\fBarray unset \fIarrayName\fR ?\fIpattern\fR? +Unsets all of the elements in the array that match \fIpattern\fR (using the +matching rules of \fBstring match\fR). If \fIarrayName\fR isn't the name +of an array variable or there are no matching elements in the array, then +an empty string is returned. If \fIpattern\fR is omitted and is it an +array variable, then the command unsets the entire array. +.VE 8.3 + +.SH KEYWORDS +array, element names, search diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/bgerror.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/bgerror.n new file mode 100644 index 0000000000000000000000000000000000000000..3384fc8d3e25c303de56329a47e53e05f874f614 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/bgerror.n @@ -0,0 +1,79 @@ +'\" +'\" Copyright (c) 1990-1994 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: bgerror.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH bgerror n 7.5 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +bgerror \- Command invoked to process background errors +.SH SYNOPSIS +\fBbgerror \fImessage\fR +.BE + +.SH DESCRIPTION +.PP +The \fBbgerror\fR command doesn't exist as built-in part of Tcl. Instead, +individual applications or users can define a \fBbgerror\fR +command (e.g. as a Tcl procedure) if they wish to handle background +errors. +.PP +A background error is one that occurs in an event handler or some +other command that didn't originate with the application. +For example, if an error occurs while executing a command specified +with the \fBafter\fR command, then it is a background error. +For a non-background error, the error can simply be returned up +through nested Tcl command evaluations until it reaches the top-level +code in the application; then the application can report the error +in whatever way it wishes. When a background error occurs, the +unwinding ends in the Tcl library and there is no obvious way for Tcl +to report the error. +.PP +When Tcl detects a background error, it saves information about the +error and invokes the \fBbgerror\fR command later as an idle event +handler. Before invoking \fBbgerror\fR, Tcl restores the +\fBerrorInfo\fR and \fBerrorCode\fR variables to their values at the +time the error occurred, then it invokes \fBbgerror\fR with the error +message as its only argument. Tcl assumes that the application has +implemented the \fBbgerror\fR command, and that the command will +report the error in a way that makes sense for the application. Tcl +will ignore any result returned by the \fBbgerror\fR command as long +as no error is generated. +.PP +If another Tcl error occurs within the \fBbgerror\fR command (for +example, because no \fBbgerror\fR command has been defined) then Tcl +reports the error itself by writing a message to stderr. +.PP +If several background errors accumulate before \fBbgerror\fR is +invoked to process them, \fBbgerror\fR will be invoked once for each +error, in the order they occurred. However, if \fBbgerror\fR returns +with a break exception, then any remaining errors are skipped without +calling \fBbgerror\fR. +.PP +Tcl has no default implementation for \fBbgerror\fR. However, in +applications using Tk there is a default \fBbgerror\fR procedure which +posts a dialog box containing the error message and offers the user a +chance to see a stack trace showing where the error occurred. In +addition to allowing the user to view the stack trace, the dialog +provides an additional application configurable button which may be +used, for example, to save the stack trace to a file. By default, +this is the behavior associated with that button. This behavior can +be redefined by setting the option database values +\fB*ErrorDialog.function.text\fR, to specify the caption for the +function button, and \fB*ErrorDialog.function.command\fR, to specify +the command to be run. The text of the stack trace is appended to the +command when it is evaluated. If either of these options is set to +the empty string, then the additional button will not be displayed in +the dialog. + +.SH "SEE ALSO" +after(n), tclvars(n) + +.SH KEYWORDS +background error, reporting diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/binary.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/binary.n new file mode 100644 index 0000000000000000000000000000000000000000..b9253bf19fbbf361feae2e5a3f28f28a78f5a5d6 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/binary.n @@ -0,0 +1,548 @@ +'\" +'\" Copyright (c) 1997 by Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: binary.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH binary n 8.0 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +binary \- Insert and extract fields from binary strings +.SH SYNOPSIS +\fBbinary format \fIformatString \fR?\fIarg arg ...\fR? +.br +\fBbinary scan \fIstring formatString \fR?\fIvarName varName ...\fR? +.BE + +.SH DESCRIPTION +.PP +This command provides facilities for manipulating binary data. The +first form, \fBbinary format\fR, creates a binary string from normal +Tcl values. For example, given the values 16 and 22, on a 32 bit +architecture, it might produce an 8-byte binary string consisting of +two 4-byte integers, one for each of the numbers. The second form of +the command, \fBbinary scan\fR, does the opposite: it extracts data +from a binary string and returns it as ordinary Tcl string values. + +.SH "BINARY FORMAT" +.PP +The \fBbinary format\fR command generates a binary string whose layout +is specified by the \fIformatString\fR and whose contents come from +the additional arguments. The resulting binary value is returned. +.PP +The \fIformatString\fR consists of a sequence of zero or more field +specifiers separated by zero or more spaces. Each field specifier is +a single type character followed by an optional numeric \fIcount\fR. +Most field specifiers consume one argument to obtain the value to be +formatted. The type character specifies how the value is to be +formatted. The \fIcount\fR typically indicates how many items of the +specified type are taken from the value. If present, the \fIcount\fR +is a non-negative decimal integer or \fB*\fR, which normally indicates +that all of the items in the value are to be used. If the number of +arguments does not match the number of fields in the format string +that consume arguments, then an error is generated. +.PP +Each type-count pair moves an imaginary cursor through the binary +data, storing bytes at the current position and advancing the cursor +to just after the last byte stored. The cursor is initially at +position 0 at the beginning of the data. The type may be any one of +the following characters: +.IP \fBa\fR 5 +Stores a character string of length \fIcount\fR in the output string. +If \fIarg\fR has fewer than \fIcount\fR bytes, then additional zero +bytes are used to pad out the field. If \fIarg\fR is longer than the +specified length, the extra characters will be ignored. If +\fIcount\fR is \fB*\fR, then all of the bytes in \fIarg\fR will be +formatted. If \fIcount\fR is omitted, then one character will be +formatted. For example, +.RS +.CS +\fBbinary format a7a*a alpha bravo charlie\fR +.CE +will return a string equivalent to \fBalpha\\000\\000bravoc\fR. +.RE +.IP \fBA\fR 5 +This form is the same as \fBa\fR except that spaces are used for +padding instead of nulls. For example, +.RS +.CS +\fBbinary format A6A*A alpha bravo charlie\fR +.CE +will return \fBalpha bravoc\fR. +.RE +.IP \fBb\fR 5 +Stores a string of \fIcount\fR binary digits in low-to-high order +within each byte in the output string. \fIArg\fR must contain a +sequence of \fB1\fR and \fB0\fR characters. The resulting bytes are +emitted in first to last order with the bits being formatted in +low-to-high order within each byte. If \fIarg\fR has fewer than +\fIcount\fR digits, then zeros will be used for the remaining bits. +If \fIarg\fR has more than the specified number of digits, the extra +digits will be ignored. If \fIcount\fR is \fB*\fR, then all of the +digits in \fIarg\fR will be formatted. If \fIcount\fR is omitted, +then one digit will be formatted. If the number of bits formatted +does not end at a byte boundary, the remaining bits of the last byte +will be zeros. For example, +.RS +.CS +\fBbinary format b5b* 11100 111000011010\fR +.CE +will return a string equivalent to \fB\\x07\\x87\\x05\fR. +.RE +.IP \fBB\fR 5 +This form is the same as \fBb\fR except that the bits are stored in +high-to-low order within each byte. For example, +.RS +.CS +\fBbinary format B5B* 11100 111000011010\fR +.CE +will return a string equivalent to \fB\\xe0\\xe1\\xa0\fR. +.RE +.IP \fBh\fR 5 +Stores a string of \fIcount\fR hexadecimal digits in low-to-high +within each byte in the output string. \fIArg\fR must contain a +sequence of characters in the set ``0123456789abcdefABCDEF''. The +resulting bytes are emitted in first to last order with the hex digits +being formatted in low-to-high order within each byte. If \fIarg\fR +has fewer than \fIcount\fR digits, then zeros will be used for the +remaining digits. If \fIarg\fR has more than the specified number of +digits, the extra digits will be ignored. If \fIcount\fR is +\fB*\fR, then all of the digits in \fIarg\fR will be formatted. If +\fIcount\fR is omitted, then one digit will be formatted. If the +number of digits formatted does not end at a byte boundary, the +remaining bits of the last byte will be zeros. For example, +.RS +.CS +\fBbinary format h3h* AB def\fR +.CE +will return a string equivalent to \fB\\xba\\x00\\xed\\x0f\fR. +.RE +.IP \fBH\fR 5 +This form is the same as \fBh\fR except that the digits are stored in +high-to-low order within each byte. For example, +.RS +.CS +\fBbinary format H3H* ab DEF\fR +.CE +will return a string equivalent to \fB\\xab\\x00\\xde\\xf0\fR. +.RE +.IP \fBc\fR 5 +Stores one or more 8-bit integer values in the output string. If no +\fIcount\fR is specified, then \fIarg\fR must consist of an integer +value; otherwise \fIarg\fR must consist of a list containing at least +\fIcount\fR integer elements. The low-order 8 bits of each integer +are stored as a one-byte value at the cursor position. If \fIcount\fR +is \fB*\fR, then all of the integers in the list are formatted. If +the number of elements in the list is fewer than \fIcount\fR, then an +error is generated. If the number of elements in the list is greater +than \fIcount\fR, then the extra elements are ignored. For example, +.RS +.CS +\fBbinary format c3cc* {3 -3 128 1} 260 {2 5}\fR +.CE +will return a string equivalent to +\fB\\x03\\xfd\\x80\\x04\\x02\\x05\fR, whereas +.CS +\fBbinary format c {2 5}\fR +.CE +will generate an error. +.RE +.IP \fBs\fR 5 +This form is the same as \fBc\fR except that it stores one or more +16-bit integers in little-endian byte order in the output string. The +low-order 16-bits of each integer are stored as a two-byte value at +the cursor position with the least significant byte stored first. For +example, +.RS +.CS +\fBbinary format s3 {3 -3 258 1}\fR +.CE +will return a string equivalent to +\fB\\x03\\x00\\xfd\\xff\\x02\\x01\fR. +.RE +.IP \fBS\fR 5 +This form is the same as \fBs\fR except that it stores one or more +16-bit integers in big-endian byte order in the output string. For +example, +.RS +.CS +\fBbinary format S3 {3 -3 258 1}\fR +.CE +will return a string equivalent to +\fB\\x00\\x03\\xff\\xfd\\x01\\x02\fR. +.RE +.IP \fBi\fR 5 +This form is the same as \fBc\fR except that it stores one or more +32-bit integers in little-endian byte order in the output string. The +low-order 32-bits of each integer are stored as a four-byte value at +the cursor position with the least significant byte stored first. For +example, +.RS +.CS +\fBbinary format i3 {3 -3 65536 1}\fR +.CE +will return a string equivalent to +\fB\\x03\\x00\\x00\\x00\\xfd\\xff\\xff\\xff\\x00\\x00\\x01\\x00\fR +.RE +.IP \fBI\fR 5 +This form is the same as \fBi\fR except that it stores one or more one +or more 32-bit integers in big-endian byte order in the output string. +For example, +.RS +.CS +\fBbinary format I3 {3 -3 65536 1}\fR +.CE +will return a string equivalent to +\fB\\x00\\x00\\x00\\x03\\xff\\xff\\xff\\xfd\\x00\\x01\\x00\\x00\fR +.RE +.IP \fBf\fR 5 +This form is the same as \fBc\fR except that it stores one or more one +or more single-precision floating in the machine's native +representation in the output string. This representation is not +portable across architectures, so it should not be used to communicate +floating point numbers across the network. The size of a floating +point number may vary across architectures, so the number of bytes +that are generated may vary. If the value overflows the +machine's native representation, then the value of FLT_MAX +as defined by the system will be used instead. Because Tcl uses +double-precision floating-point numbers internally, there may be some +loss of precision in the conversion to single-precision. For example, +on a Windows system running on an Intel Pentium processor, +.RS +.CS +\fBbinary format f2 {1.6 3.4}\fR +.CE +will return a string equivalent to +\fB\\xcd\\xcc\\xcc\\x3f\\x9a\\x99\\x59\\x40\fR. +.RE +.IP \fBd\fR 5 +This form is the same as \fBf\fR except that it stores one or more one +or more double-precision floating in the machine's native +representation in the output string. For example, on a +Windows system running on an Intel Pentium processor, +.RS +.CS +\fBbinary format d1 {1.6}\fR +.CE +will return a string equivalent to +\fB\\x9a\\x99\\x99\\x99\\x99\\x99\\xf9\\x3f\fR. +.RE +.IP \fBx\fR 5 +Stores \fIcount\fR null bytes in the output string. If \fIcount\fR is +not specified, stores one null byte. If \fIcount\fR is \fB*\fR, +generates an error. This type does not consume an argument. For +example, +.RS +.CS +\fBbinary format a3xa3x2a3 abc def ghi\fR +.CE +will return a string equivalent to \fBabc\\000def\\000\\000ghi\fR. +.RE +.IP \fBX\fR 5 +Moves the cursor back \fIcount\fR bytes in the output string. If +\fIcount\fR is \fB*\fR or is larger than the current cursor position, +then the cursor is positioned at location 0 so that the next byte +stored will be the first byte in the result string. If \fIcount\fR is +omitted then the cursor is moved back one byte. This type does not +consume an argument. For example, +.RS +.CS +\fBbinary format a3X*a3X2a3 abc def ghi\fR +.CE +will return \fBdghi\fR. +.RE +.IP \fB@\fR 5 +Moves the cursor to the absolute location in the output string +specified by \fIcount\fR. Position 0 refers to the first byte in the +output string. If \fIcount\fR refers to a position beyond the last +byte stored so far, then null bytes will be placed in the unitialized +locations and the cursor will be placed at the specified location. If +\fIcount\fR is \fB*\fR, then the cursor is moved to the current end of +the output string. If \fIcount\fR is omitted, then an error will be +generated. This type does not consume an argument. For example, +.RS +.CS +\fBbinary format a5@2a1@*a3@10a1 abcde f ghi j\fR +.CE +will return \fBabfdeghi\\000\\000j\fR. +.RE + +.SH "BINARY SCAN" +.PP +The \fBbinary scan\fR command parses fields from a binary string, +returning the number of conversions performed. \fIString\fR gives the +input to be parsed and \fIformatString\fR indicates how to parse it. +Each \fIvarName\fR gives the name of a variable; when a field is +scanned from \fIstring\fR the result is assigned to the corresponding +variable. +.PP +As with \fBbinary format\fR, the \fIformatString\fR consists of a +sequence of zero or more field specifiers separated by zero or more +spaces. Each field specifier is a single type character followed by +an optional numeric \fIcount\fR. Most field specifiers consume one +argument to obtain the variable into which the scanned values should +be placed. The type character specifies how the binary data is to be +interpreted. The \fIcount\fR typically indicates how many items of +the specified type are taken from the data. If present, the +\fIcount\fR is a non-negative decimal integer or \fB*\fR, which +normally indicates that all of the remaining items in the data are to +be used. If there are not enough bytes left after the current cursor +position to satisfy the current field specifier, then the +corresponding variable is left untouched and \fBbinary scan\fR returns +immediately with the number of variables that were set. If there are +not enough arguments for all of the fields in the format string that +consume arguments, then an error is generated. +.PP +It is \fBimportant\fR to note that the \fBc\fR, \fBs\fR, and \fBS\fR +(and \fBi\fR and \fBI\fR on 64bit systems) will be scanned into +long data size values. In doing this, values that have their high +bit set (0x80 for chars, 0x8000 for shorts, 0x80000000 for ints), +will be sign extended. Thus the following will occur: +.CS +\fBset signShort [binary format s1 0x8000]\fR +\fBbinary scan $signShort s1 val; \fI# val == 0xFFFF8000\fR +.CE +If you want to produce an unsigned value, then you can mask the return +value to the desired size. For example, to produce an unsigned short +value: +.CS +\fBset val [expr {$val & 0xFFFF}]; \fI# val == 0x8000\fR +.CE +.PP +Each type-count pair moves an imaginary cursor through the binary data, +reading bytes from the current position. The cursor is initially +at position 0 at the beginning of the data. The type may be any one of +the following characters: +.IP \fBa\fR 5 +The data is a character string of length \fIcount\fR. If \fIcount\fR +is \fB*\fR, then all of the remaining bytes in \fIstring\fR will be +scanned into the variable. If \fIcount\fR is omitted, then one +character will be scanned. For example, +.RS +.CS +\fBbinary scan abcde\\000fghi a6a10 var1 var2\fR +.CE +will return \fB1\fR with the string equivalent to \fBabcde\\000\fR +stored in \fBvar1\fR and \fBvar2\fR left unmodified. +.RE +.IP \fBA\fR 5 +This form is the same as \fBa\fR, except trailing blanks and nulls are stripped from +the scanned value before it is stored in the variable. For example, +.RS +.CS +\fBbinary scan "abc efghi \\000" A* var1\fR +.CE +will return \fB1\fR with \fBabc efghi\fR stored in \fBvar1\fR. +.RE +.IP \fBb\fR 5 +The data is turned into a string of \fIcount\fR binary digits in +low-to-high order represented as a sequence of ``1'' and ``0'' +characters. The data bytes are scanned in first to last order with +the bits being taken in low-to-high order within each byte. Any extra +bits in the last byte are ignored. If \fIcount\fR is \fB*\fR, then +all of the remaining bits in \fBstring\fR will be scanned. If +\fIcount\fR is omitted, then one bit will be scanned. For example, +.RS +.CS +\fBbinary scan \\x07\\x87\\x05 b5b* var1 var2\fR +.CE +will return \fB2\fR with \fB11100\fR stored in \fBvar1\fR and +\fB1110000110100000\fR stored in \fBvar2\fR. +.RE +.IP \fBB\fR 5 +This form is the same as \fBb\fR, except the bits are taken in +high-to-low order within each byte. For example, +.RS +.CS +\fBbinary scan \\x70\\x87\\x05 B5B* var1 var2\fR +.CE +will return \fB2\fR with \fB01110\fR stored in \fBvar1\fR and +\fB1000011100000101\fR stored in \fBvar2\fR. +.RE +.IP \fBh\fR 5 +The data is turned into a string of \fIcount\fR hexadecimal digits in +low-to-high order represented as a sequence of characters in the set +``0123456789abcdef''. The data bytes are scanned in first to last +order with the hex digits being taken in low-to-high order within each +byte. Any extra bits in the last byte are ignored. If \fIcount\fR +is \fB*\fR, then all of the remaining hex digits in \fBstring\fR will be +scanned. If \fIcount\fR is omitted, then one hex digit will be +scanned. For example, +.RS +.CS +\fBbinary scan \\x07\\x86\\x05 h3h* var1 var2\fR +.CE +will return \fB2\fR with \fB706\fR stored in \fBvar1\fR and +\fB50\fR stored in \fBvar2\fR. +.RE +.IP \fBH\fR 5 +This form is the same as \fBh\fR, except the digits are taken in +high-to-low order within each byte. For example, +.RS +.CS +\fBbinary scan \\x07\\x86\\x05 H3H* var1 var2\fR +.CE +will return \fB2\fR with \fB078\fR stored in \fBvar1\fR and +\fB05\fR stored in \fBvar2\fR. +.RE +.IP \fBc\fR 5 +The data is turned into \fIcount\fR 8-bit signed integers and stored +in the corresponding variable as a list. If \fIcount\fR is \fB*\fR, +then all of the remaining bytes in \fBstring\fR will be scanned. If +\fIcount\fR is omitted, then one 8-bit integer will be scanned. For +example, +.RS +.CS +\fBbinary scan \\x07\\x86\\x05 c2c* var1 var2\fR +.CE +will return \fB2\fR with \fB7 -122\fR stored in \fBvar1\fR and \fB5\fR +stored in \fBvar2\fR. Note that the integers returned are signed, but +they can be converted to unsigned 8-bit quantities using an expression +like: +.CS +\fBexpr ( $num + 0x100 ) % 0x100\fR +.CE +.RE +.IP \fBs\fR 5 +The data is interpreted as \fIcount\fR 16-bit signed integers +represented in little-endian byte order. The integers are stored in +the corresponding variable as a list. If \fIcount\fR is \fB*\fR, then +all of the remaining bytes in \fBstring\fR will be scanned. If +\fIcount\fR is omitted, then one 16-bit integer will be scanned. For +example, +.RS +.CS +\fBbinary scan \\x05\\x00\\x07\\x00\\xf0\\xff s2s* var1 var2\fR +.CE +will return \fB2\fR with \fB5 7\fR stored in \fBvar1\fR and \fB-16\fR +stored in \fBvar2\fR. Note that the integers returned are signed, but +they can be converted to unsigned 16-bit quantities using an expression +like: +.CS +\fBexpr ( $num + 0x10000 ) % 0x10000\fR +.CE +.RE +.IP \fBS\fR 5 +This form is the same as \fBs\fR except that the data is interpreted +as \fIcount\fR 16-bit signed integers represented in big-endian byte +order. For example, +.RS +.CS +\fBbinary scan \\x00\\x05\\x00\\x07\\xff\\xf0 S2S* var1 var2\fR +.CE +will return \fB2\fR with \fB5 7\fR stored in \fBvar1\fR and \fB-16\fR +stored in \fBvar2\fR. +.RE +.IP \fBi\fR 5 +The data is interpreted as \fIcount\fR 32-bit signed integers +represented in little-endian byte order. The integers are stored in +the corresponding variable as a list. If \fIcount\fR is \fB*\fR, then +all of the remaining bytes in \fBstring\fR will be scanned. If +\fIcount\fR is omitted, then one 32-bit integer will be scanned. For +example, +.RS +.CS +\fBbinary scan \\x05\\x00\\x00\\x00\\x07\\x00\\x00\\x00\\xf0\\xff\\xff\\xff i2i* var1 var2\fR +.CE +will return \fB2\fR with \fB5 7\fR stored in \fBvar1\fR and \fB-16\fR +stored in \fBvar2\fR. Note that the integers returned are signed and +cannot be represented by Tcl as unsigned values. +.RE +.IP \fBI\fR 5 +This form is the same as \fBI\fR except that the data is interpreted +as \fIcount\fR 32-bit signed integers represented in big-endian byte +order. For example, +.RS +.CS +\fBbinary \\x00\\x00\\x00\\x05\\x00\\x00\\x00\\x07\\xff\\xff\\xff\\xf0 I2I* var1 var2\fR +.CE +will return \fB2\fR with \fB5 7\fR stored in \fBvar1\fR and \fB-16\fR +stored in \fBvar2\fR. +.RE +.IP \fBf\fR 5 +The data is interpreted as \fIcount\fR single-precision floating point +numbers in the machine's native representation. The floating point +numbers are stored in the corresponding variable as a list. If +\fIcount\fR is \fB*\fR, then all of the remaining bytes in +\fBstring\fR will be scanned. If \fIcount\fR is omitted, then one +single-precision floating point number will be scanned. The size of a +floating point number may vary across architectures, so the number of +bytes that are scanned may vary. If the data does not represent a +valid floating point number, the resulting value is undefined and +compiler dependent. For example, on a Windows system running on an +Intel Pentium processor, +.RS +.CS +\fBbinary scan \\x3f\\xcc\\xcc\\xcd f var1\fR +.CE +will return \fB1\fR with \fB1.6000000238418579\fR stored in +\fBvar1\fR. +.RE +.IP \fBd\fR 5 +This form is the same as \fBf\fR except that the data is interpreted +as \fIcount\fR double-precision floating point numbers in the +machine's native representation. For example, on a Windows system +running on an Intel Pentium processor, +.RS +.CS +\fBbinary scan \\x9a\\x99\\x99\\x99\\x99\\x99\\xf9\\x3f d var1\fR +.CE +will return \fB1\fR with \fB1.6000000000000001\fR +stored in \fBvar1\fR. +.RE +.IP \fBx\fR 5 +Moves the cursor forward \fIcount\fR bytes in \fIstring\fR. If +\fIcount\fR is \fB*\fR or is larger than the number of bytes after the +current cursor cursor position, then the cursor is positioned after +the last byte in \fIstring\fR. If \fIcount\fR is omitted, then the +cursor is moved forward one byte. Note that this type does not +consume an argument. For example, +.RS +.CS +\fBbinary scan \\x01\\x02\\x03\\x04 x2H* var1\fR +.CE +will return \fB1\fR with \fB0304\fR stored in \fBvar1\fR. +.RE +.IP \fBX\fR 5 +Moves the cursor back \fIcount\fR bytes in \fIstring\fR. If +\fIcount\fR is \fB*\fR or is larger than the current cursor position, +then the cursor is positioned at location 0 so that the next byte +scanned will be the first byte in \fIstring\fR. If \fIcount\fR +is omitted then the cursor is moved back one byte. Note that this +type does not consume an argument. For example, +.RS +.CS +\fBbinary scan \\x01\\x02\\x03\\x04 c2XH* var1 var2\fR +.CE +will return \fB2\fR with \fB1 2\fR stored in \fBvar1\fR and \fB020304\fR +stored in \fBvar2\fR. +.RE +.IP \fB@\fR 5 +Moves the cursor to the absolute location in the data string specified +by \fIcount\fR. Note that position 0 refers to the first byte in +\fIstring\fR. If \fIcount\fR refers to a position beyond the end of +\fIstring\fR, then the cursor is positioned after the last byte. If +\fIcount\fR is omitted, then an error will be generated. For example, +.RS +.CS +\fBbinary scan \\x01\\x02\\x03\\x04 c2@1H* var1 var2\fR +.CE +will return \fB2\fR with \fB1 2\fR stored in \fBvar1\fR and \fB020304\fR +stored in \fBvar2\fR. +.RE + +.SH "PLATFORM ISSUES" +Sometimes it is desirable to format or scan integer values in the +native byte order for the machine. Refer to the \fBbyteOrder\fR +element of the \fBtcl_platform\fR array to decide which type character +to use when formatting or scanning integers. + +.SH "SEE ALSO" +format(n), scan(n), tclvars(n) + +.SH KEYWORDS +binary, format, scan diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/break.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/break.n new file mode 100644 index 0000000000000000000000000000000000000000..a9a2e9b2cef96732291c19fc8b7a1baced80d62f --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/break.n @@ -0,0 +1,37 @@ +'\" +'\" Copyright (c) 1993-1994 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: break.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH break n "" Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +break \- Abort looping command +.SH SYNOPSIS +\fBbreak\fR +.BE + +.SH DESCRIPTION +.PP +This command is typically invoked inside the body of a looping command +such as \fBfor\fR or \fBforeach\fR or \fBwhile\fR. +It returns a TCL_BREAK code, which causes a break exception +to occur. +The exception causes the current script to be aborted +out to the innermost containing loop command, which then +aborts its execution and returns normally. +Break exceptions are also handled in a few other situations, such +as the \fBcatch\fR command, Tk event bindings, and the outermost +scripts of procedure bodies. + +.SH "SEE ALSO" +catch(n), continue(n), for(n), foreach(n), while(n) + +.SH KEYWORDS +abort, break, loop diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/case.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/case.n new file mode 100644 index 0000000000000000000000000000000000000000..dd40f8066a9518a86a8ba505d6b1eeff0d3cafc9 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/case.n @@ -0,0 +1,62 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: case.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH case n 7.0 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +case \- Evaluate one of several scripts, depending on a given value +.SH SYNOPSIS +\fBcase\fI string \fR?\fBin\fR? \fIpatList body \fR?\fIpatList body \fR...? +.sp +\fBcase\fI string \fR?\fBin\fR? {\fIpatList body \fR?\fIpatList body \fR...?} +.BE + +.SH DESCRIPTION +.PP +\fINote: the \fBcase\fI command is obsolete and is supported only +for backward compatibility. At some point in the future it may be +removed entirely. You should use the \fBswitch\fI command instead.\fR +.PP +The \fBcase\fR command matches \fIstring\fR against each of +the \fIpatList\fR arguments in order. +Each \fIpatList\fR argument is a list of one or +more patterns. If any of these patterns matches \fIstring\fR then +\fBcase\fR evaluates the following \fIbody\fR argument +by passing it recursively to the Tcl interpreter and returns the result +of that evaluation. +Each \fIpatList\fR argument consists of a single +pattern or list of patterns. Each pattern may contain any of the wild-cards +described under \fBstring match\fR. If a \fIpatList\fR +argument is \fBdefault\fR, the corresponding body will be evaluated +if no \fIpatList\fR matches \fIstring\fR. If no \fIpatList\fR argument +matches \fIstring\fR and no default is given, then the \fBcase\fR +command returns an empty string. +.PP +Two syntaxes are provided for the \fIpatList\fR and \fIbody\fR arguments. +The first uses a separate argument for each of the patterns and commands; +this form is convenient if substitutions are desired on some of the +patterns or commands. +The second form places all of the patterns and commands together into +a single argument; the argument must have proper list structure, with +the elements of the list being the patterns and commands. +The second form makes it easy to construct multi-line case commands, +since the braces around the whole list make it unnecessary to include a +backslash at the end of each line. +Since the \fIpatList\fR arguments are in braces in the second form, +no command or variable substitutions are performed on them; this makes +the behavior of the second form different than the first form in some +cases. + +.SH "SEE ALSO" +switch(n) + +.SH KEYWORDS +case, match, regular expression diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/catch.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/catch.n new file mode 100644 index 0000000000000000000000000000000000000000..80526d3d94ea5384b2137bc095fe3f9d9f61e001 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/catch.n @@ -0,0 +1,66 @@ +'\" +'\" Copyright (c) 1993-1994 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: catch.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH catch n "8.0" Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +catch \- Evaluate script and trap exceptional returns +.SH SYNOPSIS +\fBcatch\fI script \fR?\fIvarName\fR? +.BE + +.SH DESCRIPTION +.PP +The \fBcatch\fR command may be used to prevent errors from aborting command +interpretation. \fBCatch\fR calls the Tcl interpreter recursively to +execute \fIscript\fR, and always returns without raising an error, +regardless of any errors that might occur while executing \fIscript\fR. +.PP +If \fIscript\fR raises an error, \fBcatch\fR will return a non-zero integer +value corresponding to one of the exceptional return codes (see tcl.h +for the definitions of code values). If the \fIvarName\fR argument is +given, then the variable it names is set to the error message from +interpreting \fIscript\fR. +.PP +If \fIscript\fR does not raise an error, \fBcatch\fR will return 0 +(TCL_OK) and set the variable to the value returned from \fIscript\fR. +.PP +Note that \fBcatch\fR catches all exceptions, including those +generated by \fBbreak\fR and \fBcontinue\fR as well as errors. The +only errors that are not caught are syntax errors found when the +script is compiled. This is because the catch command only catches +errors during runtime. When the catch statement is compiled, the +script is compiled as well and any syntax errors will generate a Tcl +error. + +.SH EXAMPLES + +The \fBcatch\fR command may be used in an \fBif\fR to branch based on +the success of a script. + +.CS +if { [catch {open $someFile w} fid] } { + puts stderr "Could not open $someFile for writing\\n$fid" + exit 1 +} +.CE +The \fBcatch\fR command will not catch compiled syntax errors. The +first time proc \fBfoo\fR is called, the body will be compiled and a +Tcl error will be generated. + +.CS +proc foo {} { + catch {expr {1 +- }} +} +.CE + +.SH KEYWORDS +catch, error diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/cd.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/cd.n new file mode 100644 index 0000000000000000000000000000000000000000..2b67d9ffe6e88a8c5ebaa8fab6b36699ed4a7a8b --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/cd.n @@ -0,0 +1,31 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: cd.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH cd n "" Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +cd \- Change working directory +.SH SYNOPSIS +\fBcd \fR?\fIdirName\fR? +.BE + +.SH DESCRIPTION +.PP +Change the current working directory to \fIdirName\fR, or to the +home directory (as specified in the HOME environment variable) if +\fIdirName\fR is not given. +Returns an empty string. + +.SH "SEE ALSO" +filename(n), glob(n), pwd(n) + +.SH KEYWORDS +working directory diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/clock.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/clock.n new file mode 100644 index 0000000000000000000000000000000000000000..63881ea18b96633628af976617ced31dd4b322ba --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/clock.n @@ -0,0 +1,214 @@ +'\" +'\" Copyright (c) 1992-1995 Karl Lehenbauer and Mark Diekhans. +'\" Copyright (c) 1995-1997 Sun Microsystems, Inc. +'\" Copyright (c) 1998-1999 Scriptics Corporation +'\" +'\" This documentation is derived from the time and date facilities of +'\" TclX, by Mark Diekhans and Karl Lehenbauer. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: clock.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH clock n 8.3 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +clock \- Obtain and manipulate time +.SH SYNOPSIS +\fBclock \fIoption\fR ?\fIarg arg ...\fR? +.BE + +.SH DESCRIPTION +.PP +This command performs one of several operations that may obtain +or manipulate strings or values that represent some notion of +time. The \fIoption\fR argument determines what action is carried +out by the command. The legal \fIoptions\fR (which may be +abbreviated) are: +.TP +.VS 8.3 +\fBclock clicks\fR ?\fB\-milliseconds\fR? +Return a high-resolution time value as a system-dependent integer +value. The unit of the value is system-dependent but should be the +highest resolution clock available on the system such as a CPU cycle +counter. If \fB\-milliseconds\fR is specified, then the value is +guaranteed to be of millisecond granularity. +This value should only be used for the relative measurement +of elapsed time. +.VE 8.3 +.TP +\fBclock format \fIclockValue\fR ?\fB\-format \fIstring\fR? ?\fB\-gmt \fIboolean\fR? +Converts an integer time value, typically returned by +\fBclock seconds\fR, \fBclock scan\fR, or the \fBatime\fR, \fBmtime\fR, +or \fBctime\fR options of the \fBfile\fR command, to human-readable +form. If the \fB\-format\fR argument is present the next argument is a +string that describes how the date and time are to be formatted. +Field descriptors consist of a \fB%\fR followed by a field +descriptor character. All other characters are copied into the result. +Valid field descriptors are: +.RS +.IP \fB%%\fR +Insert a %. +.IP \fB%a\fR +Abbreviated weekday name (Mon, Tue, etc.). +.IP \fB%A\fR +Full weekday name (Monday, Tuesday, etc.). +.IP \fB%b\fR +Abbreviated month name (Jan, Feb, etc.). +.IP \fB%B\fR +Full month name. +.IP \fB%c\fR +Locale specific date and time. +.IP \fB%d\fR +Day of month (01 - 31). +.IP \fB%H\fR +Hour in 24-hour format (00 - 23). +.IP \fB%I\fR +Hour in 12-hour format (00 - 12). +.IP \fB%j\fR +Day of year (001 - 366). +.IP \fB%m\fR +Month number (01 - 12). +.IP \fB%M\fR +Minute (00 - 59). +.IP \fB%p\fR +AM/PM indicator. +.IP \fB%S\fR +Seconds (00 - 59). +.IP \fB%U\fR +Week of year (00 - 52), Sunday is the first day of the week. +.IP \fB%w\fR +Weekday number (Sunday = 0). +.IP \fB%W\fR +Week of year (00 - 52), Monday is the first day of the week. +.IP \fB%x\fR +Locale specific date format. +.IP \fB%X\fR +Locale specific time format. +.IP \fB%y\fR +Year without century (00 - 99). +.IP \fB%Y\fR +Year with century (e.g. 1990) +.IP \fB%Z\fR +Time zone name. +.RE +.sp +.RS +In addition, the following field descriptors may be supported on some +systems (e.g. Unix but not Windows): +.IP \fB%D\fR +Date as %m/%d/%y. +.IP \fB%e\fR +Day of month (1 - 31), no leading zeros. +.IP \fB%h\fR +Abbreviated month name. +.IP \fB%n\fR +Insert a newline. +.IP \fB%r\fR +Time as %I:%M:%S %p. +.IP \fB%R\fR +Time as %H:%M. +.IP \fB%t\fR +Insert a tab. +.IP \fB%T\fR +Time as %H:%M:%S. +.RE +.sp +.RS +If the \fB\-format\fR argument is not specified, the format string +"\fB%a %b %d %H:%M:%S %Z %Y\fR" is used. If the \fB\-gmt\fR argument +is present the next argument must be a boolean which if true specifies +that the time will be formatted as Greenwich Mean Time. If false +then the local timezone will be used as defined by the operating +environment. +.RE +.TP +\fBclock scan \fIdateString\fR ?\fB\-base \fIclockVal\fR? ?\fB\-gmt \fIboolean\fR? +Convert \fIdateString\fR to an integer clock value (see \fBclock seconds\fR). +This command can parse and convert virtually any standard date and/or time +string, which can include standard time zone mnemonics. If only a time is +specified, the current date is assumed. If the string does not contain a +time zone mnemonic, the local time zone is assumed, unless the \fB\-gmt\fR +argument is true, in which case the clock value is calculated assuming +that the specified time is relative to Greenwich Mean Time. +\fB-gmt\fR, if specified, affects only the computed time value; it does not +impact the interpretation of \fB-base\fR. +.sp +If the \fB\-base\fR flag is specified, the next argument should contain +an integer clock value. Only the date in this value is used, not the +time. This is useful for determining the time on a specific day or +doing other date-relative conversions. +.sp +The \fIdateString\fR consists of zero or more specifications of the +following form: +.RS +.TP +\fItime\fR +A time of day, which is of the form: \fIhh\fR?\fI:mm\fR?\fI:ss\fR?? +?\fImeridian\fR? ?\fIzone\fR? or \fIhhmm \fR?\fImeridian\fR? +?\fIzone\fR?. If no meridian is specified, \fIhh\fR is interpreted on +a 24-hour clock. +.TP +\fIdate\fR +A specific month and day with optional year. The +acceptable formats are \fImm/dd\fR?\fI/yy\fR?, \fImonthname dd\fR +?, \fIyy\fR?, \fIdd monthname \fR?\fIyy\fR?, \fIday, dd monthname +yy\fR, \fI?CC?yymmdd\fR, \fI?CC?yy-mm-dd\fR, \fIdd-monthname-?CC?yy\fR. +The default year is the current year. If the year is less +.VS +than 100, we treat the years 00-68 as 2000-2068 and the years 69-99 +as 1969-1999. Not all platforms can represent the years 38-70, so +an error may result if these years are used. +.VE +.TP +\fIISO 8601 point-in-time\fR +An ISO 8601 point-in-time specification, such as \fICCyymmddThhmmss\fR, where +T is the literal T, \fICCyymmdd hhmmss\fR, or +\fICCyymmddThh:mm:ss\fR. +.TP +\fIrelative time\fR +A specification relative to the current time. The format is \fInumber +unit\fR acceptable units are \fByear\fR, \fBfortnight\fR, \fBmonth\fR, \fBweek\fR, \fBday\fR, +\fBhour\fR, \fBminute\fR (or \fBmin\fR), and \fBsecond\fR (or \fBsec\fR). The +unit can be specified as a singular or plural, as in \fB3 weeks\fR. +These modifiers may also be specified: +\fBtomorrow\fR, \fByesterday\fR, \fBtoday\fR, \fBnow\fR, +\fBlast\fR, \fBthis\fR, \fBnext\fR, \fBago\fR. +.RE +.sp +.RS +The actual date is calculated according to the following steps. +First, any absolute date and/or time is processed and converted. +Using that time as the base, day-of-week specifications are added. +Next, relative specifications are used. If a date or day is +specified, and no absolute or relative time is given, midnight is +used. Finally, a correction is applied so that the correct hour of +the day is produced after allowing for daylight savings time +differences and the correct date is given when going from the end +of a long month to a short month. +.sp +Daylight savings time correction is applied only when the relative time +is specified in units of days or more, ie, days, weeks, fortnights, months or +years. This means that when crossing the daylight savings time boundary, +different results will be given for \fBclock scan "1 day"\fR and +\fBclock scan "24 hours"\fR: +.CS +.ta 6c +\fB% clock scan "1 day" -base [clock scan 1999-10-31] +941443200 +% clock scan "24 hours" -base [clock scan 1999-10-31] +941439600\fR +.CE +.RE +.TP +\fBclock seconds\fR +Return the current date and time as a system-dependent integer value. The +unit of the value is seconds, allowing it to be used for relative time +calculations. The value is usually defined as total elapsed time from +an ``epoch''. You shouldn't assume the value of the epoch. + +.SH KEYWORDS +clock, date, time diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/close.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/close.n new file mode 100644 index 0000000000000000000000000000000000000000..abb1828fa628002deced706ae551095a86316ef2 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/close.n @@ -0,0 +1,62 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: close.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH close n 7.5 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +close \- Close an open channel. +.SH SYNOPSIS +\fBclose \fIchannelId\fR +.BE + +.SH DESCRIPTION +.PP +Closes the channel given by \fIchannelId\fR. \fIChannelId\fR must be a +channel identifier such as the return value from a previous \fBopen\fR +or \fBsocket\fR command. +All buffered output is flushed to the channel's output device, +any buffered input is discarded, the underlying file or device is closed, +and \fIchannelId\fR becomes unavailable for use. +.VS "" br +.PP +If the channel is blocking, the command does not return until all output +is flushed. +If the channel is nonblocking and there is unflushed output, the +channel remains open and the command +returns immediately; output will be flushed in the background and the +channel will be closed when all the flushing is complete. +.VE +.PP +If \fIchannelId\fR is a blocking channel for a command pipeline then +\fBclose\fR waits for the child processes to complete. +.VS "" br +.PP +If the channel is shared between interpreters, then \fBclose\fR +makes \fIchannelId\fR unavailable in the invoking interpreter but has no +other effect until all of the sharing interpreters have closed the +channel. +When the last interpreter in which the channel is registered invokes +\fBclose\fR, the cleanup actions described above occur. See the +\fBinterp\fR command for a description of channel sharing. +.PP +Channels are automatically closed when an interpreter is destroyed and +when the process exits. Channels are switched to blocking mode, to ensure +that all output is correctly flushed before the process exits. +.VE +.PP +The command returns an empty string, and may generate an error if +an error occurs while flushing output. + +.SH "SEE ALSO" +file(n), open(n), socket(n), eof(n) + +.SH KEYWORDS +blocking, channel, close, nonblocking diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/concat.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/concat.n new file mode 100644 index 0000000000000000000000000000000000000000..0fafb84cd6461d6345b84805c9c2759b52442cf3 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/concat.n @@ -0,0 +1,43 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: concat.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH concat n "" Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +concat \- Join lists together +.SH SYNOPSIS +\fBconcat\fI \fR?\fIarg arg ...\fR? +.BE + +.SH DESCRIPTION +.PP +This command treats each argument as a list and concatenates them +into a single list. +It also eliminates leading and trailing spaces in the \fIarg\fR's +and adds a single separator space between \fIarg\fR's. +It permits any number of arguments. For example, +the command +.CS +\fBconcat a b {c d e} {f {g h}}\fR +.CE +will return +.CS +\fBa b c d e f {g h}\fR +.CE +as its result. +.PP +If no \fIarg\fRs are supplied, the result is an empty string. + +.SH "SEE ALSO" +append(n), eval(n) + +.SH KEYWORDS +concatenate, join, lists diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/continue.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/continue.n new file mode 100644 index 0000000000000000000000000000000000000000..b1b74cedcd564496ee0c65a6aad10d1be24d7d24 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/continue.n @@ -0,0 +1,37 @@ +'\" +'\" Copyright (c) 1993-1994 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: continue.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH continue n "" Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +continue \- Skip to the next iteration of a loop +.SH SYNOPSIS +\fBcontinue\fR +.BE + +.SH DESCRIPTION +.PP +This command is typically invoked inside the body of a looping command +such as \fBfor\fR or \fBforeach\fR or \fBwhile\fR. +It returns a TCL_CONTINUE code, which causes a continue exception +to occur. +The exception causes the current script to be aborted +out to the innermost containing loop command, which then +continues with the next iteration of the loop. +Catch exceptions are also handled in a few other situations, such +as the \fBcatch\fR command and the outermost scripts of procedure +bodies. + +.SH "SEE ALSO" +break(n), for(n), foreach(n), while(n) + +.SH KEYWORDS +continue, iteration, loop diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/dde.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/dde.n new file mode 100644 index 0000000000000000000000000000000000000000..57567607df6287b14f7bf397b897c2afefdd590d --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/dde.n @@ -0,0 +1,136 @@ +'\" +'\" Copyright (c) 1997 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: dde.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH dde n 8.1 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +dde \- Execute a Dynamic Data Exchange command +.SH SYNOPSIS +.sp +\fBpackage require dde 1.1\fR +.sp +\fBdde \fIservername \fR?\fItopic\fR? +.sp +\fBdde ?\-async?\fR \fIcommand service topic \fR?\fIdata\fR? +.BE + +.SH DESCRIPTION +.PP +This command allows an application to send Dynamic Data Exchange (DDE) +command when running under Microsoft Windows. Dynamic Data Exchange is +a mechanism where applications can exchange raw data. Each DDE +transaction needs a \fIservice name\fR and a \fItopic\fR. Both the +\fIservice name\fR and \fItopic\fR are application defined; Tcl uses +the service name \fBTclEval\fR, while the topic name is the name of the +interpreter given by \fBdde servername\fR. Other applications have their +own \fIservice names\fR and \fItopics\fR. For instance, Microsoft Excel +has the service name \fBExcel\fR. +.PP +The only option to the \fBdde\fR command is: +.TP +\fB\-async\fR +Requests asynchronous invocation. This is valid only for the +\fBexecute\fR subcommand. Normally, the \fBdde execute\fR subcommand +waits until the command completes, returning appropriate error +messages. When the \fB\-async\fR option is used, the command returns +immediately, and no error information is available. +.SH "DDE COMMANDS" +.PP +The following commands are a subset of the full Dynamic Data Exchange +set of commands. +.TP +\fBdde servername \fR?\fItopic\fR? +\fBdde servername\fR registers the interpreter as a DDE server with +the service name \fBTclEval\fR and the topic name specified by \fItopic\fR. +If no \fItopic\fR is given, \fBdde servername\fR returns the name +of the current topic or the empty string if it is not registered as a service. +.TP +\fBdde execute \fIservice topic data\fR +\fBdde execute\fR takes the \fIdata\fR and sends it to the server +indicated by \fIservice\fR with the topic indicated by +\fItopic\fR. Typically, \fIservice\fR is the name of an application, +and \fItopic\fR is a file to work on. The \fIdata\fR field is given +to the remote application. Typically, the application treats the +\fIdata\fR field as a script, and the script is run in the +application. The command returns an error if the script did not +run. If the \fB\-async\fR flag was used, the command +returns immediately with no error. +.TP +\fBdde poke \fIservice topic item data\fR +\fBdde poke\fR passes the \fIdata\fR to the server indicated by +\fIservice\fR using the \fItopic\fR and \fIitem\fR specified. Typically, +\fIservice\fR is the name of an application. \fItopic\fR is application +specific but can be a command to the server or the name of a file to work +on. The \fIitem\fR is also application specific and is often not used, but +it must always be non-null. The \fIdata\fR field is given to the remote +application. +.TP +\fBdde request \fIservice topic item\fR +\fBdde request\fR is typically used to get the value of something; the +value of a cell in Microsoft Excel or the text of a selection in +Microsoft Word. \fIservice\fR is typically the name of an application, +\fItopic\fR is typically the name of the file, and \fIitem\fR is +application-specific. The command returns the value of \fIitem\fR as +defined in the application. +.TP +\fBdde services \fIservice topic\fR +\fBdde services\fR returns a list of service-topic pairs that +currently exist on the machine. If \fIservice\fR and \fItopic\fR are +both null strings ({}), then all service-topic pairs currently +available on the system are returned. If \fIservice\fR is null and +\fItopic\fR is not, then all services with the specified topic are +returned. If \fIservice\fR is not null and \fItopic\fR is, all topics +for a given service are returned. If both are not null, if that +service-topic pair currently exists, it is returned; otherwise, null +is returned. +.TP +\fBdde eval \fItopic cmd \fR?\fIarg arg ...\fR? +\fBdde eval\fR evaluates a command and its arguments using the +interpreter specified by \fItopic\fR. The DDE service must be the +\fBTclEval\fR service. This command can be used to replace send on +Windows. +.SH "DDE AND TCL" +A Tcl interpreter always has a service name of \fBTclEval\fR. Each +different interpreter of all running Tcl applications must be +given a unique +name specified by \fBdde servername\fR. Each interp is available as a +DDE topic only if the \fBdde servername\fR command was used to set the +name of the topic for each interp. So a \fBdde services TclEval {}\fR +command will return a list of service-topic pairs, where each of the +currently running interps will be a topic. +.PP +When Tcl processes a \fBdde execute\fR command, the data for the +execute is run as a script in the interp named by the topic of the +\fBdde execute\fR command. +.PP +When Tcl processes a \fBdde request\fR command, it returns the value of the +variable given in the dde command in the context of the interp named by the +dde topic. Tcl reserves the variable \fB$TCLEVAL$EXECUTE$RESULT\fR for +internal use, and \fBdde request\fR commands for that variable will give +unpredictable results. +.PP +An external application which wishes to run a script in Tcl should have +that script store its result in a variable, run the \fBdde execute\fR +command, and the run \fBdde request\fR to get the value of the +variable. +.PP +When using DDE, be careful to ensure that the event queue is flushed +using either \fBupdate\fR or \fBvwait\fR. This happens by default +when using \fBwish\fR unless a blocking command is called (such as \fBexec\fR +without adding the \fB&\fR to place the process in the background). +If for any reason the event queue is not flushed, DDE commands may +hang until the event queue is flushed. This can create a deadlock +situation. + +.SH "SEE ALSO" +tk(n), winfo(n), send(n) + +.SH KEYWORDS +application, dde, name, remote execution diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/encoding.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/encoding.n new file mode 100644 index 0000000000000000000000000000000000000000..c1a3760205edfb1ec95a64230574f97e8570df05 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/encoding.n @@ -0,0 +1,79 @@ +'\" +'\" Copyright (c) 1998 by Scriptics Corporation. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: encoding.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH encoding n "8.1" Tcl "Tcl Built-In Commands" +.BS +.SH NAME +encoding \- Manipulate encodings +.SH SYNOPSIS +\fBencoding \fIoption\fR ?\fIarg arg ...\fR? +.BE + +.SH INTRODUCTION +.PP +Strings in Tcl are encoded using 16-bit Unicode characters. Different +operating system interfaces or applications may generate strings in +other encodings such as Shift-JIS. The \fBencoding\fR command helps +to bridge the gap between Unicode and these other formats. + +.SH DESCRIPTION +.PP +Performs one of several encoding related operations, depending on +\fIoption\fR. The legal \fIoption\fRs are: +.TP +\fBencoding convertfrom ?\fIencoding\fR? \fIdata\fR +Convert \fIdata\fR to Unicode from the specified \fIencoding\fR. The +characters in \fIdata\fR are treated as binary data where the lower +8-bits of each character is taken as a single byte. The resulting +sequence of bytes is treated as a string in the specified +\fIencoding\fR. If \fIencoding\fR is not specified, the current +system encoding is used. +.TP +\fBencoding convertto ?\fIencoding\fR? \fIstring\fR +Convert \fIstring\fR from Unicode to the specified \fIencoding\fR. +The result is a sequence of bytes that represents the converted +string. Each byte is stored in the lower 8-bits of a Unicode +character. If \fIencoding\fR is not specified, the current +system encoding is used. +.TP +\fBencoding names\fR +Returns a list containing the names of all of the encodings that are +currently available. +.TP +\fBencoding system\fR ?\fIencoding\fR? +Set the system encoding to \fIencoding\fR. If \fIencoding\fR is +omitted then the command returns the current system encoding. The +system encoding is used whenever Tcl passes strings to system calls. + +.SH EXAMPLE +.PP +It is common practice to write script files using a text editor that +produces output in the euc-jp encoding, which represents the ASCII +characters as singe bytes and Japanese characters as two bytes. This +makes it easy to embed literal strings that correspond to non-ASCII +characters by simply typing the strings in place in the script. +However, because the \fBsource\fR command always reads files using the +ISO8859-1 encoding, Tcl will treat each byte in the file as a separate +character that maps to the 00 page in Unicode. The +resulting Tcl strings will not contain the expected Japanese +characters. Instead, they will contain a sequence of Latin-1 +characters that correspond to the bytes of the original string. The +\fBencoding\fR command can be used to convert this string to the +expected Japanese Unicode characters. For example, +.CS + set s [encoding convertfrom euc-jp "\\xA4\\xCF"] +.CE +would return the Unicode string "\\u306F", which is the Hiragana +letter HA. + +.SH "SEE ALSO" +Tcl_GetEncoding(3) + +.SH KEYWORDS +encoding diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/eof.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/eof.n new file mode 100644 index 0000000000000000000000000000000000000000..ce61b2077396e54ca3b4e93a600bc8f28f29f6c0 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/eof.n @@ -0,0 +1,30 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: eof.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH eof n 7.5 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +eof \- Check for end of file condition on channel +.SH SYNOPSIS +\fBeof \fIchannelId\fR +.BE + +.SH DESCRIPTION +.PP +Returns 1 if an end of file condition occurred during the most +recent input operation on \fIchannelId\fR (such as \fBgets\fR), +0 otherwise. + +.SH "SEE ALSO" +file(n), open(n), close(n), fblocked(n) + +.SH KEYWORDS +channel, end of file diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/error.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/error.n new file mode 100644 index 0000000000000000000000000000000000000000..bb7c91ff26106e0f1da50663e2099f9477bb2028 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/error.n @@ -0,0 +1,61 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: error.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH error n "" Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +error \- Generate an error +.SH SYNOPSIS +\fBerror \fImessage\fR ?\fIinfo\fR? ?\fIcode\fR? +.BE + +.SH DESCRIPTION +.PP +Returns a TCL_ERROR code, which causes command interpretation to be +unwound. \fIMessage\fR is a string that is returned to the application +to indicate what went wrong. +.PP +If the \fIinfo\fR argument is provided and is non-empty, +it is used to initialize the global variable \fBerrorInfo\fR. +\fBerrorInfo\fR is used to accumulate a stack trace of what +was in progress when an error occurred; as nested commands unwind, +the Tcl interpreter adds information to \fBerrorInfo\fR. If the +\fIinfo\fR argument is present, it is used to initialize +\fBerrorInfo\fR and the first increment of unwind information +will not be added by the Tcl interpreter. In other +words, the command containing the \fBerror\fR command will not appear +in \fBerrorInfo\fR; in its place will be \fIinfo\fR. +This feature is most useful in conjunction with the \fBcatch\fR command: +if a caught error cannot be handled successfully, \fIinfo\fR can be used +to return a stack trace reflecting the original point of occurrence +of the error: +.CS +\fBcatch {...} errMsg +set savedInfo $errorInfo +\&... +error $errMsg $savedInfo\fR +.CE +.PP +If the \fIcode\fR argument is present, then its value is stored +in the \fBerrorCode\fR global variable. This variable is intended +to hold a machine-readable description of the error in cases where +such information is available; see the \fBtclvars\fR manual +page for information on the proper format for the variable. +If the \fIcode\fR argument is not +present, then \fBerrorCode\fR is automatically reset to +``NONE'' by the Tcl interpreter as part of processing the +error generated by the command. + +.SH "SEE ALSO" +catch(n), tclvars(n) + +.SH KEYWORDS +error, errorCode, errorInfo diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/eval.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/eval.n new file mode 100644 index 0000000000000000000000000000000000000000..608c539cffec891d9168bbe2358935ceaf68b2a2 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/eval.n @@ -0,0 +1,33 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: eval.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH eval n "" Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +eval \- Evaluate a Tcl script +.SH SYNOPSIS +\fBeval \fIarg \fR?\fIarg ...\fR? +.BE + +.SH DESCRIPTION +.PP +\fBEval\fR takes one or more arguments, which together comprise a Tcl +script containing one or more commands. +\fBEval\fR concatenates all its arguments in the same +fashion as the \fBconcat\fR command, passes the concatenated string to the +Tcl interpreter recursively, and returns the result of that +evaluation (or any error generated by it). + +.SH KEYWORDS +concatenate, evaluate, script + +.SH "SEE ALSO" +catch(n), concat(n), error(n), subs(n), tclvars(n) diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/exec.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/exec.n new file mode 100644 index 0000000000000000000000000000000000000000..0e977bd503ba71309201ccaa09da134590da86a3 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/exec.n @@ -0,0 +1,307 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: exec.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH exec n 7.6 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +exec \- Invoke subprocess(es) +.SH SYNOPSIS +\fBexec \fR?\fIswitches\fR? \fIarg \fR?\fIarg ...\fR? +.BE + +.SH DESCRIPTION +.PP +This command treats its arguments as the specification +of one or more subprocesses to execute. +The arguments take the form of a standard shell pipeline +where each \fIarg\fR becomes one word of a command, and +each distinct command becomes a subprocess. +.PP +If the initial arguments to \fBexec\fR start with \fB\-\fR then +they are treated as command-line switches and are not part +of the pipeline specification. The following switches are +currently supported: +.TP 13 +\fB\-keepnewline\fR +Retains a trailing newline in the pipeline's output. +Normally a trailing newline will be deleted. +.TP 13 +\fB\-\|\-\fR +Marks the end of switches. The argument following this one will +be treated as the first \fIarg\fR even if it starts with a \fB\-\fR. +.PP +If an \fIarg\fR (or pair of \fIarg\fR's) has one of the forms +described below then it is used by \fBexec\fR to control the +flow of input and output among the subprocess(es). +Such arguments will not be passed to the subprocess(es). In forms +such as ``< \fIfileName\fR'' \fIfileName\fR may either be in a +separate argument from ``<'' or in the same argument with no +intervening space (i.e. ``<\fIfileName\fR''). +.TP 15 +| +Separates distinct commands in the pipeline. The standard output +of the preceding command will be piped into the standard input +of the next command. +.TP 15 +|& +Separates distinct commands in the pipeline. Both standard output +and standard error of the preceding command will be piped into +the standard input of the next command. +This form of redirection overrides forms such as 2> and >&. +.TP 15 +<\0\fIfileName\fR +The file named by \fIfileName\fR is opened and used as the standard +input for the first command in the pipeline. +.TP 15 +<@\0\fIfileId\fR +\fIFileId\fR must be the identifier for an open file, such as the return +value from a previous call to \fBopen\fR. +It is used as the standard input for the first command in the pipeline. +\fIFileId\fR must have been opened for reading. +.TP 15 +<<\0\fIvalue\fR +\fIValue\fR is passed to the first command as its standard input. +.TP 15 +>\0\fIfileName\fR +Standard output from the last command is redirected to the file named +\fIfileName\fR, overwriting its previous contents. +.TP 15 +2>\0\fIfileName\fR +Standard error from all commands in the pipeline is redirected to the +file named \fIfileName\fR, overwriting its previous contents. +.TP 15 +>&\0\fIfileName\fR +Both standard output from the last command and standard error from all +commands are redirected to the file named \fIfileName\fR, overwriting +its previous contents. +.TP 15 +>>\0\fIfileName\fR +Standard output from the last command is +redirected to the file named \fIfileName\fR, appending to it rather +than overwriting it. +.TP 15 +2>>\0\fIfileName\fR +Standard error from all commands in the pipeline is +redirected to the file named \fIfileName\fR, appending to it rather +than overwriting it. +.TP 15 +>>&\0\fIfileName\fR +Both standard output from the last command and standard error from +all commands are redirected to the file named \fIfileName\fR, +appending to it rather than overwriting it. +.TP 15 +>@\0\fIfileId\fR +\fIFileId\fR must be the identifier for an open file, such as the return +value from a previous call to \fBopen\fR. +Standard output from the last command is redirected to \fIfileId\fR's +file, which must have been opened for writing. +.TP 15 +2>@\0\fIfileId\fR +\fIFileId\fR must be the identifier for an open file, such as the return +value from a previous call to \fBopen\fR. +Standard error from all commands in the pipeline is +redirected to \fIfileId\fR's file. +The file must have been opened for writing. +.TP 15 +>&@\0\fIfileId\fR +\fIFileId\fR must be the identifier for an open file, such as the return +value from a previous call to \fBopen\fR. +Both standard output from the last command and standard error from +all commands are redirected to \fIfileId\fR's file. +The file must have been opened for writing. +.PP +If standard output has not been redirected then the \fBexec\fR +command returns the standard output from the last command +in the pipeline. +If any of the commands in the pipeline exit abnormally or +are killed or suspended, then \fBexec\fR will return an error +and the error message will include the pipeline's output followed by +error messages describing the abnormal terminations; the +\fBerrorCode\fR variable will contain additional information +about the last abnormal termination encountered. +If any of the commands writes to its standard error file and that +standard error isn't redirected, +then \fBexec\fR will return an error; the error message +will include the pipeline's standard output, followed by messages +about abnormal terminations (if any), followed by the standard error +output. +.PP +If the last character of the result or error message +is a newline then that character is normally deleted +from the result or error message. +This is consistent with other Tcl return values, which don't +normally end with newlines. +However, if \fB\-keepnewline\fR is specified then the trailing +newline is retained. +.PP +If standard input isn't redirected with ``<'' or ``<<'' +or ``<@'' then the standard input for the first command in the +pipeline is taken from the application's current standard input. +.PP +If the last \fIarg\fR is ``&'' then the pipeline will be +executed in background. +In this case the \fBexec\fR command will return a list whose +elements are the process identifiers for all of the subprocesses +in the pipeline. +The standard output from the last command in the pipeline will +go to the application's standard output if it hasn't been +redirected, and error output from all of +the commands in the pipeline will go to the application's +standard error file unless redirected. +.PP +The first word in each command is taken as the command name; +tilde-substitution is performed on it, and if the result contains +no slashes then the directories +in the PATH environment variable are searched for +an executable by the given name. +If the name contains a slash then it must refer to an executable +reachable from the current directory. +No ``glob'' expansion or other shell-like substitutions +are performed on the arguments to commands. + +.VS +.SH "PORTABILITY ISSUES" +.TP +\fBWindows\fR (all versions) +. +Reading from or writing to a socket, using the ``\fB@\0\fIfileId\fR'' +notation, does not work. When reading from a socket, a 16-bit DOS +application will hang and a 32-bit application will return immediately with +end-of-file. When either type of application writes to a socket, the +information is instead sent to the console, if one is present, or is +discarded. +.sp +The Tk console text widget does not provide real standard IO capabilities. +Under Tk, when redirecting from standard input, all applications will see an +immediate end-of-file; information redirected to standard output or standard +error will be discarded. +.sp +Either forward or backward slashes are accepted as path separators for +arguments to Tcl commands. When executing an application, the path name +specified for the application may also contain forward or backward slashes +as path separators. Bear in mind, however, that most Windows applications +accept arguments with forward slashes only as option delimiters and +backslashes only in paths. Any arguments to an application that specify a +path name with forward slashes will not automatically be converted to use +the backslash character. If an argument contains forward slashes as the +path separator, it may or may not be recognized as a path name, depending on +the program. +.sp +Additionally, when calling a 16-bit DOS or Windows 3.X application, all path +names must use the short, cryptic, path format (e.g., using ``applba~1.def'' +instead of ``applbakery.default''). +.sp +Two or more forward or backward slashes in a row in a path refer to a +network path. For example, a simple concatenation of the root directory +\fBc:/\fR with a subdirectory \fB/windows/system\fR will yield +\fBc://windows/system\fR (two slashes together), which refers to the mount +point called \fBsystem\fR on the machine called \fBwindows\fR (and the +\fBc:/\fR is ignored), and is not equivalent to \fBc:/windows/system\fR, +which describes a directory on the current computer. The \fBfile join\fR +command should be used to concatenate path components. +.TP +\fBWindows NT\fR +. +When attempting to execute an application, \fBexec\fR first searches for the +name as it was specified. Then, in order, \fB.com\fR, \fB.exe\fR, and \fB.bat\fR +are appended to the end of the specified name and it searches for +the longer name. If a directory name was not specified as part of the +application name, the following directories are automatically searched in +order when attempting to locate the application: +.sp +.RS +.RS +The directory from which the Tcl executable was loaded. +.br +The current directory. +.br +The Windows NT 32-bit system directory. +.br +The Windows NT 16-bit system directory. +.br +The Windows NT home directory. +.br +The directories listed in the path. +.RE +.sp +In order to execute the shell builtin commands like \fBdir\fR and \fBcopy\fR, +the caller must prepend ``\fBcmd.exe /c\0\fR'' to the desired command. +.sp +.RE +.TP +\fBWindows 95\fR +. +When attempting to execute an application, \fBexec\fR first searches for the +name as it was specified. Then, in order, \fB.com\fR, \fB.exe\fR, and \fB.bat\fR +are appended to the end of the specified name and it searches for +the longer name. If a directory name was not specified as part of the +application name, the following directories are automatically searched in +order when attempting to locate the application: +.sp +.RS +.RS +The directory from which the Tcl executable was loaded. +.br +The current directory. +.br +The Windows 95 system directory. +.br +The Windows 95 home directory. +.br +The directories listed in the path. +.RE +.sp +In order to execute the shell builtin commands like \fBdir\fR and \fBcopy\fR, +the caller must prepend ``\fBcommand.com /c\0\fR'' to the desired command. +.sp +Once a 16-bit DOS application has read standard input from a console and +then quit, all subsequently run 16-bit DOS applications will see the +standard input as already closed. 32-bit applications do not have this +problem and will run correctly, even after a 16-bit DOS application thinks +that standard input is closed. There is no known workaround for this bug +at this time. +.sp +Redirection between the \fBNUL:\fR device and a 16-bit application does not +always work. When redirecting from \fBNUL:\fR, some applications may hang, +others will get an infinite stream of ``0x01'' bytes, and some will actually +correctly get an immediate end-of-file; the behavior seems to depend upon +something compiled into the application itself. When redirecting greater than +4K or so to \fBNUL:\fR, some applications will hang. The above problems do not +happen with 32-bit applications. +.sp +All DOS 16-bit applications are run synchronously. All standard input from +a pipe to a 16-bit DOS application is collected into a temporary file; the +other end of the pipe must be closed before the 16-bit DOS application +begins executing. All standard output or error from a 16-bit DOS +application to a pipe is collected into temporary files; the application +must terminate before the temporary files are redirected to the next stage +of the pipeline. This is due to a workaround for a Windows 95 bug in the +implementation of pipes, and is how the standard Windows 95 DOS shell +handles pipes itself. +.sp +Certain applications, such as \fBcommand.com\fR, should not be executed +interactively. Applications which directly access the console window, +rather than reading from their standard input and writing to their standard +output may fail, hang Tcl, or even hang the system if their own private +console window is not available to them. +.RE +.TP +\fBMacintosh\fR +The \fBexec\fR command is not implemented and does not exist under Macintosh. +.TP +\fBUnix\fR\0\0\0\0\0\0\0 +The \fBexec\fR command is fully functional and works as described. + +.SH "SEE ALSO" +error(n), open(n) + +.SH KEYWORDS +execute, pipeline, redirection, subprocess diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/exit.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/exit.n new file mode 100644 index 0000000000000000000000000000000000000000..d06c575629da393e54f6dc1cc41d1e2b1ff53980 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/exit.n @@ -0,0 +1,31 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: exit.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH exit n "" Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +exit \- End the application +.SH SYNOPSIS +\fBexit \fR?\fIreturnCode\fR? +.BE + +.SH DESCRIPTION +.PP +Terminate the process, returning \fIreturnCode\fR to the +system as the exit status. +If \fIreturnCode\fR isn't specified then it defaults +to 0. + +.SH "SEE ALSO" +exec(n), tclvars(n) + +.SH KEYWORDS +exit, process diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/expr.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/expr.n new file mode 100644 index 0000000000000000000000000000000000000000..84016a76293b2bdae149afbff8ffe23bbce9057f --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/expr.n @@ -0,0 +1,387 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-2000 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: expr.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH expr n 8.3 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +expr \- Evaluate an expression +.SH SYNOPSIS +\fBexpr \fIarg \fR?\fIarg arg ...\fR? +.BE + +.SH DESCRIPTION +.PP +Concatenates \fIarg\fR's (adding separator spaces between them), +evaluates the result as a Tcl expression, and returns the value. +The operators permitted in Tcl expressions are a subset of +the operators permitted in C expressions, and they have the +same meaning and precedence as the corresponding C operators. +Expressions almost always yield numeric results +(integer or floating-point values). +For example, the expression +.CS +\fBexpr 8.2 + 6\fR +.CE +evaluates to 14.2. +Tcl expressions differ from C expressions in the way that +operands are specified. Also, Tcl expressions support +non-numeric operands and string comparisons. +.SH OPERANDS +.PP +A Tcl expression consists of a combination of operands, operators, +and parentheses. +White space may be used between the operands and operators and +parentheses; it is ignored by the expression's instructions. +Where possible, operands are interpreted as integer values. +Integer values may be specified in decimal (the normal case), in octal (if the +first character of the operand is \fB0\fR), or in hexadecimal (if the first +two characters of the operand are \fB0x\fR). +If an operand does not have one of the integer formats given +above, then it is treated as a floating-point number if that is +possible. Floating-point numbers may be specified in any of the +ways accepted by an ANSI-compliant C compiler (except that the +\fBf\fR, \fBF\fR, \fBl\fR, and \fBL\fR suffixes will not be permitted in +most installations). For example, all of the +following are valid floating-point numbers: 2.1, 3., 6e4, 7.91e+16. +If no numeric interpretation is possible, then an operand is left +as a string (and only a limited set of operators may be applied to +it). +.PP +Operands may be specified in any of the following ways: +.IP [1] +As an numeric value, either integer or floating-point. +.IP [2] +As a Tcl variable, using standard \fB$\fR notation. +The variable's value will be used as the operand. +.IP [3] +As a string enclosed in double-quotes. +The expression parser will perform backslash, variable, and +command substitutions on the information between the quotes, +and use the resulting value as the operand +.IP [4] +As a string enclosed in braces. +The characters between the open brace and matching close brace +will be used as the operand without any substitutions. +.IP [5] +As a Tcl command enclosed in brackets. +The command will be executed and its result will be used as +the operand. +.IP [6] +As a mathematical function whose arguments have any of the above +forms for operands, such as \fBsin($x)\fR. See below for a list of defined +functions. +.LP +Where substitutions occur above (e.g. inside quoted strings), they +are performed by the expression's instructions. +However, an additional layer of substitution may already have +been performed by the command parser before the expression +processor was called. +As discussed below, it is usually best to enclose expressions +in braces to prevent the command parser from performing substitutions +on the contents. +.PP +For some examples of simple expressions, suppose the variable +\fBa\fR has the value 3 and +the variable \fBb\fR has the value 6. +Then the command on the left side of each of the lines below +will produce the value on the right side of the line: +.CS +.ta 6c +\fBexpr 3.1 + $a 6.1 +expr 2 + "$a.$b" 5.6 +expr 4*[llength "6 2"] 8 +expr {{word one} < "word $a"} 0\fR +.CE +.SH OPERATORS +.PP +The valid operators are listed below, grouped in decreasing order +of precedence: +.TP 20 +\fB\-\0\0+\0\0~\0\0!\fR +Unary minus, unary plus, bit-wise NOT, logical NOT. None of these operands +may be applied to string operands, and bit-wise NOT may be +applied only to integers. +.TP 20 +\fB*\0\0/\0\0%\fR +Multiply, divide, remainder. None of these operands may be +applied to string operands, and remainder may be applied only +to integers. +The remainder will always have the same sign as the divisor and +an absolute value smaller than the divisor. +.TP 20 +\fB+\0\0\-\fR +Add and subtract. Valid for any numeric operands. +.TP 20 +\fB<<\0\0>>\fR +Left and right shift. Valid for integer operands only. +A right shift always propagates the sign bit. +.TP 20 +\fB<\0\0>\0\0<=\0\0>=\fR +Boolean less, greater, less than or equal, and greater than or equal. +Each operator produces 1 if the condition is true, 0 otherwise. +These operators may be applied to strings as well as numeric operands, +in which case string comparison is used. +.TP 20 +\fB==\0\0!=\fR +Boolean equal and not equal. Each operator produces a zero/one result. +Valid for all operand types. +.TP 20 +\fB&\fR +Bit-wise AND. Valid for integer operands only. +.TP 20 +\fB^\fR +Bit-wise exclusive OR. Valid for integer operands only. +.TP 20 +\fB|\fR +Bit-wise OR. Valid for integer operands only. +.TP 20 +\fB&&\fR +Logical AND. Produces a 1 result if both operands are non-zero, +0 otherwise. +Valid for boolean and numeric (integers or floating-point) operands only. +.TP 20 +\fB||\fR +Logical OR. Produces a 0 result if both operands are zero, 1 otherwise. +Valid for boolean and numeric (integers or floating-point) operands only. +.TP 20 +\fIx\fB?\fIy\fB:\fIz\fR +If-then-else, as in C. If \fIx\fR +evaluates to non-zero, then the result is the value of \fIy\fR. +Otherwise the result is the value of \fIz\fR. +The \fIx\fR operand must have a numeric value. +.LP +See the C manual for more details on the results +produced by each operator. +All of the binary operators group left-to-right within the same +precedence level. For example, the command +.CS +\fBexpr 4*2 < 7\fR +.CE +returns 0. +.PP +The \fB&&\fR, \fB||\fR, and \fB?:\fR operators have ``lazy +evaluation'', just as in C, +which means that operands are not evaluated if they are +not needed to determine the outcome. For example, in the command +.CS +\fBexpr {$v ? [a] : [b]}\fR +.CE +only one of \fB[a]\fR or \fB[b]\fR will actually be evaluated, +depending on the value of \fB$v\fR. Note, however, that this is +only true if the entire expression is enclosed in braces; otherwise +the Tcl parser will evaluate both \fB[a]\fR and \fB[b]\fR before +invoking the \fBexpr\fR command. +.SH "MATH FUNCTIONS" +.PP +Tcl supports the following mathematical functions in expressions: +.DS +.ta 3c 6c 9c +\fBabs\fR \fBcosh\fR \fBlog\fR \fBsqrt\fR +\fBacos\fR \fBdouble\fR \fBlog10\fR \fBsrand\fR +\fBasin\fR \fBexp\fR \fBpow\fR \fBtan\fR +\fBatan\fR \fBfloor\fR \fBrand\fR \fBtanh\fR +\fBatan2\fR \fBfmod\fR \fBround\fR +\fBceil\fR \fBhypot\fR \fBsin\fR +\fBcos\fR \fBint\fR \fBsinh\fR +.DE +.PP +.TP +\fBabs(\fIarg\fB)\fR +Returns the absolute value of \fIarg\fR. \fIArg\fR may be either +integer or floating-point, and the result is returned in the same form. +.TP +\fBacos(\fIarg\fB)\fR +Returns the arc cosine of \fIarg\fR, in the range [0,pi] +radians. \fIArg\fR should be in the range [-1,1]. +.TP +\fBasin(\fIarg\fB)\fR +Returns the arc sine of \fIarg\fR, in the range [-pi/2,pi/2] radians. +\fIArg\fR should be in the range [-1,1]. +.TP +\fBatan(\fIarg\fB)\fR +Returns the arc tangent of \fIarg\fR, in the range [-pi/2,pi/2] radians. +.TP +\fBatan2(\fIx, y\fB)\fR +Returns the arc tangent of \fIy\fR/\fIx\fR, in the range [-pi,pi] +radians. \fIx\fR and \fIy\fR cannot both be 0. +.TP +\fBceil(\fIarg\fB)\fR +Returns the smallest integer value not less than \fIarg\fR. +.TP +\fBcos(\fIarg\fB)\fR +Returns the cosine of \fIarg\fR, measured in radians. +.TP +\fBcosh(\fIarg\fB)\fR +Returns the hyperbolic cosine of \fIarg\fR. If the result would cause +an overflow, an error is returned. +.TP +\fBdouble(\fIarg\fB)\fR +If \fIarg\fR is a floating value, returns \fIarg\fR, otherwise converts +\fIarg\fR to floating and returns the converted value. +.TP +\fBexp(\fIarg\fB)\fR +Returns the exponential of \fIarg\fR, defined as e**\fIarg\fR. If the +result would cause an overflow, an error is returned. +.TP +\fBfloor(\fIarg\fB)\fR +Returns the largest integral value not greater than \fIarg\fR. +.TP +\fBfmod(\fIx, y\fB)\fR +Returns the floating-point remainder of the division of \fIx\fR by +\fIy\fR. If \fIy\fR is 0, an error is returned. +.TP +\fBhypot(\fIx, y\fB)\fR +Computes the length of the hypotenuse of a right-angled triangle +(\fIx\fR*\fIx\fR+\fIy\fR*\fIy\fR). +.TP +\fBint(\fIarg\fB)\fR +If \fIarg\fR is an integer value, returns \fIarg\fR, otherwise converts +\fIarg\fR to integer by truncation and returns the converted value. +.TP +\fBlog(\fIarg\fB)\fR +Returns the natural logarithm of \fIarg\fR. \fIArg\fR must be a +positive value. +.TP +\fBlog10(\fIarg\fB)\fR +Returns the base 10 logarithm of \fIarg\fR. \fIArg\fR must be a +positive value. +.TP +\fBpow(\fIx, y\fB)\fR +Computes the value of \fIx\fR raised to the power \fIy\fR. If \fIx\fR +is negative, \fIy\fR must be an integer value. +.TP +\fBrand()\fR +Returns a floating point number from zero to just less than one or, +in mathematical terms, the range [0,1). The seed comes from the +internal clock of the machine or may be set manual with the srand +function. +.TP +\fBround(\fIarg\fB)\fR +If \fIarg\fR is an integer value, returns \fIarg\fR, otherwise converts +\fIarg\fR to integer by rounding and returns the converted value. +.TP +\fBsin(\fIarg\fB)\fR +Returns the sine of \fIarg\fR, measured in radians. +.TP +\fBsinh(\fIarg\fB)\fR +Returns the hyperbolic sine of \fIarg\fR. If the result would cause +an overflow, an error is returned. +.TP +\fBsqrt(\fIarg\fB)\fR +Returns the square root of \fIarg\fR. \fIArg\fR must be non-negative. +.TP +\fBsrand(\fIarg\fB)\fR +The \fIarg\fR, which must be an integer, is used to reset the seed for +the random number generator. Returns the first random number from +that seed. Each interpreter has it's own seed. +.TP +\fBtan(\fIarg\fB)\fR +Returns the tangent of \fIarg\fR, measured in radians. +.TP +\fBtanh(\fIarg\fB)\fR +Returns the hyperbolic tangent of \fIarg\fR. +.PP +In addition to these predefined functions, applications may +define additional functions using \fBTcl_CreateMathFunc\fR(). +.SH "TYPES, OVERFLOW, AND PRECISION" +.PP +All internal computations involving integers are done with the C type +\fIlong\fR, and all internal computations involving floating-point are +done with the C type \fIdouble\fR. +When converting a string to floating-point, exponent overflow is +detected and results in a Tcl error. +For conversion to integer from string, detection of overflow depends +on the behavior of some routines in the local C library, so it should +be regarded as unreliable. +In any case, integer overflow and underflow are generally not detected +reliably for intermediate results. Floating-point overflow and underflow +are detected to the degree supported by the hardware, which is generally +pretty reliable. +.PP +Conversion among internal representations for integer, floating-point, +and string operands is done automatically as needed. +For arithmetic computations, integers are used until some +floating-point number is introduced, after which floating-point is used. +For example, +.CS +\fBexpr 5 / 4\fR +.CE +returns 1, while +.CS +\fBexpr 5 / 4.0\fR +\fBexpr 5 / ( [string length "abcd"] + 0.0 )\fR +.CE +both return 1.25. +Floating-point values are always returned with a ``\fB.\fR'' +or an \fBe\fR so that they will not look like integer values. For +example, +.CS +\fBexpr 20.0/5.0\fR +.CE +returns \fB4.0\fR, not \fB4\fR. + +.SH "STRING OPERATIONS" +.PP +String values may be used as operands of the comparison operators, +although the expression evaluator tries to do comparisons as integer +or floating-point when it can. +If one of the operands of a comparison is a string and the other +has a numeric value, the numeric operand is converted back to +a string using the C \fIsprintf\fR format specifier +\fB%d\fR for integers and \fB%g\fR for floating-point values. +For example, the commands +.CS +\fBexpr {"0x03" > "2"}\fR +\fBexpr {"0y" < "0x12"}\fR +.CE +both return 1. The first comparison is done using integer +comparison, and the second is done using string comparison after +the second operand is converted to the string \fB18\fR. +Because of Tcl's tendency to treat values as numbers whenever +possible, it isn't generally a good idea to use operators like \fB==\fR +when you really want string comparison and the values of the +operands could be arbitrary; it's better in these cases to use +the \fBstring\fR command instead. + +.SH "PERFORMANCE CONSIDERATIONS" +.PP +Enclose expressions in braces for the best speed and the smallest +storage requirements. +This allows the Tcl bytecode compiler to generate the best code. +.PP +As mentioned above, expressions are substituted twice: +once by the Tcl parser and once by the \fBexpr\fR command. +For example, the commands +.CS +\fBset a 3\fR +\fBset b {$a + 2}\fR +\fBexpr $b*4\fR +.CE +return 11, not a multiple of 4. +This is because the Tcl parser will first substitute \fB$a + 2\fR for +the variable \fBb\fR, +then the \fBexpr\fR command will evaluate the expression \fB$a + 2*4\fR. +.PP +Most expressions do not require a second round of substitutions. +Either they are enclosed in braces or, if not, +their variable and command substitutions yield numbers or strings +that don't themselves require substitutions. +However, because a few unbraced expressions +need two rounds of substitutions, +the bytecode compiler must emit +additional instructions to handle this situation. +The most expensive code is required for +unbraced expressions that contain command substitutions. +These expressions must be implemented by generating new code +each time the expression is executed. + +.SH KEYWORDS +arithmetic, boolean, compare, expression, fuzzy comparison diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/fblocked.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/fblocked.n new file mode 100644 index 0000000000000000000000000000000000000000..79ffca98c9ae716a3ce36bece6447fe698b19102 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/fblocked.n @@ -0,0 +1,33 @@ +'\" +'\" Copyright (c) 1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: fblocked.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +.so man.macros +.TH fblocked n 7.5 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +fblocked \- Test whether the last input operation exhausted all available input +.SH SYNOPSIS +\fBfblocked \fIchannelId\fR +.BE + +.SH DESCRIPTION +.PP +The \fBfblocked\fR command returns 1 if the most recent input operation +on \fIchannelId\fR returned less information than requested because all +available input was exhausted. +For example, if \fBgets\fR is invoked when there are only three +characters available for input and no end-of-line sequence, \fBgets\fR +returns an empty string and a subsequent call to \fBfblocked\fR will +return 1. +.PP + +.SH "SEE ALSO" +gets(n), open(n), read(n) + +.SH KEYWORDS +blocking, nonblocking diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/fconfigure.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/fconfigure.n new file mode 100644 index 0000000000000000000000000000000000000000..05a47598a9dd4c29cc25a728fb4ce007b50eeeeb --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/fconfigure.n @@ -0,0 +1,201 @@ +'\" +'\" Copyright (c) 1995-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: fconfigure.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH fconfigure n 8.1 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +fconfigure \- Set and get options on a channel +.SH SYNOPSIS +.nf +\fBfconfigure \fIchannelId\fR +\fBfconfigure \fIchannelId\fR \fIname\fR +\fBfconfigure \fIchannelId\fR \fIname value \fR?\fIname value ...\fR? +.fi +.BE + +.SH DESCRIPTION +.PP +The \fBfconfigure\fR command sets and retrieves options for channels. +\fIChannelId\fR identifies the channel for which to set or query an option. +If no \fIname\fR or \fIvalue\fR arguments are supplied, the command +returns a list containing alternating option names and values for the channel. +If \fIname\fR is supplied but no \fIvalue\fR then the command returns +the current value of the given option. +If one or more pairs of \fIname\fR and \fIvalue\fR are supplied, the +command sets each of the named options to the corresponding \fIvalue\fR; +in this case the return value is an empty string. +.PP +The options described below are supported for all channels. In addition, +each channel type may add options that only it supports. See the manual +entry for the command that creates each type of channels for the options +that that specific type of channel supports. For example, see the manual +entry for the \fBsocket\fR command for its additional options. +.TP +\fB\-blocking\fR \fIboolean\fR +The \fB\-blocking\fR option determines whether I/O operations on the +channel can cause the process to block indefinitely. +The value of the option must be a proper boolean value. +Channels are normally in blocking mode; if a channel is placed into +nonblocking mode it will affect the operation of the \fBgets\fR, +\fBread\fR, \fBputs\fR, \fBflush\fR, and \fBclose\fR commands; +see the documentation for those commands for details. +For nonblocking mode to work correctly, the application must be +using the Tcl event loop (e.g. by calling \fBTcl_DoOneEvent\fR or +invoking the \fBvwait\fR command). +.TP +\fB\-buffering\fR \fInewValue\fR +. +If \fInewValue\fR is \fBfull\fR then the I/O system will buffer output +until its internal buffer is full or until the \fBflush\fR command is +invoked. If \fInewValue\fR is \fBline\fR, then the I/O system will +automatically flush output for the channel whenever a newline character +is output. If \fInewValue\fR is \fBnone\fR, the I/O system will flush +automatically after every output operation. The default is for +\fB\-buffering\fR to be set to \fBfull\fR except for channels that +connect to terminal-like devices; for these channels the initial setting +is \fBline\fR. Additionally, \fBstdin\fR and \fBstdout\fR are +intially set to \fBline\fR, and \fBstderr\fR is set to \fBnone\fR. +.TP +\fB\-buffersize\fR \fInewSize\fR +. +\fINewvalue\fR must be an integer; its value is used to set the size of +buffers, in bytes, subsequently allocated for this channel to store input +or output. \fINewvalue\fR must be between ten and one million, allowing +buffers of ten to one million bytes in size. +.VS 8.1 br +.TP +\fB\-encoding\fR \fIname\fR +. +This option is used to specify the encoding of the channel, so that the data +can be converted to and from Unicode for use in Tcl. For instance, in +order for Tcl to read characters from a Japanese file in \fBshiftjis\fR +and properly process and display the contents, the encoding would be set +to \fBshiftjis\fR. Thereafter, when reading from the channel, the bytes in +the Japanese file would be converted to Unicode as they are read. +Writing is also supported \- as Tcl strings are written to the channel they +will automatically be converted to the specified encoding on output. +.RS +.PP +If a file contains pure binary data (for instance, a JPEG image), the +encoding for the channel should be configured to be \fBbinary\fR. Tcl +will then assign no interpretation to the data in the file and simply read or +write raw bytes. The Tcl \fBbinary\fR command can be used to manipulate this +byte-oriented data. +.PP +The default encoding for newly opened channels is the same platform- and +locale-dependent system encoding used for interfacing with the operating +system. +.RE +.VE +.TP +\fB\-eofchar\fR \fIchar\fR +.TP +\fB\-eofchar\fR \fB{\fIinChar outChar\fB}\fR +. +This option supports DOS file systems that use Control-z (\ex1a) as an +end of file marker. If \fIchar\fR is not an empty string, then this +character signals end-of-file when it is encountered during input. For +output, the end-of-file character is output when the channel is closed. +If \fIchar\fR is the empty string, then there is no special end of file +character marker. For read-write channels, a two-element list specifies +the end of file marker for input and output, respectively. As a +convenience, when setting the end-of-file character for a read-write +channel you can specify a single value that will apply to both reading +and writing. When querying the end-of-file character of a read-write +channel, a two-element list will always be returned. The default value +for \fB\-eofchar\fR is the empty string in all cases except for files +under Windows. In that case the \fB\-eofchar\fR is Control-z (\ex1a) for +reading and the empty string for writing. +.TP +\fB\-translation\fR \fImode\fR +.TP +\fB\-translation\fR \fB{\fIinMode outMode\fB}\fR +. +In Tcl scripts the end of a line is always represented using a single +newline character (\en). However, in actual files and devices the end of +a line may be represented differently on different platforms, or even for +different devices on the same platform. For example, under UNIX newlines +are used in files, whereas carriage-return-linefeed sequences are +normally used in network connections. On input (i.e., with \fBgets\fP +and \fBread\fP) the Tcl I/O system automatically translates the external +end-of-line representation into newline characters. Upon output (i.e., +with \fBputs\fP), the I/O system translates newlines to the external +end-of-line representation. The default translation mode, \fBauto\fP, +handles all the common cases automatically, but the \fB\-translation\fR +option provides explicit control over the end of line translations. +.RS +.PP +The value associated with \fB\-translation\fR is a single item for +read-only and write-only channels. The value is a two-element list for +read-write channels; the read translation mode is the first element of +the list, and the write translation mode is the second element. As a +convenience, when setting the translation mode for a read-write channel +you can specify a single value that will apply to both reading and +writing. When querying the translation mode of a read-write channel, a +two-element list will always be returned. The following values are +currently supported: +.TP +\fBauto\fR +. +As the input translation mode, \fBauto\fR treats any of newline +(\fBlf\fP), carriage return (\fBcr\fP), or carriage return followed by a +newline (\fBcrlf\fP) as the end of line representation. The end of line +representation can even change from line-to-line, and all cases are +translated to a newline. As the output translation mode, \fBauto\fR +chooses a platform specific representation; for sockets on all platforms +Tcl chooses \fBcrlf\fR, for all Unix flavors, it chooses \fBlf\fR, for the +Macintosh platform it chooses \fBcr\fR and for the various flavors of +Windows it chooses \fBcrlf\fR. The default setting for +\fB\-translation\fR is \fBauto\fR for both input and output. +.VS 8.1 br +.TP +\fBbinary\fR +. +No end-of-line translations are performed. This is nearly identical to +\fBlf\fP mode, except that in addition \fBbinary\fP mode also sets the +end-of-file character to the empty string (which disables it) and sets the +encoding to \fBbinary\fR (which disables encoding filtering). See the +description of \fB\-eofchar\fR and \fB\-encoding\fR for more information. +.VE +.TP +\fBcr\fR +. +The end of a line in the underlying file or device is represented by a +single carriage return character. As the input translation mode, +\fBcr\fP mode converts carriage returns to newline characters. As the +output translation mode, \fBcr\fP mode translates newline characters to +carriage returns. This mode is typically used on Macintosh platforms. +.TP +\fBcrlf\fR +. +The end of a line in the underlying file or device is represented by a +carriage return character followed by a linefeed character. As the input +translation mode, \fBcrlf\fP mode converts carriage-return-linefeed +sequences to newline characters. As the output translation mode, +\fBcrlf\fP mode translates newline characters to carriage-return-linefeed +sequences. This mode is typically used on Windows platforms and for +network connections. +.TP +\fBlf\fR +. +The end of a line in the underlying file or device is represented by a +single newline (linefeed) character. In this mode no translations occur +during either input or output. This mode is typically used on UNIX +platforms. +.RE +.PP + +.SH "SEE ALSO" +close(n), flush(n), gets(n), puts(n), read(n), socket(n) + +.SH KEYWORDS +blocking, buffering, carriage return, end of line, flushing, linemode, +newline, nonblocking, platform, translation, encoding, filter, byte array, +binary diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/fcopy.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/fcopy.n new file mode 100644 index 0000000000000000000000000000000000000000..733b90daf7a7591827b96899fc6b2b2515199ca8 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/fcopy.n @@ -0,0 +1,127 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1997 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: fcopy.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH fcopy n 8.0 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +fcopy \- Copy data from one channel to another. +.SH SYNOPSIS +\fBfcopy \fIinchan\fR \fIoutchan\fR ?\fB\-size \fIsize\fR? ?\fB\-command \fIcallback\fR? +.BE + +.SH DESCRIPTION +.PP +The \fBfcopy\fP command copies data from one I/O channel, \fIinchan\fR to another I/O channel, \fIoutchan\fR. +The \fBfcopy\fP command leverages the buffering in the Tcl I/O system to +avoid extra copies and to avoid buffering too much data in +main memory when copying large files to slow destinations like +network sockets. +.PP +The \fBfcopy\fP +command transfers data from \fIinchan\fR until end of file +or \fIsize\fP bytes have been +transferred. If no \fB\-size\fP argument is given, +then the copy goes until end of file. +All the data read from \fIinchan\fR is copied to \fIoutchan\fR. +Without the \fB\-command\fP option, \fBfcopy\fP blocks until the copy is complete +and returns the number of bytes written to \fIoutchan\fR. +.PP +The \fB\-command\fP argument makes \fBfcopy\fP work in the background. +In this case it returns immediately and the \fIcallback\fP is invoked +later when the copy completes. +The \fIcallback\fP is called with +one or two additional +arguments that indicates how many bytes were written to \fIoutchan\fR. +If an error occurred during the background copy, the second argument is the +error string associated with the error. +With a background copy, +it is not necessary to put \fIinchan\fR or \fIoutchan\fR into +non-blocking mode; the \fBfcopy\fP command takes care of that automatically. +However, it is necessary to enter the event loop by using +the \fBvwait\fP command or by using Tk. +.PP +You are not allowed to do other I/O operations with +\fIinchan\fR or \fIoutchan\fR during a background fcopy. +If either \fIinchan\fR or \fIoutchan\fR get closed +while the copy is in progress, the current copy is stopped +and the command callback is \fInot\fP made. +If \fIinchan\fR is closed, +then all data already queued for \fIoutchan\fR is written out. +.PP +Note that \fIinchan\fR can become readable during a background copy. +You should turn off any \fBfileevent\fP handlers during a background +copy so those handlers do not interfere with the copy. +Any I/O attempted by a \fBfileevent\fP handler will get a "channel busy" error. +.PP +\fBFcopy\fR translates end-of-line sequences in \fIinchan\fR and \fIoutchan\fR +according to the \fB\-translation\fR option +for these channels. +See the manual entry for \fBfconfigure\fR for details on the +\fB\-translation\fR option. +The translations mean that the number of bytes read from \fIinchan\fR +can be different than the number of bytes written to \fIoutchan\fR. +Only the number of bytes written to \fIoutchan\fR is reported, +either as the return value of a synchronous \fBfcopy\fP or +as the argument to the callback for an asynchronous \fBfcopy\fP. + +.SH EXAMPLE +.PP +This first example shows how the callback gets +passed the number of bytes transferred. +It also uses vwait to put the application into the event loop. +Of course, this simplified example could be done without the command +callback. +.DS +proc Cleanup {in out bytes {error {}}} { + global total + set total $bytes + close $in + close $out + if {[string length $error] != 0} { + # error occurred during the copy + } +} +set in [open $file1] +set out [socket $server $port] +fcopy $in $out -command [list Cleanup $in $out] +vwait total + +.DE +.PP +The second example copies in chunks and tests for end of file +in the command callback +.DS +proc CopyMore {in out chunk bytes {error {}}} { + global total done + incr total $bytes + if {([string length $error] != 0) || [eof $in] { + set done $total + close $in + close $out + } else { + fcopy $in $out -command [list CopyMore $in $out $chunk] \\ + -size $chunk + } +} +set in [open $file1] +set out [socket $server $port] +set chunk 1024 +set total 0 +fcopy $in $out -command [list CopyMore $in $out $chunk] -size $chunk +vwait done + +.DE + +.SH "SEE ALSO" +eof(n), fblocked(n), fconfigure(n) + +.SH KEYWORDS +blocking, channel, end of line, end of file, nonblocking, read, translation diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/file.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/file.n new file mode 100644 index 0000000000000000000000000000000000000000..354b284d2b73513267ea2db23679bbf3b9b58c14 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/file.n @@ -0,0 +1,344 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: file.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH file n 8.3 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +file \- Manipulate file names and attributes +.SH SYNOPSIS +\fBfile \fIoption\fR \fIname\fR ?\fIarg arg ...\fR? +.BE + +.SH DESCRIPTION +.PP +This command provides several operations on a file's name or attributes. +\fIName\fR is the name of a file; if it starts with a tilde, then tilde +substitution is done before executing the command (see the manual entry for +\fBfilename\fR for details). \fIOption\fR indicates what to do with the +file name. Any unique abbreviation for \fIoption\fR is acceptable. The +valid options are: +.TP +\fBfile atime \fIname\fR ?\fBtime\fR? +. +Returns a decimal string giving the time at which file \fIname\fR was last +accessed. If \fItime\fR is specified, it is an access time to set +for the file. The time is measured in the standard POSIX fashion as +seconds from a fixed starting time (often January 1, 1970). If the file +doesn't exist or its access time cannot be queried or set then an error is +generated. On Windows, FAT file systems do not support access time. +.TP +\fBfile attributes \fIname\fR +.br +\fBfile attributes \fIname\fR ?\fBoption\fR? +.br +\fBfile attributes \fIname\fR ?\fBoption value option value...\fR? +.RS +This subcommand returns or sets platform specific values associated +with a file. The first form returns a list of the platform specific +flags and their values. The second form returns the value for the +specific option. The third form sets one or more of the values. The +values are as follows: +.PP +On Unix, \fB-group\fR gets or sets the group name for the file. A group id +can be given to the command, but it returns a group name. \fB-owner\fR gets +or sets the user name of the owner of the file. The command returns the +owner name, but the numerical id can be passed when setting the +owner. \fB-permissions\fR sets or retrieves the octal code that chmod(1) +uses. This command does also has limited support for setting using the +symbolic attributes for chmod(1), of the form [ugo]?[[+\-=][rwxst],[...]], +where multiple symbolic attributes can be separated by commas (example: +\fBu+s,go\-rw\fR add sticky bit for user, remove read and write +permissions for group and other). A simplified \fBls\fR style string, +of the form rwxrwxrwx (must be 9 characters), is also supported +(example: \fBrwxr\-xr\-t\fR is equivalent to 01755). +.PP +On Windows, \fB-archive\fR gives the value or sets or clears the +archive attribute of the file. \fB-hidden\fR gives the value or sets +or clears the hidden attribute of the file. \fB-longname\fR will +expand each path element to its long version. This attribute cannot be +set. \fB-readonly\fR gives the value or sets or clears the readonly +attribute of the file. \fB-shortname\fR gives a string where every +path element is replaced with its short (8.3) version of the +name. This attribute cannot be set. \fB-system\fR gives or sets or +clears the value of the system attribute of the file. +.PP +On Macintosh, \fB-creator\fR gives or sets the Finder creator type of +the file. \fB-hidden\fR gives or sets or clears the hidden attribute +of the file. \fB-readonly\fR gives or sets or clears the readonly +attribute of the file. Note that directories can only be locked if +File Sharing is turned on. \fB-type\fR gives or sets the Finder file +type for the file. +.RE +.VS +.TP +\fBfile channels ?\fIpattern\fR? +. +If \fIpattern\fR isn't specified, returns a list of names of all +registered open channels in this interpreter. If \fIpattern\fR is +specified, only those names matching \fIpattern\fR are returned. Matching +is determined using the same rules as for \fBstring match\fR. +.VE +.TP +\fBfile copy \fR?\fB\-force\fR? ?\fB\-\|\-\fR? \fIsource\fR \fItarget\fR +.br +\fBfile copy \fR?\fB\-force\fR? ?\fB\-\|\-\fR? \fIsource\fR ?\fIsource\fR ...? \fItargetDir\fR +.RS +The first form makes a copy of the file or directory \fIsource\fR under +the pathname \fItarget\fR. If \fItarget\fR is an existing directory, +then the second form is used. The second form makes a copy inside +\fItargetDir\fR of each \fIsource\fR file listed. If a directory is +specified as a \fIsource\fR, then the contents of the directory will be +recursively copied into \fItargetDir\fR. Existing files will not be +overwritten unless the \fB\-force\fR option is specified. Trying to +overwrite a non-empty directory, overwrite a directory with a file, or a +file with a directory will all result in errors even if \fI\-force\fR was +specified. Arguments are processed in the order specified, halting at the +first error, if any. A \fB\-\|\-\fR marks the end of switches; the argument +following the \fB\-\|\-\fR will be treated as a \fIsource\fR even if it +starts with a \fB\-\fR. +.RE +.TP +\fBfile delete \fR?\fB\-force\fR? ?\fB\-\|\-\fR? \fIpathname\fR ?\fIpathname\fR ... ? +. +Removes the file or directory specified by each \fIpathname\fR argument. +Non-empty directories will be removed only if the \fB\-force\fR option is +specified. Trying to delete a non-existant file is not considered an +error. Trying to delete a read-only file will cause the file to be deleted, +even if the \fB\-force\fR flags is not specified. Arguments are processed +in the order specified, halting at the first error, if any. A \fB\-\|\-\fR +marks the end of switches; the argument following the \fB\-\|\-\fR will be +treated as a \fIpathname\fR even if it starts with a \fB\-\fR. +.TP +\fBfile dirname \fIname\fR +Returns a name comprised of all of the path components in \fIname\fR +excluding the last element. If \fIname\fR is a relative file name and +only contains one path element, then returns ``\fB.\fR'' (or ``\fB:\fR'' +on the Macintosh). If \fIname\fR refers to a root directory, then the +root directory is returned. For example, +.RS +.CS +\fBfile dirname c:/\fR +.CE +returns \fBc:/\fR. +.PP +Note that tilde substitution will only be +performed if it is necessary to complete the command. For example, +.CS +\fBfile dirname ~/src/foo.c\fR +.CE +returns \fB~/src\fR, whereas +.CS +\fBfile dirname ~\fR +.CE +returns \fB/home\fR (or something similar). +.RE +.TP +\fBfile executable \fIname\fR +. +Returns \fB1\fR if file \fIname\fR is executable by the current user, +\fB0\fR otherwise. +.TP +\fBfile exists \fIname\fR +. +Returns \fB1\fR if file \fIname\fR exists and the current user has +search privileges for the directories leading to it, \fB0\fR otherwise. +.TP +\fBfile extension \fIname\fR +. +Returns all of the characters in \fIname\fR after and including the last +dot in the last element of \fIname\fR. If there is no dot in the last +element of \fIname\fR then returns the empty string. +.TP +\fBfile isdirectory \fIname\fR +. +Returns \fB1\fR if file \fIname\fR is a directory, \fB0\fR otherwise. +.TP +\fBfile isfile \fIname\fR +. +Returns \fB1\fR if file \fIname\fR is a regular file, \fB0\fR otherwise. +.TP +\fBfile join \fIname\fR ?\fIname ...\fR? +. +Takes one or more file names and combines them, using the correct path +separator for the current platform. If a particular \fIname\fR is +relative, then it will be joined to the previous file name argument. +Otherwise, any earlier arguments will be discarded, and joining will +proceed from the current argument. For example, +.RS +.CS +\fBfile join a b /foo bar\fR +.CE +returns \fB/foo/bar\fR. +.PP +Note that any of the names can contain separators, and that the result +is always canonical for the current platform: \fB/\fR for Unix and +Windows, and \fB:\fR for Macintosh. +.RE +.TP +\fBfile lstat \fIname varName\fR +. +Same as \fBstat\fR option (see below) except uses the \fIlstat\fR +kernel call instead of \fIstat\fR. This means that if \fIname\fR +refers to a symbolic link the information returned in \fIvarName\fR +is for the link rather than the file it refers to. On systems that +don't support symbolic links this option behaves exactly the same +as the \fBstat\fR option. +.TP +\fBfile mkdir \fIdir\fR ?\fIdir\fR ...? +. +Creates each directory specified. For each pathname \fIdir\fR specified, +this command will create all non-existing parent directories as +well as \fIdir\fR itself. If an existing directory is specified, then +no action is taken and no error is returned. Trying to overwrite an existing +file with a directory will result in an error. Arguments are processed in +the order specified, halting at the first error, if any. +.TP +\fBfile mtime \fIname\fR ?\fItime\fR? +. +Returns a decimal string giving the time at which file \fIname\fR was last +modified. If \fItime\fR is specified, it is a modification time to set for +the file (equivalent to Unix \fBtouch\fR). The time is measured in the +standard POSIX fashion as seconds from a fixed starting time (often January +1, 1970). If the file doesn't exist or its modified time cannot be queried +or set then an error is generated. +.TP +\fBfile nativename \fIname\fR +. +Returns the platform-specific name of the file. This is useful if the +filename is needed to pass to a platform-specific call, such as exec +under Windows or AppleScript on the Macintosh. +.TP +\fBfile owned \fIname\fR +. +Returns \fB1\fR if file \fIname\fR is owned by the current user, \fB0\fR +otherwise. +.TP +\fBfile pathtype \fIname\fR +. +Returns one of \fBabsolute\fR, \fBrelative\fR, \fBvolumerelative\fR. If +\fIname\fR refers to a specific file on a specific volume, the path type +will be \fBabsolute\fR. If \fIname\fR refers to a file relative to the +current working directory, then the path type will be \fBrelative\fR. If +\fIname\fR refers to a file relative to the current working directory on +a specified volume, or to a specific file on the current working volume, then +the file type is \fBvolumerelative\fR. +.TP +\fBfile readable \fIname\fR +. +Returns \fB1\fR if file \fIname\fR is readable by the current user, +\fB0\fR otherwise. +.TP +\fBfile readlink \fIname\fR +. +Returns the value of the symbolic link given by \fIname\fR (i.e. the name +of the file it points to). If \fIname\fR isn't a symbolic link or its +value cannot be read, then an error is returned. On systems that don't +support symbolic links this option is undefined. +.PP +\fBfile rename \fR?\fB\-force\fR? ?\fB\-\|\-\fR? \fIsource\fR \fItarget\fR +.br +\fBfile rename \fR?\fB\-force\fR? ?\fB\-\|\-\fR? \fIsource\fR ?\fIsource\fR ...? \fItargetDir\fR +.RS +The first form takes the file or directory specified by pathname +\fIsource\fR and renames it to \fItarget\fR, moving the file if the +pathname \fItarget\fR specifies a name in a different directory. If +\fItarget\fR is an existing directory, then the second form is used. The +second form moves each \fIsource\fR file or directory into the directory +\fItargetDir\fR. Existing files will not be overwritten unless the +\fB\-force\fR option is specified. Trying to overwrite a non-empty +directory, overwrite a directory with a file, or a file with a directory +will all result in errors. Arguments are processed in the order specified, +halting at the first error, if any. A \fB\-\|\-\fR marks the end of +switches; the argument following the \fB\-\|\-\fR will be treated as a +\fIsource\fR even if it starts with a \fB\-\fR. +.RE +.TP +\fBfile rootname \fIname\fR +. +Returns all of the characters in \fIname\fR up to but not including the +last ``.'' character in the last component of name. If the last +component of \fIname\fR doesn't contain a dot, then returns \fIname\fR. +.TP +\fBfile size \fIname\fR +. +Returns a decimal string giving the size of file \fIname\fR in bytes. If +the file doesn't exist or its size cannot be queried then an error is +generated. +.TP +\fBfile split \fIname\fR +. +Returns a list whose elements are the path components in \fIname\fR. The +first element of the list will have the same path type as \fIname\fR. +All other elements will be relative. Path separators will be discarded +unless they are needed ensure that an element is unambiguously relative. +For example, under Unix +.RS +.CS +\fBfile split /foo/~bar/baz\fR +.CE +returns \fB/\0\0foo\0\0./~bar\0\0baz\fR to ensure that later commands +that use the third component do not attempt to perform tilde +substitution. +.RE +.TP +\fBfile stat \fIname varName\fR +. +Invokes the \fBstat\fR kernel call on \fIname\fR, and uses the variable +given by \fIvarName\fR to hold information returned from the kernel call. +\fIVarName\fR is treated as an array variable, and the following elements +of that variable are set: \fBatime\fR, \fBctime\fR, \fBdev\fR, \fBgid\fR, +\fBino\fR, \fBmode\fR, \fBmtime\fR, \fBnlink\fR, \fBsize\fR, \fBtype\fR, +\fBuid\fR. Each element except \fBtype\fR is a decimal string with the +value of the corresponding field from the \fBstat\fR return structure; +see the manual entry for \fBstat\fR for details on the meanings of the +values. The \fBtype\fR element gives the type of the file in the same +form returned by the command \fBfile type\fR. This command returns an +empty string. +.TP +\fBfile tail \fIname\fR +. +Returns all of the characters in \fIname\fR after the last directory +separator. If \fIname\fR contains no separators then returns +\fIname\fR. +.TP +\fBfile type \fIname\fR +. +Returns a string giving the type of file \fIname\fR, which will be one of +\fBfile\fR, \fBdirectory\fR, \fBcharacterSpecial\fR, \fBblockSpecial\fR, +\fBfifo\fR, \fBlink\fR, or \fBsocket\fR. +.TP +\fBfile volume\fR +. +Returns the absolute paths to the volumes mounted on the system, as a +proper Tcl list. On the Macintosh, this will be a list of the mounted +drives, both local and network. N.B. if two drives have the same name, +they will both appear on the volume list, but there is currently no way, +from Tcl, to access any but the first of these drives. On UNIX, the +command will always return "/", since all filesystems are locally mounted. +On Windows, it will return a list of the available local drives +(e.g. {a:/ c:/}). +.TP +\fBfile writable \fIname\fR +. +Returns \fB1\fR if file \fIname\fR is writable by the current user, +\fB0\fR otherwise. +.SH "PORTABILITY ISSUES" +.TP +\fBUnix\fR\0\0\0\0\0\0\0 +. +These commands always operate using the real user and group identifiers, +not the effective ones. + +.SH "SEE ALSO" +filename + +.SH KEYWORDS +attributes, copy files, delete files, directory, file, move files, name, rename files, stat diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/fileevent.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/fileevent.n new file mode 100644 index 0000000000000000000000000000000000000000..de581882d5ec0369d8e7f855d38ea1ff1343da21 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/fileevent.n @@ -0,0 +1,109 @@ +'\" +'\" Copyright (c) 1994 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: fileevent.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH fileevent n 7.5 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +fileevent \- Execute a script when a channel becomes readable or writable +.SH SYNOPSIS +\fBfileevent \fIchannelId \fBreadable \fR?\fIscript\fR? +.sp +\fBfileevent \fIchannelId \fBwritable \fR?\fIscript\fR? +.BE + +.SH DESCRIPTION +.PP +This command is used to create \fIfile event handlers\fR. A file event +handler is a binding between a channel and a script, such that the script +is evaluated whenever the channel becomes readable or writable. File event +handlers are most commonly used to allow data to be received from another +process on an event-driven basis, so that the receiver can continue to +interact with the user while waiting for the data to arrive. If an +application invokes \fBgets\fR or \fBread\fR on a blocking channel when +there is no input data available, the process will block; until the input +data arrives, it will not be able to service other events, so it will +appear to the user to ``freeze up''. With \fBfileevent\fR, the process can +tell when data is present and only invoke \fBgets\fR or \fBread\fR when +they won't block. +.PP +The \fIchannelId\fR argument to \fBfileevent\fR refers to an open channel, +such as the return value from a previous \fBopen\fR or \fBsocket\fR +command. +If the \fIscript\fR argument is specified, then \fBfileevent\fR +creates a new event handler: \fIscript\fR will be evaluated +whenever the channel becomes readable or writable (depending on the +second argument to \fBfileevent\fR). +In this case \fBfileevent\fR returns an empty string. +The \fBreadable\fR and \fBwritable\fR event handlers for a file +are independent, and may be created and deleted separately. +However, there may be at most one \fBreadable\fR and one \fBwritable\fR +handler for a file at a given time in a given interpreter. +If \fBfileevent\fR is called when the specified handler already +exists in the invoking interpreter, the new script replaces the old one. +.PP +If the \fIscript\fR argument is not specified, \fBfileevent\fR +returns the current script for \fIchannelId\fR, or an empty string +if there is none. +If the \fIscript\fR argument is specified as an empty string +then the event handler is deleted, so that no script will be invoked. +A file event handler is also deleted automatically whenever +its channel is closed or its interpreter is deleted. +.PP +A channel is considered to be readable if there is unread data +available on the underlying device. +A channel is also considered to be readable if there is unread +data in an input buffer, except in the special case where the +most recent attempt to read from the channel was a \fBgets\fR +call that could not find a complete line in the input buffer. +This feature allows a file to be read a line at a time in nonblocking mode +using events. +A channel is also considered to be readable if an end of file or +error condition is present on the underlying file or device. +It is important for \fIscript\fR to check for these conditions +and handle them appropriately; for example, if there is no special +check for end of file, an infinite loop may occur where \fIscript\fR +reads no data, returns, and is immediately invoked again. +.PP +A channel is considered to be writable if at least one byte of data +can be written to the underlying file or device without blocking, +or if an error condition is present on the underlying file or device. +.PP +Event-driven I/O works best for channels that have been +placed into nonblocking mode with the \fBfconfigure\fR command. +In blocking mode, a \fBputs\fR command may block if you give it +more data than the underlying file or device can accept, and a +\fBgets\fR or \fBread\fR command will block if you attempt to read +more data than is ready; no events will be processed while the +commands block. +In nonblocking mode \fBputs\fR, \fBread\fR, and \fBgets\fR never block. +See the documentation for the individual commands for information +on how they handle blocking and nonblocking channels. +.PP +The script for a file event is executed at global level (outside the +context of any Tcl procedure) in the interpreter in which the +\fBfileevent\fR command was invoked. +If an error occurs while executing the script then the +\fBbgerror\fR mechanism is used to report the error. +In addition, the file event handler is deleted if it ever returns +an error; this is done in order to prevent infinite loops due to +buggy handlers. + +.SH CREDITS +.PP +\fBfileevent\fR is based on the \fBaddinput\fR command created +by Mark Diekhans. + +.SH "SEE ALSO" +bgerror(n), fconfigure(n), gets(n), puts(n), read(n) + +.SH KEYWORDS +asynchronous I/O, blocking, channel, event handler, nonblocking, readable, +script, writable. diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/filename.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/filename.n new file mode 100644 index 0000000000000000000000000000000000000000..33fb52bcd24efc3b23fb3a31ae564c20c9cf1c64 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/filename.n @@ -0,0 +1,200 @@ +'\" +'\" Copyright (c) 1995-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: filename.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH filename n 7.5 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +filename \- File name conventions supported by Tcl commands +.BE +.SH INTRODUCTION +.PP +All Tcl commands and C procedures that take file names as arguments +expect the file names to be in one of three forms, depending on the +current platform. On each platform, Tcl supports file names in the +standard forms(s) for that platform. In addition, on all platforms, +Tcl supports a Unix-like syntax intended to provide a convenient way +of constructing simple file names. However, scripts that are intended +to be portable should not assume a particular form for file names. +Instead, portable scripts must use the \fBfile split\fR and \fBfile +join\fR commands to manipulate file names (see the \fBfile\fR manual +entry for more details). + +.SH "PATH TYPES" +.PP +File names are grouped into three general types based on the starting point +for the path used to specify the file: absolute, relative, and +volume-relative. Absolute names are completely qualified, giving a path to +the file relative to a particular volume and the root directory on that +volume. Relative names are unqualified, giving a path to the file relative +to the current working directory. Volume-relative names are partially +qualified, either giving the path relative to the root directory on the +current volume, or relative to the current directory of the specified +volume. The \fBfile pathtype\fR command can be used to determine the +type of a given path. + +.SH "PATH SYNTAX" +.PP +The rules for native names depend on the value reported in the Tcl +array element \fBtcl_platform(platform)\fR: +.TP 10 +\fBmac\fR +On Apple Macintosh systems, Tcl supports two forms of path names. The +normal Mac style names use colons as path separators. Paths may be +relative or absolute, and file names may contain any character other +than colon. A leading colon causes the rest of the path to be +interpreted relative to the current directory. If a path contains a +colon that is not at the beginning, then the path is interpreted as an +absolute path. Sequences of two or more colons anywhere in the path +are used to construct relative paths where \fB::\fR refers to the +parent of the current directory, \fB:::\fR refers to the parent of the +parent, and so forth. +.RS +.PP +In addition to Macintosh style names, Tcl also supports a subset of +Unix-like names. If a path contains no colons, then it is interpreted +like a Unix path. Slash is used as the path separator. The file name +\fB\&.\fR refers to the current directory, and \fB\&..\fR refers to the +parent of the current directory. However, some names like \fB/\fR or +\fB/..\fR have no mapping, and are interpreted as Macintosh names. In +general, commands that generate file names will return Macintosh style +names, but commands that accept file names will take both Macintosh +and Unix-style names. +.PP +The following examples illustrate various forms of path names: +.TP 15 +\fB:\fR +Relative path to the current folder. +.TP 15 +\fBMyFile\fR +Relative path to a file named \fBMyFile\fR in the current folder. +.TP 15 +\fBMyDisk:MyFile\fR +Absolute path to a file named \fBMyFile\fR on the device named \fBMyDisk\fR. +.TP 15 +\fB:MyDir:MyFile\fR +Relative path to a file name \fBMyFile\fR in a folder named +\fBMyDir\fR in the current folder. +.TP 15 +\fB::MyFile\fR +Relative path to a file named \fBMyFile\fR in the folder above the +current folder. +.TP 15 +\fB:::MyFile\fR +Relative path to a file named \fBMyFile\fR in the folder two levels above the +current folder. +.TP 15 +\fB/MyDisk/MyFile\fR +Absolute path to a file named \fBMyFile\fR on the device named +\fBMyDisk\fR. +.TP 15 +\fB\&../MyFile\fR +Relative path to a file named \fBMyFile\fR in the folder above the +current folder. +.RE +.TP +\fBunix\fR +On Unix platforms, Tcl uses path names where the components are +separated by slashes. Path names may be relative or absolute, and +file names may contain any character other than slash. The file names +\fB\&.\fR and \fB\&..\fR are special and refer to the current directory +and the parent of the current directory respectively. Multiple +adjacent slash characters are interpreted as a single separator. +The following examples illustrate various forms of path names: +.RS +.TP 15 +\fB/\fR +Absolute path to the root directory. +.TP 15 +\fB/etc/passwd\fR +Absolute path to the file named \fBpasswd\fR in the directory +\fBetc\fR in the root directory. +.TP 15 +\fB\&.\fR +Relative path to the current directory. +.TP 15 +\fBfoo\fR +Relative path to the file \fBfoo\fR in the current directory. +.TP 15 +\fBfoo/bar\fR +Relative path to the file \fBbar\fR in the directory \fBfoo\fR in the +current directory. +.TP 15 +\fB\&../foo\fR +Relative path to the file \fBfoo\fR in the directory above the current +directory. +.RE +.TP +\fBwindows\fR +On Microsoft Windows platforms, Tcl supports both drive-relative and UNC +style names. Both \fB/\fR and \fB\e\fR may be used as directory separators +in either type of name. Drive-relative names consist of an optional drive +specifier followed by an absolute or relative path. UNC paths follow the +general form \fB\e\eservername\esharename\epath\efile\fR. In both forms, +the file names \fB.\fR and \fB..\fR are special and refer to the current +directory and the parent of the current directory respectively. The +following examples illustrate various forms of path names: +.RS +.TP 15 +\fB\&\e\eHost\eshare/file\fR +Absolute UNC path to a file called \fBfile\fR in the root directory of +the export point \fBshare\fR on the host \fBHost\fR. +.TP 15 +\fBc:foo\fR +Volume-relative path to a file \fBfoo\fR in the current directory on drive +\fBc\fR. +.TP 15 +\fBc:/foo\fR +Absolute path to a file \fBfoo\fR in the root directory of drive +\fBc\fR. +.TP 15 +\fBfoo\ebar\fR +Relative path to a file \fBbar\fR in the \fBfoo\fR directory in the current +directory on the current volume. +.TP 15 +\fB\&\efoo\fR +Volume-relative path to a file \fBfoo\fR in the root directory of the current +volume. +.RE + +.SH "TILDE SUBSTITUTION" +.PP +In addition to the file name rules described above, Tcl also supports +\fIcsh\fR-style tilde substitution. If a file name starts with a +tilde, then the file name will be interpreted as if the first element +is replaced with the location of the home directory for the given +user. If the tilde is followed immediately by a separator, then the +\fB$HOME\fR environment variable is substituted. Otherwise the +characters between the tilde and the next separator are taken as a +user name, which is used to retrieve the user's home directory for +substitution. +.PP +The Macintosh and Windows platforms do not support tilde substitution +when a user name follows the tilde. On these platforms, attempts to +use a tilde followed by a user name will generate an error. File +names that have a tilde without a user name will be substituted using +the \fB$HOME\fR environment variable, just like for Unix. + +.SH "PORTABILITY ISSUES" +.PP +Not all file systems are case sensitive, so scripts should avoid code +that depends on the case of characters in a file name. In addition, +the character sets allowed on different devices may differ, so scripts +should choose file names that do not contain special characters like: +\fB<>:"/\e|\fR. The safest approach is to use names consisting of +alphanumeric characters only. Also Windows 3.1 only supports file +names with a root of no more than 8 characters and an extension of no +more than 3 characters. + +.SH KEYWORDS +current directory, absolute file name, relative file name, +volume-relative file name, portability + +.SH "SEE ALSO" +file(n), glob(n) diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/flush.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/flush.n new file mode 100644 index 0000000000000000000000000000000000000000..2a2f193ad89212d1f58314dc5215d0521e7adbdc --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/flush.n @@ -0,0 +1,35 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: flush.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH flush n 7.5 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +flush \- Flush buffered output for a channel +.SH SYNOPSIS +\fBflush \fIchannelId\fR +.BE + +.SH DESCRIPTION +.PP +Flushes any output that has been buffered for \fIchannelId\fR. +\fIChannelId\fR must be a channel identifier such as returned by a previous +\fBopen\fR or \fBsocket\fR command, and it must have been opened for writing. +If the channel is in blocking mode the command does not return until all the +buffered output has been flushed to the channel. If the channel is in +nonblocking mode, the command may return before all buffered output has been +flushed; the remainder will be flushed in the background as fast as the +underlying file or device is able to absorb it. + +.SH "SEE ALSO" +file(n), open(n), socket(n) + +.SH KEYWORDS +blocking, buffer, channel, flush, nonblocking, output diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/for.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/for.n new file mode 100644 index 0000000000000000000000000000000000000000..ace84d947437e5a25bc924064fde515c05d293a7 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/for.n @@ -0,0 +1,63 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1997 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: for.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH for n "" Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +for \- ``For'' loop +.SH SYNOPSIS +\fBfor \fIstart test next body\fR +.BE + +.SH DESCRIPTION +.PP +\fBFor\fR is a looping command, similar in structure to the C +\fBfor\fR statement. The \fIstart\fR, \fInext\fR, and +\fIbody\fR arguments must be Tcl command strings, and \fItest\fR +is an expression string. +The \fBfor\fR command first invokes the Tcl interpreter to +execute \fIstart\fR. Then it repeatedly evaluates \fItest\fR as +an expression; if the result is non-zero it invokes the Tcl +interpreter on \fIbody\fR, then invokes the Tcl interpreter on \fInext\fR, +then repeats the loop. The command terminates when \fItest\fR evaluates +to 0. If a \fBcontinue\fR command is invoked within \fIbody\fR then +any remaining commands in the current execution of \fIbody\fR are skipped; +processing continues by invoking the Tcl interpreter on \fInext\fR, then +evaluating \fItest\fR, and so on. If a \fBbreak\fR command is invoked +within \fIbody\fR +or \fInext\fR, +then the \fBfor\fR command will +return immediately. +The operation of \fBbreak\fR and \fBcontinue\fR are similar to the +corresponding statements in C. +\fBFor\fR returns an empty string. +.PP +Note: \fItest\fR should almost always be enclosed in braces. If not, +variable substitutions will be made before the \fBfor\fR +command starts executing, which means that variable changes +made by the loop body will not be considered in the expression. +This is likely to result in an infinite loop. If \fItest\fR is +enclosed in braces, variable substitutions are delayed until the +expression is evaluated (before +each loop iteration), so changes in the variables will be visible. +For an example, try the following script with and without the braces +around \fB$x<10\fR: +.CS +for {set x 0} {$x<10} {incr x} { + puts "x is $x" +} +.CE + +.SH "SEE ALSO" +break, continue, foreach, while + +.SH KEYWORDS +for, iteration, looping diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/foreach.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/foreach.n new file mode 100644 index 0000000000000000000000000000000000000000..919fc70f0631e2ac7df5c7de43d2ed1ab2c70f49 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/foreach.n @@ -0,0 +1,90 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: foreach.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH foreach n "" Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +foreach \- Iterate over all elements in one or more lists +.SH SYNOPSIS +\fBforeach \fIvarname list body\fR +.br +\fBforeach \fIvarlist1 list1\fR ?\fIvarlist2 list2 ...\fR? \fIbody\fR +.BE + +.SH DESCRIPTION +.PP +The \fBforeach\fR command implements a loop where the loop +variable(s) take on values from one or more lists. +In the simplest case there is one loop variable, \fIvarname\fR, +and one list, \fIlist\fR, that is a list of values to assign to \fIvarname\fR. +The \fIbody\fR argument is a Tcl script. +For each element of \fIlist\fR (in order +from first to last), \fBforeach\fR assigns the contents of the +element to \fIvarname\fR as if the \fBlindex\fR command had been used +to extract the element, then calls the Tcl interpreter to execute +\fIbody\fR. +.PP +In the general case there can be more than one value list +(e.g., \fIlist1\fR and \fIlist2\fR), +and each value list can be associated with a list of loop variables +(e.g., \fIvarlist1\fR and \fIvarlist2\fR). +During each iteration of the loop +the variables of each \fIvarlist\fP are assigned +consecutive values from the corresponding \fIlist\fP. +Values in each \fIlist\fP are used in order from first to last, +and each value is used exactly once. +The total number of loop iterations is large enough to use +up all the values from all the value lists. +If a value list does not contain enough +elements for each of its loop variables in each iteration, +empty values are used for the missing elements. +.PP +The \fBbreak\fR and \fBcontinue\fR statements may be +invoked inside \fIbody\fR, with the same effect as in the \fBfor\fR +command. \fBForeach\fR returns an empty string. +.SH EXAMPLES +.PP +The following loop uses i and j as loop variables to iterate over +pairs of elements of a single list. +.DS +set x {} +foreach {i j} {a b c d e f} { + lappend x $j $i +} +# The value of x is "b a d c f e" +# There are 3 iterations of the loop. +.DE +.PP +The next loop uses i and j to iterate over two lists in parallel. +.DS +set x {} +foreach i {a b c} j {d e f g} { + lappend x $i $j +} +# The value of x is "a d b e c f {} g" +# There are 4 iterations of the loop. +.DE +.PP +The two forms are combined in the following example. +.DS +set x {} +foreach i {a b c} {j k} {d e f g} { + lappend x $i $j $k +} +# The value of x is "a d e b f g c {} {}" +# There are 3 iterations of the loop. +.DE + +.SH "SEE ALSO" +for(n), while(n), break(n), continue(n) + +.SH KEYWORDS +foreach, iteration, list, looping diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/format.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/format.n new file mode 100644 index 0000000000000000000000000000000000000000..f06f9b2008dfcdbffc7e387c4ae911968224ff2d --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/format.n @@ -0,0 +1,217 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: format.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH format n 8.1 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +format \- Format a string in the style of sprintf +.SH SYNOPSIS +\fBformat \fIformatString \fR?\fIarg arg ...\fR? +.BE + +.SH INTRODUCTION +.PP +This command generates a formatted string in the same way as the +ANSI C \fBsprintf\fR procedure (it uses \fBsprintf\fR in its +implementation). +\fIFormatString\fR indicates how to format the result, using +\fB%\fR conversion specifiers as in \fBsprintf\fR, and the additional +arguments, if any, provide values to be substituted into the result. +The return value from \fBformat\fR is the formatted string. + +.SH "DETAILS ON FORMATTING" +.PP +The command operates by scanning \fIformatString\fR from left to right. +Each character from the format string is appended to the result +string unless it is a percent sign. +If the character is a \fB%\fR then it is not copied to the result string. +Instead, the characters following the \fB%\fR character are treated as +a conversion specifier. +The conversion specifier controls the conversion of the next successive +\fIarg\fR to a particular format and the result is appended to +the result string in place of the conversion specifier. +If there are multiple conversion specifiers in the format string, +then each one controls the conversion of one additional \fIarg\fR. +The \fBformat\fR command must be given enough \fIarg\fRs to meet the needs +of all of the conversion specifiers in \fIformatString\fR. +.PP +Each conversion specifier may contain up to six different parts: +an XPG3 position specifier, +a set of flags, a minimum field width, a precision, a length modifier, +and a conversion character. +Any of these fields may be omitted except for the conversion character. +The fields that are present must appear in the order given above. +The paragraphs below discuss each of these fields in turn. +.PP +If the \fB%\fR is followed by a decimal number and a \fB$\fR, as in +``\fB%2$d\fR'', then the value to convert is not taken from the +next sequential argument. +Instead, it is taken from the argument indicated by the number, +where 1 corresponds to the first \fIarg\fR. +If the conversion specifier requires multiple arguments because +of \fB*\fR characters in the specifier then +successive arguments are used, starting with the argument +given by the number. +This follows the XPG3 conventions for positional specifiers. +If there are any positional specifiers in \fIformatString\fR +then all of the specifiers must be positional. +.PP +The second portion of a conversion specifier may contain any of the +following flag characters, in any order: +.TP 10 +\fB\-\fR +Specifies that the converted argument should be left-justified +in its field (numbers are normally right-justified with leading +spaces if needed). +.TP 10 +\fB+\fR +Specifies that a number should always be printed with a sign, +even if positive. +.TP 10 +\fIspace\fR +Specifies that a space should be added to the beginning of the +number if the first character isn't a sign. +.TP 10 +\fB0\fR +Specifies that the number should be padded on the left with +zeroes instead of spaces. +.TP 10 +\fB#\fR +Requests an alternate output form. For \fBo\fR and \fBO\fR +conversions it guarantees that the first digit is always \fB0\fR. +For \fBx\fR or \fBX\fR conversions, \fB0x\fR or \fB0X\fR (respectively) +will be added to the beginning of the result unless it is zero. +For all floating-point conversions (\fBe\fR, \fBE\fR, \fBf\fR, +\fBg\fR, and \fBG\fR) it guarantees that the result always +has a decimal point. +For \fBg\fR and \fBG\fR conversions it specifies that +trailing zeroes should not be removed. +.PP +The third portion of a conversion specifier is a number giving a +minimum field width for this conversion. +It is typically used to make columns line up in tabular printouts. +If the converted argument contains fewer characters than the +minimum field width then it will be padded so that it is as wide +as the minimum field width. +Padding normally occurs by adding extra spaces on the left of the +converted argument, but the \fB0\fR and \fB\-\fR flags +may be used to specify padding with zeroes on the left or with +spaces on the right, respectively. +If the minimum field width is specified as \fB*\fR rather than +a number, then the next argument to the \fBformat\fR command +determines the minimum field width; it must be a numeric string. +.PP +The fourth portion of a conversion specifier is a precision, +which consists of a period followed by a number. +The number is used in different ways for different conversions. +For \fBe\fR, \fBE\fR, and \fBf\fR conversions it specifies the number +of digits to appear to the right of the decimal point. +For \fBg\fR and \fBG\fR conversions it specifies the total number +of digits to appear, including those on both sides of the decimal +point (however, trailing zeroes after the decimal point will still +be omitted unless the \fB#\fR flag has been specified). +For integer conversions, it specifies a minimum number of digits +to print (leading zeroes will be added if necessary). +For \fBs\fR conversions it specifies the maximum number of characters to be +printed; if the string is longer than this then the trailing characters will be dropped. +If the precision is specified with \fB*\fR rather than a number +then the next argument to the \fBformat\fR command determines the precision; +it must be a numeric string. +.PP +The fifth part of a conversion specifier is a length modifier, +which must be \fBh\fR or \fBl\fR. +If it is \fBh\fR it specifies that the numeric value should be +truncated to a 16-bit value before converting. +This option is rarely useful. +The \fBl\fR modifier is ignored. +.PP +The last thing in a conversion specifier is an alphabetic character +that determines what kind of conversion to perform. +The following conversion characters are currently supported: +.TP 10 +\fBd\fR +Convert integer to signed decimal string. +.TP 10 +\fBu\fR +Convert integer to unsigned decimal string. +.TP 10 +\fBi\fR +Convert integer to signed decimal string; the integer may either be +in decimal, in octal (with a leading \fB0\fR) or in hexadecimal +(with a leading \fB0x\fR). +.TP 10 +\fBo\fR +Convert integer to unsigned octal string. +.TP 10 +\fBx\fR or \fBX\fR +Convert integer to unsigned hexadecimal string, using digits +``0123456789abcdef'' for \fBx\fR and ``0123456789ABCDEF'' for \fBX\fR). +.VS +.TP 10 +\fBc\fR +Convert integer to the Unicode character it represents. +.VE +.TP 10 +\fBs\fR +No conversion; just insert string. +.TP 10 +\fBf\fR +Convert floating-point number to signed decimal string of +the form \fIxx.yyy\fR, where the number of \fIy\fR's is determined by +the precision (default: 6). +If the precision is 0 then no decimal point is output. +.TP 10 +\fBe\fR or \fBe\fR +Convert floating-point number to scientific notation in the +form \fIx.yyy\fBe\(+-\fIzz\fR, where the number of \fIy\fR's is determined +by the precision (default: 6). +If the precision is 0 then no decimal point is output. +If the \fBE\fR form is used then \fBE\fR is +printed instead of \fBe\fR. +.TP 10 +\fBg\fR or \fBG\fR +If the exponent is less than \-4 or greater than or equal to the +precision, then convert floating-point number as for \fB%e\fR or +\fB%E\fR. +Otherwise convert as for \fB%f\fR. +Trailing zeroes and a trailing decimal point are omitted. +.TP 10 +\fB%\fR +No conversion: just insert \fB%\fR. +.LP +For the numerical conversions the argument being converted must +be an integer or floating-point string; format converts the argument +to binary and then converts it back to a string according to +the conversion specifier. + +.SH "DIFFERENCES FROM ANSI SPRINTF" +.PP +The behavior of the format command is the same as the +ANSI C \fBsprintf\fR procedure except for the following +differences: +.IP [1] +\fB%p\fR and \fB%n\fR specifiers are not currently supported. +.IP [2] +For \fB%c\fR conversions the argument must be a decimal string, +which will then be converted to the corresponding character value. +.IP [3] +The \fBl\fR modifier is ignored; integer values are always converted +as if there were no modifier present and real values are always +converted as if the \fBl\fR modifier were present (i.e. type +\fBdouble\fR is used for the internal representation). +If the \fBh\fR modifier is specified then integer values are truncated +to \fBshort\fR before conversion. + +.SH "SEE ALSO" +sprintf(3), string(n) + +.SH KEYWORDS +conversion specifier, format, sprintf, string, substitution diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/gets.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/gets.n new file mode 100644 index 0000000000000000000000000000000000000000..79e1bdf6e9f6e4d9d6c65b11d8b2f868db4a4792 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/gets.n @@ -0,0 +1,50 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: gets.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH gets n 7.5 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +gets \- Read a line from a channel +.SH SYNOPSIS +\fBgets \fIchannelId\fR ?\fIvarName\fR? +.BE + +.SH DESCRIPTION +.PP +This command reads the next line from \fIchannelId\fR, returns everything +in the line up to (but not including) the end-of-line character(s), and +discards the end-of-line character(s). +If \fIvarName\fR is omitted the line is returned as the result of the +command. +If \fIvarName\fR is specified then the line is placed in the variable by +that name and the return value is a count of the number of characters +returned. +.PP +If end of file occurs while scanning for an end of +line, the command returns whatever input is available up to the end of file. +If \fIchannelId\fR is in nonblocking mode and there is not a full +line of input available, the command returns an empty string and +does not consume any input. +If \fIvarName\fR is specified and an empty string is returned in +\fIvarName\fR because of end-of-file or because of insufficient +data in nonblocking mode, then the return count is -1. +Note that if \fIvarName\fR is not specified then the end-of-file +and no-full-line-available cases can +produce the same results as if there were an input line consisting +only of the end-of-line character(s). +The \fBeof\fR and \fBfblocked\fR commands can be used to distinguish +these three cases. + +.SH "SEE ALSO" +file(n), eof(n), fblocked(n) + +.SH KEYWORDS +blocking, channel, end of file, end of line, line, nonblocking, read diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/glob.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/glob.n new file mode 100644 index 0000000000000000000000000000000000000000..b975e4a8211646510c652f660c14a6ef4e76561d --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/glob.n @@ -0,0 +1,161 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: glob.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH glob n 8.3 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +glob \- Return names of files that match patterns +.SH SYNOPSIS +\fBglob \fR?\fIswitches\fR? \fIpattern \fR?\fIpattern ...\fR? +.BE + +.SH DESCRIPTION +.PP +This command performs file name ``globbing'' in a fashion similar to +the csh shell. It returns a list of the files whose names match any +of the \fIpattern\fR arguments. +.LP +If the initial arguments to \fBglob\fR start with \fB\-\fR then +they are treated as switches. The following switches are +currently supported: +.VS 8.3 +.TP +\fB\-directory\fR \fIdirectory\fR +Search for files which match the given patterns starting in the given +\fIdirectory\fR. This allows searching of directories whose name +contains glob-sensitive characters without the need to quote such +characters explicitly. This option may not be used in conjunction with +\fB\-path\fR. +.TP +\fB\-join\fR +The remaining pattern arguments are treated as a single pattern +obtained by joining the arguments with directory separators. +.VE 8.3 +.TP +\fB\-nocomplain\fR +Allows an empty list to be returned without error; without this +switch an error is returned if the result list would be empty. +.VS 8.3 +.TP +\fB\-path\fR \fIpathPrefix\fR +Search for files with the given \fIpathPrefix\fR where the rest of the name +matches the given patterns. This allows searching for files with names +similar to a given file even when the names contain glob-sensitive +characters. This option may not be used in conjunction with +\fB\-directory\fR. +.TP +\fB\-types\fR \fItypeList\fR +Only list files or directories which match \fItypeList\fR, where the items +in the list have two forms. The first form is like the \-type option of +the Unix find command: +\fIb\fR (block special file), +\fIc\fR (character special file), +\fId\fR (directory), +\fIf\fR (plain file), +\fIl\fR (symbolic link), +\fIp\fR (named pipe), +or \fIs\fR (socket), where multiple types may be specified in the list. +\fBGlob\fR will return all files which match at least one of the types given. +.RS +.PP +The second form specifies types where all the types given must match. +These are \fIr\fR, \fIw\fR, \fIx\fR as file permissions, and +\fIreadonly\fR, \fIhidden\fR as special permission cases. On the +Macintosh, MacOS types and creators are also supported, where any item +which is four characters long is assumed to be a MacOS type +(e.g. \fBTEXT\fR). Items which are of the form \fI{macintosh type XXXX}\fR +or \fI{macintosh creator XXXX}\fR will match types or creators +respectively. Unrecognised types, or specifications of multiple MacOS +types/creators will signal an error. +.PP +The two forms may be mixed, so \fB\-types {d f r w}\fR will find all +regular files OR directories that have both read AND write permissions. +The following are equivalent: +.RS +.CS +\fBglob \-type d *\fR +\fBglob */\fR +.CE +.RE +except that the first case doesn't return the trailing ``/'' and +is more platform independent. +.RE +.VE 8.3 +.TP +\fB\-\|\-\fR +Marks the end of switches. The argument following this one will +be treated as a \fIpattern\fR even if it starts with a \fB\-\fR. +.PP +The \fIpattern\fR arguments may contain any of the following +special characters: +.TP 10 +\fB?\fR +Matches any single character. +.TP 10 +\fB*\fR +Matches any sequence of zero or more characters. +.TP 10 +\fB[\fIchars\fB]\fR +Matches any single character in \fIchars\fR. If \fIchars\fR +contains a sequence of the form \fIa\fB\-\fIb\fR then any +character between \fIa\fR and \fIb\fR (inclusive) will match. +.TP 10 +\fB\e\fIx\fR +Matches the character \fIx\fR. +.TP 10 +\fB{\fIa\fB,\fIb\fB,\fI...\fR} +Matches any of the strings \fIa\fR, \fIb\fR, etc. +.LP +As with csh, a ``.'' at the beginning of a file's name or just +after a ``/'' must be matched explicitly or with a {} construct. +In addition, all ``/'' characters must be matched explicitly. +.LP +If the first character in a \fIpattern\fR is ``~'' then it refers +to the home directory for the user whose name follows the ``~''. +If the ``~'' is followed immediately by ``/'' then the value of +the HOME environment variable is used. +.LP +The \fBglob\fR command differs from csh globbing in two ways. +First, it does not sort its result list (use the \fBlsort\fR +command if you want the list sorted). +Second, \fBglob\fR only returns the names of files that actually +exist; in csh no check for existence is made unless a pattern +contains a ?, *, or [] construct. + +.SH "PORTABILITY ISSUES" +.PP +Unlike other Tcl commands that will accept both network and native +style names (see the \fBfilename\fR manual entry for details on how +native and network names are specified), the \fBglob\fR command only +accepts native names. +.TP +\fBWindows\fR +. +For Windows UNC names, the servername and sharename components of the path +may not contain ?, *, or [] constructs. On Windows NT, if \fIpattern\fR is +of the form ``\fB~\fIusername\fB@\fIdomain\fR'' it refers to the home +directory of the user whose account information resides on the specified NT +domain server. Otherwise, user account information is obtained from +the local computer. On Windows 95 and 98, \fBglob\fR accepts patterns +like ``.../'' and ``..../'' for successively higher up parent directories. +.TP +\fBMacintosh\fR +. +When using the options, \fB\-dir\fR, \fB\-join\fR or \fB\-path\fR, glob +assumes the directory separator for the entire pattern is the standard +``:''. When not using these options, glob examines each pattern argument +and uses ``/'' unless the pattern contains a ``:''. + +.SH "SEE ALSO" +file(n) + +.SH KEYWORDS +exist, file, glob, pattern diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/global.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/global.n new file mode 100644 index 0000000000000000000000000000000000000000..43fdddf7ff143b1b4033e75444b8ce8468854073 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/global.n @@ -0,0 +1,39 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1997 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: global.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH global n "" Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +global \- Access global variables +.SH SYNOPSIS +\fBglobal \fIvarname \fR?\fIvarname ...\fR? +.BE + +.SH DESCRIPTION +.PP +This command is ignored unless a Tcl procedure is being interpreted. +If so then it declares the given \fIvarname\fR's to be global variables +rather than local ones. +Global variables are variables in the global namespace. +For the duration of the current procedure +(and only while executing in the current procedure), +any reference to any of the \fIvarname\fRs +will refer to the global variable by the same name. +.PP +Please note that this is done by creating local variables that are +linked to the global variables, and therefore that these variables +will be listed by \fBinfo locals\fR like all other local variables. + +.SH "SEE ALSO" +namespace(n), upvar(n), variable(n) + +.SH KEYWORDS +global, namespace, procedure, variable diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/history.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/history.n new file mode 100644 index 0000000000000000000000000000000000000000..58b612487cf0b8a0eb2b1b7e049c7f7ea2bdb9ef --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/history.n @@ -0,0 +1,104 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1997 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: history.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH history n "" Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +history \- Manipulate the history list +.SH SYNOPSIS +\fBhistory \fR?\fIoption\fR? ?\fIarg arg ...\fR? +.BE + +.SH DESCRIPTION +.PP +The \fBhistory\fR command performs one of several operations related to +recently-executed commands recorded in a history list. Each of +these recorded commands is referred to as an ``event''. When +specifying an event to the \fBhistory\fR command, the following +forms may be used: +.IP [1] +A number: if positive, it refers to the event with +that number (all events are numbered starting at 1). If the number +is negative, it selects an event relative to the current event +(\fB\-1\fR refers to the previous event, \fB\-2\fR to the one before that, and +so on). Event \fB0\fP refers to the current event. +.IP [2] +A string: selects the most recent event that matches the string. +An event is considered to match the string either if the string is +the same as the first characters of the event, or if the string +matches the event in the sense of the \fBstring match\fR command. +.PP +The \fBhistory\fR command can take any of the following forms: +.TP +\fBhistory\fR +Same +as \fBhistory info\fR, described below. +.TP +\fBhistory add\fI command \fR?\fBexec\fR? +Adds the \fIcommand\fR argument to the history list as a new event. If +\fBexec\fR is specified (or abbreviated) then the command is also +executed and its result is returned. If \fBexec\fR isn't specified +then an empty string is returned as result. +.TP +\fBhistory change\fI newValue\fR ?\fIevent\fR? +Replaces the value recorded for an event with \fInewValue\fR. \fIEvent\fR +specifies the event to replace, and +defaults to the \fIcurrent\fR event (not event \fB\-1\fR). This command +is intended for use in commands that implement new forms of history +substitution and wish to replace the current event (which invokes the +substitution) with the command created through substitution. The return +value is an empty string. +.TP +\fBhistory clear\fR +Erase the history list. The current keep limit is retained. +The history event numbers are reset. +.TP +\fBhistory event\fR ?\fIevent\fR? +Returns the value of the event given by \fIevent\fR. \fIEvent\fR +defaults to \fB\-1\fR. +.TP +\fBhistory info \fR?\fIcount\fR? +Returns a formatted string (intended for humans to read) giving +the event number and contents for each of the events in the history +list except the current event. If \fIcount\fR is specified +then only the most recent \fIcount\fR events are returned. +.TP +\fBhistory keep \fR?\fIcount\fR? +This command may be used to change the size of the history list to +\fIcount\fR events. Initially, 20 events are retained in the history +list. If \fIcount\fR is not specified, the current keep limit is returned. +.TP +\fBhistory nextid\fR +Returns the number of the next event to be recorded +in the history list. It is useful for things like printing the +event number in command-line prompts. +.TP +\fBhistory redo \fR?\fIevent\fR? +Re-executes the command indicated by \fIevent\fR and return its result. +\fIEvent\fR defaults to \fB\-1\fR. This command results in history +revision: see below for details. +.SH "HISTORY REVISION" +.PP +Pre-8.0 Tcl had a complex history revision mechanism. +The current mechanism is more limited, and the old +history operations \fBsubstitute\fP and \fBwords\fP have been removed. +(As a consolation, the \fBclear\fP operation was added.) +.PP +The history option \fBredo\fR results in much simpler ``history revision''. +When this option is invoked then the most recent event +is modified to eliminate the history command and replace it with +the result of the history command. +If you want to redo an event without modifying history, then use +the \fBevent\fP operation to retrieve some event, +and the \fBadd\fP operation to add it to history and execute it. + +.SH KEYWORDS +event, history, record diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/http.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/http.n new file mode 100644 index 0000000000000000000000000000000000000000..fb4d9b0628693d2c79ba2ba46a9ed2ccdbbf7c76 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/http.n @@ -0,0 +1,526 @@ +'\" +'\" Copyright (c) 1995-1997 Sun Microsystems, Inc. +'\" Copyright (c) 1998-2000 by Ajuba Solutions. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: http.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH "Http" n 8.3 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +Http \- Client-side implementation of the HTTP/1.0 protocol. +.SH SYNOPSIS +\fBpackage require http ?2.4?\fP +.sp +\fB::http::config \fI?options?\fR +.sp +\fB::http::geturl \fIurl ?options?\fR +.sp +\fB::http::formatQuery \fIlist\fR +.sp +\fB::http::reset \fItoken\fR +.sp +\fB::http::wait \fItoken\fR +.sp +\fB::http::status \fItoken\fR +.sp +\fB::http::size \fItoken\fR +.sp +\fB::http::code \fItoken\fR +.sp +\fB::http::ncode \fItoken\fR +.sp +\fB::http::data \fItoken\fR +.sp +\fB::http::error \fItoken\fR +.sp +\fB::http::cleanup \fItoken\fR +.sp +\fB::http::register \fIproto port command\fR +.sp +\fB::http::unregister \fIproto\fR +.BE + +.SH DESCRIPTION +.PP +The \fBhttp\fR package provides the client side of the HTTP/1.0 +protocol. The package implements the GET, POST, and HEAD operations +of HTTP/1.0. It allows configuration of a proxy host to get through +firewalls. The package is compatible with the \fBSafesock\fR security +policy, so it can be used by untrusted applets to do URL fetching from +a restricted set of hosts. This package can be extened to support +additional HTTP transport protocols, such as HTTPS, by providing +a custom \fBsocket\fR command, via \fBhttp::register\fR. +.PP +The \fB::http::geturl\fR procedure does a HTTP transaction. +Its \fIoptions \fR determine whether a GET, POST, or HEAD transaction +is performed. +The return value of \fB::http::geturl\fR is a token for the transaction. +The value is also the name of an array in the ::http namespace +that contains state information about the transaction. The elements +of this array are described in the STATE ARRAY section. +.PP +If the \fB-command\fP option is specified, then +the HTTP operation is done in the background. +\fB::http::geturl\fR returns immediately after generating the +HTTP request and the callback is invoked +when the transaction completes. For this to work, the Tcl event loop +must be active. In Tk applications this is always true. For pure-Tcl +applications, the caller can use \fB::http::wait\fR after calling +\fB::http::geturl\fR to start the event loop. +.SH COMMANDS +.TP +\fB::http::config\fP ?\fIoptions\fR? +The \fB::http::config\fR command is used to set and query the name of the +proxy server and port, and the User-Agent name used in the HTTP +requests. If no options are specified, then the current configuration +is returned. If a single argument is specified, then it should be one +of the flags described below. In this case the current value of +that setting is returned. Otherwise, the options should be a set of +flags and values that define the configuration: +.RS +.TP +\fB\-accept\fP \fImimetypes\fP +The Accept header of the request. The default is */*, which means that +all types of documents are accepted. Otherwise you can supply a +comma separated list of mime type patterns that you are +willing to receive. For example, "image/gif, image/jpeg, text/*". +.TP +\fB\-proxyhost\fP \fIhostname\fP +The name of the proxy host, if any. If this value is the +empty string, the URL host is contacted directly. +.TP +\fB\-proxyport\fP \fInumber\fP +The proxy port number. +.TP +\fB\-proxyfilter\fP \fIcommand\fP +The command is a callback that is made during +\fB::http::geturl\fR +to determine if a proxy is required for a given host. One argument, a +host name, is added to \fIcommand\fR when it is invoked. If a proxy +is required, the callback should return a two element list containing +the proxy server and proxy port. Otherwise the filter should return +an empty list. The default filter returns the values of the +\fB\-proxyhost\fR and \fB\-proxyport\fR settings if they are +non-empty. +.TP +\fB\-useragent\fP \fIstring\fP +The value of the User-Agent header in the HTTP request. The default +is \fB"Tcl http client package 2.2."\fR +.RE +.TP +\fB::http::geturl\fP \fIurl\fP ?\fIoptions\fP? +The \fB::http::geturl\fR command is the main procedure in the package. +The \fB\-query\fR option causes a POST operation and +the \fB\-validate\fR option causes a HEAD operation; +otherwise, a GET operation is performed. The \fB::http::geturl\fR command +returns a \fItoken\fR value that can be used to get +information about the transaction. See the STATE ARRAY and ERRORS section for +details. The \fB::http::geturl\fR command blocks until the operation +completes, unless the \fB\-command\fR option specifies a callback +that is invoked when the HTTP transaction completes. +\fB::http::geturl\fR takes several options: +.RS +.TP +\fB\-binary\fP \fIboolean\fP +Specifies whether to force interpreting the url data as binary. Normally +this is auto-detected (anything not beginning with a \fBtext\fR content +type or whose content encoding is \fBgzip\fR or \fBcompress\fR is +considered binary data). +.TP +\fB\-blocksize\fP \fIsize\fP +The blocksize used when reading the URL. +At most \fIsize\fR bytes are read at once. After each block, a call to the +\fB\-progress\fR callback is made (if that option is specified). +.TP +\fB\-channel\fP \fIname\fP +Copy the URL contents to channel \fIname\fR instead of saving it in +\fBstate(body)\fR. +.TP +\fB\-command\fP \fIcallback\fP +Invoke \fIcallback\fP after the HTTP transaction completes. +This option causes \fB::http::geturl\fP to return immediately. +The \fIcallback\fP gets an additional argument that is the \fItoken\fR returned +from \fB::http::geturl\fR. This token is the name of an array that is +described in the STATE ARRAY section. Here is a template for the +callback: +.RS +.CS +proc httpCallback {token} { + upvar #0 $token state + # Access state as a Tcl array +} +.CE +.RE +.TP +\fB\-handler\fP \fIcallback\fP +Invoke \fIcallback\fP whenever HTTP data is available; if present, nothing +else will be done with the HTTP data. This procedure gets two additional +arguments: the socket for the HTTP data and the \fItoken\fR returned from +\fB::http::geturl\fR. The token is the name of a global array that is described +in the STATE ARRAY section. The procedure is expected to return the number +of bytes read from the socket. Here is a template for the callback: +.RS +.CS +proc httpHandlerCallback {socket token} { + upvar #0 $token state + # Access socket, and state as a Tcl array + ... + (example: set data [read $socket 1000];set nbytes [string length $data]) + ... + return nbytes +} +.CE +.RE +.TP +\fB\-headers\fP \fIkeyvaluelist\fP +This option is used to add extra headers to the HTTP request. The +\fIkeyvaluelist\fR argument must be a list with an even number of +elements that alternate between keys and values. The keys become +header field names. Newlines are stripped from the values so the +header cannot be corrupted. For example, if \fIkeyvaluelist\fR is +\fBPragma no-cache\fR then the following header is included in the +HTTP request: +.CS +Pragma: no-cache +.CE +.TP +\fB\-progress\fP \fIcallback\fP +The \fIcallback\fR is made after each transfer of data from the URL. +The callback gets three additional arguments: the \fItoken\fR from +\fB::http::geturl\fR, the expected total size of the contents from the +\fBContent-Length\fR meta-data, and the current number of bytes +transferred so far. The expected total size may be unknown, in which +case zero is passed to the callback. Here is a template for the +progress callback: +.RS +.CS +proc httpProgress {token total current} { + upvar #0 $token state +} +.CE +.RE +.TP +\fB\-query\fP \fIquery\fP +This flag causes \fB::http::geturl\fR to do a POST request that passes the +\fIquery\fR to the server. The \fIquery\fR must be a x-url-encoding +formatted query. The \fB::http::formatQuery\fR procedure can be used to +do the formatting. +.TP +\fB\-queryblocksize\fP \fIsize\fP +The blocksize used when posting query data to the URL. +At most +\fIsize\fR +bytes are written at once. After each block, a call to the +\fB\-queryprogress\fR +callback is made (if that option is specified). +.TP +\fB\-querychannel\fP \fIchannelID\fP +This flag causes \fB::http::geturl\fR to do a POST request that passes the +data contained in \fIchannelID\fR to the server. The data contained in \fIchannelID\fR must be a x-url-encoding +formatted query unless the \fB\-type\fP option below is used. +If a Content-Length header is not specified via the \fB\-headers\fR options, +\fB::http::geturl\fR attempts to determine the size of the post data +in order to create that header. If it is +unable to determine the size, it returns an error. +.TP +\fB\-queryprogress\fP \fIcallback\fP +The \fIcallback\fR is made after each transfer of data to the URL +(i.e. POST) and acts exactly like the \fB\-progress\fR option (the +callback format is the same). +.TP +\fB\-timeout\fP \fImilliseconds\fP +If \fImilliseconds\fR is non-zero, then \fB::http::geturl\fR sets up a timeout +to occur after the specified number of milliseconds. +A timeout results in a call to \fB::http::reset\fP and to +the \fB-command\fP callback, if specified. +The return value of \fB::http::status\fP is \fBtimeout\fP +after a timeout has occurred. +.TP +\fB\-type\fP \fImime-type\fP +Use \fImime-type\fR as the \fBContent-Type\fR value, instead of the +default value (\fBapplication/x-www-form-urlencoded\fR) during a +POST operation. +.TP +\fB\-validate\fP \fIboolean\fP +If \fIboolean\fR is non-zero, then \fB::http::geturl\fR does an HTTP HEAD +request. This request returns meta information about the URL, but the +contents are not returned. The meta information is available in the +\fBstate(meta) \fR variable after the transaction. See the STATE +ARRAY section for details. +.RE +.TP +\fB::http::formatQuery\fP \fIkey value\fP ?\fIkey value\fP ...? +This procedure does x-url-encoding of query data. It takes an even +number of arguments that are the keys and values of the query. It +encodes the keys and values, and generates one string that has the +proper & and = separators. The result is suitable for the +\fB\-query\fR value passed to \fB::http::geturl\fR. +.TP +\fB::http::reset\fP \fItoken\fP ?\fIwhy\fP? +This command resets the HTTP transaction identified by \fItoken\fR, if +any. This sets the \fBstate(status)\fP value to \fIwhy\fP, which defaults to \fBreset\fR, and then calls the registered \fB\-command\fR callback. +.TP +\fB::http::wait\fP \fItoken\fP +This is a convenience procedure that blocks and waits for the +transaction to complete. This only works in trusted code because it +uses \fBvwait\fR. Also, it's not useful for the case where +\fB::http::geturl\fP is called \fIwithout\fP the \fB-command\fP option +because in this case the \fB::http::geturl\fP call doesn't return +until the HTTP transaction is complete, and thus there's nothing to +wait for. +.TP +\fB::http::data\fP \fItoken\fP +This is a convenience procedure that returns the \fBbody\fP element +(i.e., the URL data) of the state array. +.TP +\fB::http::error\fP \fItoken\fP +This is a convenience procedure that returns the \fBerror\fP element +of the state array. +.TP +\fB::http::status\fP \fItoken\fP +This is a convenience procedure that returns the \fBstatus\fP element of +the state array. +.TP +\fB::http::code\fP \fItoken\fP +This is a convenience procedure that returns the \fBhttp\fP element of the +state array. +.TP +\fB::http::ncode\fP \fItoken\fP +This is a convenience procedure that returns just the numeric return +code (200, 404, etc.) from the \fBhttp\fP element of the state array. +.TP +\fB::http::size\fP \fItoken\fP +This is a convenience procedure that returns the \fBcurrentsize\fP +element of the state array, which represents the number of bytes +received from the URL in the \fB::http::geturl\fP call. +.TP +\fB::http::cleanup\fP \fItoken\fP +This procedure cleans up the state associated with the connection +identified by \fItoken\fP. After this call, the procedures +like \fB::http::data\fP cannot be used to get information +about the operation. It is \fIstrongly\fP recommended that you call +this function after you're done with a given HTTP request. Not doing +so will result in memory not being freed, and if your app calls +\fB::http::geturl\fP enough times, the memory leak could cause a +performance hit...or worse. +.TP +\fB::http::register\fP \fIproto port command\fP +This procedure allows one to provide custom HTTP transport types +such as HTTPS, by registering a prefix, the default port, and the +command to execute to create the Tcl \fBchannel\fR. E.g.: +.RS +.CS +package require http +package require tls + +http::register https 443 ::tls::socket + +set token [http::geturl https://my.secure.site/] +.CE +.RE +.TP +\fB::http::unregister\fP \fIproto\fP +This procedure unregisters a protocol handler that was previously +registered via \fBhttp::register\fR. + +.SH "ERRORS" +The \fBhttp::geturl\fP procedure will raise errors in the following cases: +invalid command line options, +an invalid URL, +a URL on a non-existent host, +or a URL at a bad port on an existing host. +These errors mean that it +cannot even start the network transaction. +It will also raise an error if it gets an I/O error while +writing out the HTTP request header. +For synchronous \fB::http::geturl\fP calls (where \fB-command\fP is +not specified), it will raise an error if it gets an I/O error while +reading the HTTP reply headers or data. Because \fB::http::geturl\fP +doesn't return a token in these cases, it does all the required +cleanup and there's no issue of your app having to call +\fB::http::cleanup\fP. +.PP +For asynchronous \fB::http::geturl\fP calls, all of the above error +situations apply, except that if there's any error while +reading the +HTTP reply headers or data, no exception is thrown. This is because +after writing the HTTP headers, \fB::http::geturl\fP returns, and the +rest of the HTTP transaction occurs in the background. The command +callback can check if any error occurred during the read by calling +\fB::http::status\fP to check the status and if it's \fIerror\fP, +calling \fB::http::error\fP to get the error message. +.PP +Alternatively, if the main program flow reaches a point where it needs +to know the result of the asynchronous HTTP request, it can call +\fB::http::wait\fP and then check status and error, just as the +callback does. +.PP +In any case, you must still call +\fBhttp::cleanup\fP to delete the state array when you're done. +.PP +There are other possible results of the HTTP transaction +determined by examining the status from \fBhttp::status\fP. +These are described below. +.TP +ok +If the HTTP transaction completes entirely, then status will be \fBok\fP. +However, you should still check the \fBhttp::code\fP value to get +the HTTP status. The \fBhttp::ncode\fP procedure provides just +the numeric error (e.g., 200, 404 or 500) while the \fBhttp::code\fP +procedure returns a value like "HTTP 404 File not found". +.TP +eof +If the server closes the socket without replying, then no error +is raised, but the status of the transaction will be \fBeof\fP. +.TP +error +The error message will also be stored in the \fBerror\fP status +array element, accessible via \fB::http::error\fP. +.PP +Another error possibility is that \fBhttp::geturl\fP is unable to +write all the post query data to the server before the server +responds and closes the socket. +The error message is saved in the \fBposterror\fP status array +element and then \fBhttp::geturl\fP attempts to complete the +transaction. +If it can read the server's response +it will end up with an \fBok\fP status, otherwise it will have +an \fBeof\fP status. + +.SH "STATE ARRAY" +The \fB::http::geturl\fR procedure returns a \fItoken\fR that can be used to +get to the state of the HTTP transaction in the form of a Tcl array. +Use this construct to create an easy-to-use array variable: +.CS +upvar #0 $token state +.CE +Once the data associated with the url is no longer needed, the state +array should be unset to free up storage. +The \fBhttp::cleanup\fP procedure is provided for that purpose. +The following elements of +the array are supported: +.RS +.TP +\fBbody\fR +The contents of the URL. This will be empty if the \fB\-channel\fR +option has been specified. This value is returned by the \fB::http::data\fP command. +.TP +\fBcharset\fR +The value of the charset attribute from the \fBContent-Type\fR meta-data +value. If none was specified, this defaults to the RFC standard +\fBiso8859-1\fR, or the value of \fB$::http::defaultCharset\fR. Incoming +text data will be automatically converted from this charset to utf-8. +.TP +\fBcoding\fR +A copy of the \fBContent-Encoding\fR meta-data value. +.TP +\fBcurrentsize\fR +The current number of bytes fetched from the URL. +This value is returned by the \fB::http::size\fP command. +.TP +\fBerror\fR +If defined, this is the error string seen when the HTTP transaction +was aborted. +.TP +\fBhttp\fR +The HTTP status reply from the server. This value +is returned by the \fB::http::code\fP command. The format of this value is: +.RS +.CS +\fIHTTP/1.0 code string\fP +.CE +The \fIcode\fR is a three-digit number defined in the HTTP standard. +A code of 200 is OK. Codes beginning with 4 or 5 indicate errors. +Codes beginning with 3 are redirection errors. In this case the +\fBLocation\fR meta-data specifies a new URL that contains the +requested information. +.RE +.TP +\fBmeta\fR +The HTTP protocol returns meta-data that describes the URL contents. +The \fBmeta\fR element of the state array is a list of the keys and +values of the meta-data. This is in a format useful for initializing +an array that just contains the meta-data: +.RS +.CS +array set meta $state(meta) +.CE +Some of the meta-data keys are listed below, but the HTTP standard defines +more, and servers are free to add their own. +.TP +\fBContent-Type\fR +The type of the URL contents. Examples include \fBtext/html\fR, +\fBimage/gif,\fR \fBapplication/postscript\fR and +\fBapplication/x-tcl\fR. +.TP +\fBContent-Length\fR +The advertised size of the contents. The actual size obtained by +\fB::http::geturl\fR is available as \fBstate(size)\fR. +.TP +\fBLocation\fR +An alternate URL that contains the requested data. +.RE +.TP +\fBposterror\fR +The error, if any, that occurred while writing +the post query data to the server. +.TP +\fBstatus\fR +Either \fBok\fR, for successful completion, \fBreset\fR for +user-reset, \fBtimeout\fP if a timeout occurred before the transaction +could complete, or \fBerror\fR for an error condition. During the +transaction this value is the empty string. +.TP +\fBtotalsize\fR +A copy of the \fBContent-Length\fR meta-data value. +.TP +\fBtype\fR +A copy of the \fBContent-Type\fR meta-data value. +.TP +\fBurl\fR +The requested URL. +.RE +.SH EXAMPLE +.DS +# Copy a URL to a file and print meta-data +proc ::http::copy { url file {chunk 4096} } { + set out [open $file w] + set token [geturl $url -channel $out -progress ::http::Progress \\ + -blocksize $chunk] + close $out + # This ends the line started by http::Progress + puts stderr "" + upvar #0 $token state + set max 0 + foreach {name value} $state(meta) { + if {[string length $name] > $max} { + set max [string length $name] + } + if {[regexp -nocase ^location$ $name]} { + # Handle URL redirects + puts stderr "Location:$value" + return [copy [string trim $value] $file $chunk] + } + } + incr max + foreach {name value} $state(meta) { + puts [format "%-*s %s" $max $name: $value] + } + + return $token +} +proc ::http::Progress {args} { + puts -nonewline stderr . ; flush stderr +} +.DE + +.SH "SEE ALSO" +safe(n), socket(n), safesock(n) + +.SH KEYWORDS +security policy, socket diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/if.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/if.n new file mode 100644 index 0000000000000000000000000000000000000000..1229f51f7e49cdd521c43c2ac8860252abc40e07 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/if.n @@ -0,0 +1,46 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: if.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH if n "" Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +if \- Execute scripts conditionally +.SH SYNOPSIS +\fBif \fIexpr1 \fR?\fBthen\fR? \fIbody1 \fBelseif \fIexpr2 \fR?\fBthen\fR? \fIbody2\fR \fBelseif\fR ... ?\fBelse\fR? ?\fIbodyN\fR? +.BE + +.SH DESCRIPTION +.PP +The \fIif\fR command evaluates \fIexpr1\fR as an expression (in the +same way that \fBexpr\fR evaluates its argument). The value of the +expression must be a boolean +(a numeric value, where 0 is false and +anything is true, or a string value such as \fBtrue\fR or \fByes\fR +for true and \fBfalse\fR or \fBno\fR for false); +if it is true then \fIbody1\fR is executed by passing it to the +Tcl interpreter. +Otherwise \fIexpr2\fR is evaluated as an expression and if it is true +then \fBbody2\fR is executed, and so on. +If none of the expressions evaluates to true then \fIbodyN\fR is +executed. +The \fBthen\fR and \fBelse\fR arguments are optional +``noise words'' to make the command easier to read. +There may be any number of \fBelseif\fR clauses, including zero. +\fIBodyN\fR may also be omitted as long as \fBelse\fR is omitted too. +The return value from the command is the result of the body script +that was executed, or an empty string +if none of the expressions was non-zero and there was no \fIbodyN\fR. + +.SH "SEE ALSO" +expr(n), for(n), foreach(n) + +.SH KEYWORDS +boolean, conditional, else, false, if, true diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/incr.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/incr.n new file mode 100644 index 0000000000000000000000000000000000000000..77501b89fd99f6c65bcae7f668a22051612db950 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/incr.n @@ -0,0 +1,34 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: incr.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH incr n "" Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +incr \- Increment the value of a variable +.SH SYNOPSIS +\fBincr \fIvarName \fR?\fIincrement\fR? +.BE + +.SH DESCRIPTION +.PP +Increments the value stored in the variable whose name is \fIvarName\fR. +The value of the variable must be an integer. +If \fIincrement\fR is supplied then its value (which must be an +integer) is added to the value of variable \fIvarName\fR; otherwise +1 is added to \fIvarName\fR. +The new value is stored as a decimal string in variable \fIvarName\fR +and also returned as result. + +.SH "SEE ALSO" +expr(n) + +.SH KEYWORDS +add, increment, variable, value diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/info.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/info.n new file mode 100644 index 0000000000000000000000000000000000000000..cce5cdc6b3e485a5637e0fdc0bab86b1d4b5a3f2 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/info.n @@ -0,0 +1,185 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1997 Sun Microsystems, Inc. +'\" Copyright (c) 1993-1997 Bell Labs Innovations for Lucent Technologies +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: info.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH info n 7.5 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +info \- Return information about the state of the Tcl interpreter +.SH SYNOPSIS +\fBinfo \fIoption \fR?\fIarg arg ...\fR? +.BE + +.SH DESCRIPTION +.PP +This command provides information about various internals of the Tcl +interpreter. +The legal \fIoption\fR's (which may be abbreviated) are: +.TP +\fBinfo args \fIprocname\fR +Returns a list containing the names of the arguments to procedure +\fIprocname\fR, in order. \fIProcname\fR must be the name of a +Tcl command procedure. +.TP +\fBinfo body \fIprocname\fR +Returns the body of procedure \fIprocname\fR. \fIProcname\fR must be +the name of a Tcl command procedure. +.TP +\fBinfo cmdcount\fR +Returns a count of the total number of commands that have been invoked +in this interpreter. +.TP +\fBinfo commands \fR?\fIpattern\fR? +If \fIpattern\fR isn't specified, +returns a list of names of all the Tcl commands in the current namespace, +including both the built-in commands written in C and +the command procedures defined using the \fBproc\fR command. +If \fIpattern\fR is specified, +only those names matching \fIpattern\fR are returned. +Matching is determined using the same rules as for \fBstring match\fR. +\fIpattern\fR can be a qualified name like \fBFoo::print*\fR. +That is, it may specify a particular namespace +using a sequence of namespace names separated by \fB::\fRs, +and may have pattern matching special characters +at the end to specify a set of commands in that namespace. +If \fIpattern\fR is a qualified name, +the resulting list of command names has each one qualified with the name +of the specified namespace. +.TP +\fBinfo complete \fIcommand\fR +Returns 1 if \fIcommand\fR is a complete Tcl command in the sense of +having no unclosed quotes, braces, brackets or array element names, +If the command doesn't appear to be complete then 0 is returned. +This command is typically used in line-oriented input environments +to allow users to type in commands that span multiple lines; if the +command isn't complete, the script can delay evaluating it until additional +lines have been typed to complete the command. +.TP +\fBinfo default \fIprocname arg varname\fR +\fIProcname\fR must be the name of a Tcl command procedure and \fIarg\fR +must be the name of an argument to that procedure. If \fIarg\fR +doesn't have a default value then the command returns \fB0\fR. +Otherwise it returns \fB1\fR and places the default value of \fIarg\fR +into variable \fIvarname\fR. +.TP +\fBinfo exists \fIvarName\fR +Returns \fB1\fR if the variable named \fIvarName\fR exists in the +current context (either as a global or local variable) and has been +defined by being given a value, returns \fB0\fR otherwise. +.TP +\fBinfo globals \fR?\fIpattern\fR? +If \fIpattern\fR isn't specified, returns a list of all the names +of currently-defined global variables. +Global variables are variables in the global namespace. +If \fIpattern\fR is specified, only those names matching \fIpattern\fR +are returned. Matching is determined using the same rules as for +\fBstring match\fR. +.TP +\fBinfo hostname\fR +Returns the name of the computer on which this invocation is being +executed. +.TP +\fBinfo level\fR ?\fInumber\fR? +If \fInumber\fR is not specified, this command returns a number +giving the stack level of the invoking procedure, or 0 if the +command is invoked at top-level. If \fInumber\fR is specified, +then the result is a list consisting of the name and arguments for the +procedure call at level \fInumber\fR on the stack. If \fInumber\fR +is positive then it selects a particular stack level (1 refers +to the top-most active procedure, 2 to the procedure it called, and +so on); otherwise it gives a level relative to the current level +(0 refers to the current procedure, -1 to its caller, and so on). +See the \fBuplevel\fR command for more information on what stack +levels mean. +.TP +\fBinfo library\fR +Returns the name of the library directory in which standard Tcl +scripts are stored. +This is actually the value of the \fBtcl_library\fR +variable and may be changed by setting \fBtcl_library\fR. +See the \fBtclvars\fR manual entry for more information. +.TP +\fBinfo loaded \fR?\fIinterp\fR? +Returns a list describing all of the packages that have been loaded into +\fIinterp\fR with the \fBload\fR command. +Each list element is a sub-list with two elements consisting of the +name of the file from which the package was loaded and the name of +the package. +For statically-loaded packages the file name will be an empty string. +If \fIinterp\fR is omitted then information is returned for all packages +loaded in any interpreter in the process. +To get a list of just the packages in the current interpreter, specify +an empty string for the \fIinterp\fR argument. +.TP +\fBinfo locals \fR?\fIpattern\fR? +If \fIpattern\fR isn't specified, returns a list of all the names +of currently-defined local variables, including arguments to the +current procedure, if any. +Variables defined with the \fBglobal\fR and \fBupvar\fR commands +will not be returned. +If \fIpattern\fR is specified, only those names matching \fIpattern\fR +are returned. Matching is determined using the same rules as for +\fBstring match\fR. +.TP +\fBinfo nameofexecutable\fR +Returns the full path name of the binary file from which the application +was invoked. If Tcl was unable to identify the file, then an empty +string is returned. +.TP +\fBinfo patchlevel\fR +Returns the value of the global variable \fBtcl_patchLevel\fR; see +the \fBtclvars\fR manual entry for more information. +.TP +\fBinfo procs \fR?\fIpattern\fR? +If \fIpattern\fR isn't specified, returns a list of all the +names of Tcl command procedures in the current namespace. +If \fIpattern\fR is specified, +only those procedure names in the current namespace +matching \fIpattern\fR are returned. +Matching is determined using the same rules as for +\fBstring match\fR. +.TP +\fBinfo script\fR +If a Tcl script file is currently being evaluated (i.e. there is a +call to \fBTcl_EvalFile\fR active or there is an active invocation +of the \fBsource\fR command), then this command returns the name +of the innermost file being processed. Otherwise the command returns an +empty string. +.TP +\fBinfo sharedlibextension\fR +Returns the extension used on this platform for the names of files +containing shared libraries (for example, \fB.so\fR under Solaris). +If shared libraries aren't supported on this platform then an empty +string is returned. +.TP +\fBinfo tclversion\fR +Returns the value of the global variable \fBtcl_version\fR; see +the \fBtclvars\fR manual entry for more information. +.TP +\fBinfo vars\fR ?\fIpattern\fR? +If \fIpattern\fR isn't specified, +returns a list of all the names of currently-visible variables. +This includes locals and currently-visible globals. +If \fIpattern\fR is specified, only those names matching \fIpattern\fR +are returned. Matching is determined using the same rules as for +\fBstring match\fR. +\fIpattern\fR can be a qualified name like \fBFoo::option*\fR. +That is, it may specify a particular namespace +using a sequence of namespace names separated by \fB::\fRs, +and may have pattern matching special characters +at the end to specify a set of variables in that namespace. +If \fIpattern\fR is a qualified name, +the resulting list of variable names +has each matching namespace variable qualified with the name +of its namespace. + +.SH KEYWORDS +command, information, interpreter, level, namespace, procedure, variable diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/interp.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/interp.n new file mode 100644 index 0000000000000000000000000000000000000000..660a4c3797fd167c096d111725f3eefb21333b6a --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/interp.n @@ -0,0 +1,542 @@ +'\" +'\" Copyright (c) 1995-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: interp.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH interp n 7.6 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +interp \- Create and manipulate Tcl interpreters +.SH SYNOPSIS +\fBinterp \fIoption \fR?\fIarg arg ...\fR? +.BE + +.SH DESCRIPTION +.PP +This command makes it possible to create one or more new Tcl +interpreters that co-exist with the creating interpreter in the +same application. The creating interpreter is called the \fImaster\fR +and the new interpreter is called a \fIslave\fR. +A master can create any number of slaves, and each slave can +itself create additional slaves for which it is master, resulting +in a hierarchy of interpreters. +.PP +Each interpreter is independent from the others: it has its own name +space for commands, procedures, and global variables. +A master interpreter may create connections between its slaves and +itself using a mechanism called an \fIalias\fR. An \fIalias\fR is +a command in a slave interpreter which, when invoked, causes a +command to be invoked in its master interpreter or in another slave +interpreter. The only other connections between interpreters are +through environment variables (the \fBenv\fR variable), which are +normally shared among all interpreters in the application. Note that the +name space for files (such as the names returned by the \fBopen\fR command) +is no longer shared between interpreters. Explicit commands are provided to +share files and to transfer references to open files from one interpreter +to another. +.PP +The \fBinterp\fR command also provides support for \fIsafe\fR +interpreters. A safe interpreter is a slave whose functions have +been greatly restricted, so that it is safe to execute untrusted +scripts without fear of them damaging other interpreters or the +application's environment. For example, all IO channel creation +commands and subprocess creation commands are made inaccessible to safe +interpreters. +.VS +See SAFE INTERPRETERS below for more information on +what features are present in a safe interpreter. +The dangerous functionality is not removed from the safe interpreter; +instead, it is \fIhidden\fR, so that only trusted interpreters can obtain +access to it. For a detailed explanation of hidden commands, see +HIDDEN COMMANDS, below. +The alias mechanism can be used for protected communication (analogous to a +kernel call) between a slave interpreter and its master. See ALIAS +INVOCATION, below, for more details on how the alias mechanism works. +.VE +.PP +A qualified interpreter name is a proper Tcl lists containing a subset of its +ancestors in the interpreter hierarchy, terminated by the string naming the +interpreter in its immediate master. Interpreter names are relative to the +interpreter in which they are used. For example, if \fBa\fR is a slave of +the current interpreter and it has a slave \fBa1\fR, which in turn has a +slave \fBa11\fR, the qualified name of \fBa11\fR in \fBa\fR is the list +\fBa1 a11\fR. +.PP +The \fBinterp\fR command, described below, accepts qualified interpreter +names as arguments; the interpreter in which the command is being evaluated +can always be referred to as \fB{}\fR (the empty list or string). Note that +it is impossible to refer to a master (ancestor) interpreter by name in a +slave interpreter except through aliases. Also, there is no global name by +which one can refer to the first interpreter created in an application. +Both restrictions are motivated by safety concerns. + +.VS +.SH "THE INTERP COMMAND" +.PP +.VE +The \fBinterp\fR command is used to create, delete, and manipulate +slave interpreters, and to share or transfer +channels between interpreters. It can have any of several forms, depending +on the \fIoption\fR argument: +.TP +\fBinterp\fR \fBalias\fR \fIsrcPath\fR \fIsrcCmd\fR +Returns a Tcl list whose elements are the \fItargetCmd\fR and +\fIarg\fRs associated with the alias named \fIsrcCmd\fR +(all of these are the values specified when the alias was +created; it is possible that the actual source command in the +slave is different from \fIsrcCmd\fR if it was renamed). +.TP +\fBinterp\fR \fBalias\fR \fIsrcPath\fR \fIsrcCmd\fR \fB{}\fR +Deletes the alias for \fIsrcCmd\fR in the slave interpreter identified by +\fIsrcPath\fR. +\fIsrcCmd\fR refers to the name under which the alias +was created; if the source command has been renamed, the renamed +command will be deleted. +.TP +\fBinterp\fR \fBalias\fR \fIsrcPath\fR \fIsrcCmd\fR \fItargetPath\fR \fItargetCmd \fR?\fIarg arg ...\fR? +This command creates an alias between one slave and another (see the +\fBalias\fR slave command below for creating aliases between a slave +and its master). In this command, either of the slave interpreters +may be anywhere in the hierarchy of interpreters under the interpreter +invoking the command. +\fISrcPath\fR and \fIsrcCmd\fR identify the source of the alias. +\fISrcPath\fR is a Tcl list whose elements select a particular +interpreter. For example, ``\fBa b\fR'' identifies an interpreter +\fBb\fR, which is a slave of interpreter \fBa\fR, which is a slave +of the invoking interpreter. An empty list specifies the interpreter +invoking the command. \fIsrcCmd\fR gives the name of a new +command, which will be created in the source interpreter. +\fITargetPath\fR and \fItargetCmd\fR specify a target interpreter +and command, and the \fIarg\fR arguments, if any, specify additional +arguments to \fItargetCmd\fR which are prepended to any arguments specified +in the invocation of \fIsrcCmd\fR. +\fITargetCmd\fR may be undefined at the time of this call, or it may +already exist; it is not created by this command. +The alias arranges for the given target command to be invoked +in the target interpreter whenever the given source command is +invoked in the source interpreter. See ALIAS INVOCATION below for +more details. +.TP +\fBinterp\fR \fBaliases \fR?\fIpath\fR? +This command returns a Tcl list of the names of all the source commands for +aliases defined in the interpreter identified by \fIpath\fR. +.TP +\fBinterp\fR \fBcreate \fR?\fB\-safe\fR? ?\fB\-\|\-\fR? ?\fIpath\fR? +Creates a slave interpreter identified by \fIpath\fR and a new command, +called a \fIslave command\fR. The name of the slave command is the last +component of \fIpath\fR. The new slave interpreter and the slave command +are created in the interpreter identified by the path obtained by removing +the last component from \fIpath\fR. For example, if \fIpath is \fBa b +c\fR then a new slave interpreter and slave command named \fBc\fR are +created in the interpreter identified by the path \fBa b\fR. +The slave command may be used to manipulate the new interpreter as +described below. If \fIpath\fR is omitted, Tcl creates a unique name of the +form \fBinterp\fIx\fR, where \fIx\fR is an integer, and uses it for the +interpreter and the slave command. If the \fB\-safe\fR switch is specified +(or if the master interpreter is a safe interpreter), the new slave +interpreter will be created as a safe interpreter with limited +functionality; otherwise the slave will include the full set of Tcl +built-in commands and variables. The \fB\-\|\-\fR switch can be used to +mark the end of switches; it may be needed if \fIpath\fR is an unusual +value such as \fB\-safe\fR. The result of the command is the name of the +new interpreter. The name of a slave interpreter must be unique among all +the slaves for its master; an error occurs if a slave interpreter by the +given name already exists in this master. +.TP +\fBinterp\fR \fBdelete \fR?\fIpath ...?\fR +Deletes zero or more interpreters given by the optional \fIpath\fR +arguments, and for each interpreter, it also deletes its slaves. The +command also deletes the slave command for each interpreter deleted. +For each \fIpath\fR argument, if no interpreter by that name +exists, the command raises an error. +.TP +\fBinterp\fR \fBeval\fR \fIpath arg \fR?\fIarg ...\fR? +This command concatenates all of the \fIarg\fR arguments in the same +fashion as the \fBconcat\fR command, then evaluates the resulting string as +a Tcl script in the slave interpreter identified by \fIpath\fR. The result +of this evaluation (including error information such as the \fBerrorInfo\fR +and \fBerrorCode\fR variables, if an error occurs) is returned to the +invoking interpreter. +.TP +\fBinterp exists \fIpath\fR +Returns \fB1\fR if a slave interpreter by the specified \fIpath\fR +exists in this master, \fB0\fR otherwise. If \fIpath\fR is omitted, the +invoking interpreter is used. +.VS "" BR +.TP +\fBinterp expose \fIpath\fR \fIhiddenName\fR ?\fIexposedCmdName\fR? +Makes the hidden command \fIhiddenName\fR exposed, eventually bringing +it back under a new \fIexposedCmdName\fR name (this name is currently +accepted only if it is a valid global name space name without any ::), +in the interpreter +denoted by \fIpath\fR. +If an exposed command with the targetted name already exists, this command +fails. +Hidden commands are explained in more detail in HIDDEN COMMANDS, below. +.TP +\fBinterp\fR \fBhide\fR \fIpath\fR \fIexposedCmdName\fR ?\fIhiddenCmdName\fR? +Makes the exposed command \fIexposedCmdName\fR hidden, renaming +it to the hidden command \fIhiddenCmdName\fR, or keeping the same name if +\fIhiddenCmdName\fR is not given, in the interpreter denoted +by \fIpath\fR. +If a hidden command with the targetted name already exists, this command +fails. +Currently both \fIexposedCmdName\fR and \fIhiddenCmdName\fR can +not contain namespace qualifiers, or an error is raised. +Commands to be hidden by \fBinterp hide\fR are looked up in the global +namespace even if the current namespace is not the global one. This +prevents slaves from fooling a master interpreter into hiding the wrong +command, by making the current namespace be different from the global one. +Hidden commands are explained in more detail in HIDDEN COMMANDS, below. +.TP +\fBinterp\fR \fBhidden\fR \fIpath\fR +Returns a list of the names of all hidden commands in the interpreter +identified by \fIpath\fR. +.TP +\fBinterp\fR \fBinvokehidden\fR \fIpath\fR ?\fB-global\fR? \fIhiddenCmdName\fR ?\fIarg ...\fR? +Invokes the hidden command \fIhiddenCmdName\fR with the arguments supplied +in the interpreter denoted by \fIpath\fR. No substitutions or evaluation +are applied to the arguments. +If the \fB-global\fR flag is present, the hidden command is invoked at the +global level in the target interpreter; otherwise it is invoked at the +current call frame and can access local variables in that and outer call +frames. +Hidden commands are explained in more detail in HIDDEN COMMANDS, below. +.VE +.TP +\fBinterp issafe\fR ?\fIpath\fR? +Returns \fB1\fR if the interpreter identified by the specified \fIpath\fR +is safe, \fB0\fR otherwise. +.VS "" BR +.TP +\fBinterp marktrusted\fR \fIpath\fR +Marks the interpreter identified by \fIpath\fR as trusted. Does +not expose the hidden commands. This command can only be invoked from a +trusted interpreter. +The command has no effect if the interpreter identified by \fIpath\fR is +already trusted. +.VE +.TP +\fBinterp\fR \fBshare\fR \fIsrcPath channelId destPath\fR +Causes the IO channel identified by \fIchannelId\fR to become shared +between the interpreter identified by \fIsrcPath\fR and the interpreter +identified by \fIdestPath\fR. Both interpreters have the same permissions +on the IO channel. +Both interpreters must close it to close the underlying IO channel; IO +channels accessible in an interpreter are automatically closed when an +interpreter is destroyed. +.TP +\fBinterp\fR \fBslaves\fR ?\fIpath\fR? +Returns a Tcl list of the names of all the slave interpreters associated +with the interpreter identified by \fIpath\fR. If \fIpath\fR is omitted, +the invoking interpreter is used. +.TP +\fBinterp\fR \fBtarget\fR \fIpath alias\fR +Returns a Tcl list describing the target interpreter for an alias. The +alias is specified with an interpreter path and source command name, just +as in \fBinterp alias\fR above. The name of the target interpreter is +returned as an interpreter path, relative to the invoking interpreter. +If the target interpreter for the alias is the invoking interpreter then an +empty list is returned. If the target interpreter for the alias is not the +invoking interpreter or one of its descendants then an error is generated. +The target command does not have to be defined at the time of this invocation. +.TP +\fBinterp\fR \fBtransfer\fR \fIsrcPath channelId destPath\fR +Causes the IO channel identified by \fIchannelId\fR to become available in +the interpreter identified by \fIdestPath\fR and unavailable in the +interpreter identified by \fIsrcPath\fR. + +.SH "SLAVE COMMAND" +.PP +For each slave interpreter created with the \fBinterp\fR command, a +new Tcl command is created in the master interpreter with the same +name as the new interpreter. This command may be used to invoke +various operations on the interpreter. It has the following +general form: +.CS +\fIslave command \fR?\fIarg arg ...\fR? +.CE +\fISlave\fR is the name of the interpreter, and \fIcommand\fR +and the \fIarg\fRs determine the exact behavior of the command. +The valid forms of this command are: +.TP +\fIslave \fBaliases\fR +Returns a Tcl list whose elements are the names of all the +aliases in \fIslave\fR. The names returned are the \fIsrcCmd\fR +values used when the aliases were created (which may not be the same +as the current names of the commands, if they have been +renamed). +.TP +\fIslave \fBalias \fIsrcCmd\fR +Returns a Tcl list whose elements are the \fItargetCmd\fR and +\fIarg\fRs associated with the alias named \fIsrcCmd\fR +(all of these are the values specified when the alias was +created; it is possible that the actual source command in the +slave is different from \fIsrcCmd\fR if it was renamed). +.TP +\fIslave \fBalias \fIsrcCmd \fB{}\fR +Deletes the alias for \fIsrcCmd\fR in the slave interpreter. +\fIsrcCmd\fR refers to the name under which the alias +was created; if the source command has been renamed, the renamed +command will be deleted. +.TP +\fIslave \fBalias \fIsrcCmd targetCmd \fR?\fIarg ..\fR? +Creates an alias such that whenever \fIsrcCmd\fR is invoked +in \fIslave\fR, \fItargetCmd\fR is invoked in the master. +The \fIarg\fR arguments will be passed to \fItargetCmd\fR as additional +arguments, prepended before any arguments passed in the invocation of +\fIsrcCmd\fR. +See ALIAS INVOCATION below for details. +.TP +\fIslave \fBeval \fIarg \fR?\fIarg ..\fR? +This command concatenates all of the \fIarg\fR arguments in +the same fashion as the \fBconcat\fR command, then evaluates +the resulting string as a Tcl script in \fIslave\fR. +The result of this evaluation (including error information +such as the \fBerrorInfo\fR and \fBerrorCode\fR variables, if an +error occurs) is returned to the invoking interpreter. +.VS "" BR +.TP +\fIslave \fBexpose \fIhiddenName \fR?\fIexposedCmdName\fR? +This command exposes the hidden command \fIhiddenName\fR, eventually bringing +it back under a new \fIexposedCmdName\fR name (this name is currently +accepted only if it is a valid global name space name without any ::), +in \fIslave\fR. +If an exposed command with the targetted name already exists, this command +fails. +For more details on hidden commands, see HIDDEN COMMANDS, below. +.TP +\fIslave \fBhide \fIexposedCmdName\fR ?\fIhiddenCmdName\fR? +This command hides the exposed command \fIexposedCmdName\fR, renaming it to +the hidden command \fIhiddenCmdName\fR, or keeping the same name if the +the argument is not given, in the \fIslave\fR interpreter. +If a hidden command with the targetted name already exists, this command +fails. +Currently both \fIexposedCmdName\fR and \fIhiddenCmdName\fR can +not contain namespace qualifiers, or an error is raised. +Commands to be hidden are looked up in the global +namespace even if the current namespace is not the global one. This +prevents slaves from fooling a master interpreter into hiding the wrong +command, by making the current namespace be different from the global one. +For more details on hidden commands, see HIDDEN COMMANDS, below. +.TP +\fIslave \fBhidden\fR +Returns a list of the names of all hidden commands in \fIslave\fR. +.TP +\fIslave \fBinvokehidden\fR ?\fB-global\fR \fIhiddenName \fR?\fIarg ..\fR? +This command invokes the hidden command \fIhiddenName\fR with the +supplied arguments, in \fIslave\fR. No substitutions or evaluations are +applied to the arguments. +If the \fB-global\fR flag is given, the command is invoked at the global +level in the slave; otherwise it is invoked at the current call frame and +can access local variables in that or outer call frames. +For more details on hidden commands, see HIDDEN +COMMANDS, below. +.VE +.TP +\fIslave \fBissafe\fR +Returns \fB1\fR if the slave interpreter is safe, \fB0\fR otherwise. +.VS "" BR +.TP +\fIslave \fBmarktrusted\fR +Marks the slave interpreter as trusted. Can only be invoked by a +trusted interpreter. This command does not expose any hidden +commands in the slave interpreter. The command has no effect if the slave +is already trusted. +.VE + +.SH "SAFE INTERPRETERS" +.PP +A safe interpreter is one with restricted functionality, so that +is safe to execute an arbitrary script from your worst enemy without +fear of that script damaging the enclosing application or the rest +of your computing environment. In order to make an interpreter +safe, certain commands and variables are removed from the interpreter. +For example, commands to create files on disk are removed, and the +\fBexec\fR command is removed, since it could be used to cause damage +through subprocesses. +Limited access to these facilities can be provided, by creating +aliases to the master interpreter which check their arguments carefully +and provide restricted access to a safe subset of facilities. +For example, file creation might be allowed in a particular subdirectory +and subprocess invocation might be allowed for a carefully selected and +fixed set of programs. +.PP +A safe interpreter is created by specifying the \fB\-safe\fR switch +to the \fBinterp create\fR command. Furthermore, any slave created +by a safe interpreter will also be safe. +.PP +A safe interpreter is created with exactly the following set of +built-in commands: +.DS +.ta 1.2i 2.4i 3.6i +\fBafter append array binary +break case catch clock +close concat continue eof +error eval expr fblocked +fcopy fileevent flush for +foreach format gets global +history if incr info +interp join lappend lindex +linsert list llength lrange +lreplace lsearch lsort namespace +package pid proc puts +read regexp regsub rename +return scan seek set +split string subst switch +tell trace unset update +uplevel upvar variable vwait +while\fR +.DE +.VS "" BR +The following commands are hidden by \fBinterp create\fR when it +creates a safe interpreter: +.DS +.ta 1.2i 2.4i 3.6i +\fBcd exec exit fconfigure +file glob load open +pwd socket source vwait\fR +.DE +These commands can be recreated later as Tcl procedures or aliases, or +re-exposed by \fBinterp expose\fR. +.VE +.PP +In addition, the \fBenv\fR variable is not present in a safe interpreter, +so it cannot share environment variables with other interpreters. The +\fBenv\fR variable poses a security risk, because users can store +sensitive information in an environment variable. For example, the PGP +manual recommends storing the PGP private key protection password in +the environment variable \fIPGPPASS\fR. Making this variable available +to untrusted code executing in a safe interpreter would incur a +security risk. +.PP +If extensions are loaded into a safe interpreter, they may also restrict +their own functionality to eliminate unsafe commands. For a discussion of +management of extensions for safety see the manual entries for +\fBSafe\-Tcl\fR and the \fBload\fR Tcl command. + +.SH "ALIAS INVOCATION" +.PP +The alias mechanism has been carefully designed so that it can +be used safely when an untrusted script is executing +in a safe slave and the target of the alias is a trusted +master. The most important thing in guaranteeing safety is to +ensure that information passed from the slave to the master is +never evaluated or substituted in the master; if this were to +occur, it would enable an evil script in the slave to invoke +arbitrary functions in the master, which would compromise security. +.PP +When the source for an alias is invoked in the slave interpreter, the +usual Tcl substitutions are performed when parsing that command. +These substitutions are carried out in the source interpreter just +as they would be for any other command invoked in that interpreter. +The command procedure for the source command takes its arguments +and merges them with the \fItargetCmd\fR and \fIarg\fRs for the +alias to create a new array of arguments. If the words +of \fIsrcCmd\fR were ``\fIsrcCmd arg1 arg2 ... argN\fR'', +the new set of words will be +``\fItargetCmd arg arg ... arg arg1 arg2 ... argN\fR'', +where \fItargetCmd\fR and \fIarg\fRs are the values supplied when the +alias was created. \fITargetCmd\fR is then used to locate a command +procedure in the target interpreter, and that command procedure +is invoked with the new set of arguments. An error occurs if +there is no command named \fItargetCmd\fR in the target interpreter. +No additional substitutions are performed on the words: the +target command procedure is invoked directly, without +going through the normal Tcl evaluation mechanism. +Substitutions are thus performed on each word exactly once: +\fItargetCmd\fR and \fIargs\fR were substituted when parsing the command +that created the alias, and \fIarg1 - argN\fR are substituted when +the alias's source command is parsed in the source interpreter. +.PP +When writing the \fItargetCmd\fRs for aliases in safe interpreters, +it is very important that the arguments to that command never be +evaluated or substituted, since this would provide an escape +mechanism whereby the slave interpreter could execute arbitrary +code in the master. This in turn would compromise the security +of the system. + +.VS +.SH "HIDDEN COMMANDS" +.PP +Safe interpreters greatly restrict the functionality available to Tcl +programs executing within them. +Allowing the untrusted Tcl program to have direct access to this +functionality is unsafe, because it can be used for a variety of +attacks on the environment. +However, there are times when there is a legitimate need to use the +dangerous functionality in the context of the safe interpreter. For +example, sometimes a program must be \fBsource\fRd into the interpreter. +Another example is Tk, where windows are bound to the hierarchy of windows +for a specific interpreter; some potentially dangerous functions, e.g. +window management, must be performed on these windows within the +interpreter context. +.PP +The \fBinterp\fR command provides a solution to this problem in the form of +\fIhidden commands\fR. Instead of removing the dangerous commands entirely +from a safe interpreter, these commands are hidden so they become +unavailable to Tcl scripts executing in the interpreter. However, such +hidden commands can be invoked by any trusted ancestor of the safe +interpreter, in the context of the safe interpreter, using \fBinterp +invoke\fR. Hidden commands and exposed commands reside in separate name +spaces. It is possible to define a hidden command and an exposed command by +the same name within one interpreter. +.PP +Hidden commands in a slave interpreter can be invoked in the body of +procedures called in the master during alias invocation. For example, an +alias for \fBsource\fR could be created in a slave interpreter. When it is +invoked in the slave interpreter, a procedure is called in the master +interpreter to check that the operation is allowable (e.g. it asks to +source a file that the slave interpreter is allowed to access). The +procedure then it invokes the hidden \fBsource\fR command in the slave +interpreter to actually source in the contents of the file. Note that two +commands named \fBsource\fR exist in the slave interpreter: the alias, and +the hidden command. +.PP +Because a master interpreter may invoke a hidden command as part of +handling an alias invocation, great care must be taken to avoid evaluating +any arguments passed in through the alias invocation. +Otherwise, malicious slave interpreters could cause a trusted master +interpreter to execute dangerous commands on their behalf. See the section +on ALIAS INVOCATION for a more complete discussion of this topic. +To help avoid this problem, no substitutions or evaluations are +applied to arguments of \fBinterp invokehidden\fR. +.PP +Safe interpreters are not allowed to invoke hidden commands in themselves +or in their descendants. This prevents safe slaves from gaining access to +hidden functionality in themselves or their descendants. +.PP +The set of hidden commands in an interpreter can be manipulated by a trusted +interpreter using \fBinterp expose\fR and \fBinterp hide\fR. The \fBinterp +expose\fR command moves a hidden command to the +set of exposed commands in the interpreter identified by \fIpath\fR, +potentially renaming the command in the process. If an exposed command by +the targetted name already exists, the operation fails. Similarly, +\fBinterp hide\fR moves an exposed command to the set of hidden commands in +that interpreter. Safe interpreters are not allowed to move commands +between the set of hidden and exposed commands, in either themselves or +their descendants. +.PP +Currently, the names of hidden commands cannot contain namespace +qualifiers, and you must first rename a command in a namespace to the +global namespace before you can hide it. +Commands to be hidden by \fBinterp hide\fR are looked up in the global +namespace even if the current namespace is not the global one. This +prevents slaves from fooling a master interpreter into hiding the wrong +command, by making the current namespace be different from the global one. +.VE +.SH CREDITS +.PP +This mechanism is based on the Safe-Tcl prototype implemented +by Nathaniel Borenstein and Marshall Rose. + +.SH "SEE ALSO" +load(n), safe(n), Tcl_CreateSlave(3) + +.SH KEYWORDS +alias, master interpreter, safe interpreter, slave interpreter diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/join.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/join.n new file mode 100644 index 0000000000000000000000000000000000000000..5e03b26300f254e64a0daad68fe8bd00bb8e9205 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/join.n @@ -0,0 +1,32 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: join.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH join n "" Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +join \- Create a string by joining together list elements +.SH SYNOPSIS +\fBjoin \fIlist \fR?\fIjoinString\fR? +.BE + +.SH DESCRIPTION +.PP +The \fIlist\fR argument must be a valid Tcl list. +This command returns the string +formed by joining all of the elements of \fIlist\fR together with +\fIjoinString\fR separating each adjacent pair of elements. +The \fIjoinString\fR argument defaults to a space character. + +.SH "SEE ALSO" +list(n), lappend(n) + +.SH KEYWORDS +element, join, list, separator diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/lappend.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/lappend.n new file mode 100644 index 0000000000000000000000000000000000000000..64f46546fb45ffb30f8ff332a54f916f7e117a31 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/lappend.n @@ -0,0 +1,38 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: lappend.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH lappend n "" Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +lappend \- Append list elements onto a variable +.SH SYNOPSIS +\fBlappend \fIvarName \fR?\fIvalue value value ...\fR? +.BE + +.SH DESCRIPTION +.PP +This command treats the variable given by \fIvarName\fR as a list +and appends each of the \fIvalue\fR arguments to that list as a separate +element, with spaces between elements. +If \fIvarName\fR doesn't exist, it is created as a list with elements +given by the \fIvalue\fR arguments. +\fBLappend\fR is similar to \fBappend\fR except that the \fIvalue\fRs +are appended as list elements rather than raw text. +This command provides a relatively efficient way to build up +large lists. For example, ``\fBlappend a $b\fR'' is much +more efficient than ``\fBset a [concat $a [list $b]]\fR'' when +\fB$a\fR is long. + +.SH "SEE ALSO" +list(n), lindex(n), linsert(n), llength(n), lsort(n), lrange(n) + +.SH KEYWORDS +append, element, list, variable diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/library.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/library.n new file mode 100644 index 0000000000000000000000000000000000000000..e2d22d6fab37474075f39ef88bc400758dcfa282 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/library.n @@ -0,0 +1,311 @@ +'\" +'\" Copyright (c) 1991-1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: library.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +.so man.macros +.TH library n "8.0" Tcl "Tcl Built-In Commands" +.BS +.SH NAME +auto_execok, auto_import, auto_load, auto_mkindex, auto_mkindex_old, auto_qualify, auto_reset, tcl_findLibrary, parray, tcl_endOfWord, tcl_startOfNextWord, tcl_startOfPreviousWord, tcl_wordBreakAfter, tcl_wordBreakBefore \- standard library of Tcl procedures +.SH SYNOPSIS +.nf +\fBauto_execok \fIcmd\fR +\fBauto_import \fIpattern\fR +\fBauto_load \fIcmd\fR +\fBauto_mkindex \fIdir pattern pattern ...\fR +\fBauto_mkindex_old \fIdir pattern pattern ...\fR +\fBauto_qualify \fIcommand namespace\fR +\fBauto_reset\fR +\fBtcl_findLibrary \fIbasename version patch initScript enVarName varName\fR +\fBparray \fIarrayName\fR +.VS +\fBtcl_endOfWord \fIstr start\fR +\fBtcl_startOfNextWord \fIstr start\fR +\fBtcl_startOfPreviousWord \fIstr start\fR +\fBtcl_wordBreakAfter \fIstr start\fR +\fBtcl_wordBreakBefore \fIstr start\fR +.VE +.BE + +.SH INTRODUCTION +.PP +Tcl includes a library of Tcl procedures for commonly-needed functions. +The procedures defined in the Tcl library are generic ones suitable +for use by many different applications. +The location of the Tcl library is returned by the \fBinfo library\fR +command. +In addition to the Tcl library, each application will normally have +its own library of support procedures as well; the location of this +library is normally given by the value of the \fB$\fIapp\fB_library\fR +global variable, where \fIapp\fR is the name of the application. +For example, the location of the Tk library is kept in the variable +\fB$tk_library\fR. +.PP +To access the procedures in the Tcl library, an application should +source the file \fBinit.tcl\fR in the library, for example with +the Tcl command +.CS +\fBsource [file join [info library] init.tcl]\fR +.CE +If the library procedure \fBTcl_Init\fR is invoked from an application's +\fBTcl_AppInit\fR procedure, this happens automatically. +The code in \fBinit.tcl\fR will define the \fBunknown\fR procedure +and arrange for the other procedures to be loaded on-demand using +the auto-load mechanism defined below. + +.SH "COMMAND PROCEDURES" +.PP +The following procedures are provided in the Tcl library: +.TP +\fBauto_execok \fIcmd\fR +Determines whether there is an executable file or shell builtin +by the name \fIcmd\fR. If so, it returns a list of arguments to be +passed to \fBexec\fR to execute the executable file or shell builtin +named by \fIcmd\fR. If not, it returns an empty string. This command +examines the directories in the current search path (given by the PATH +environment variable) in its search for an executable file named +\fIcmd\fR. On Windows platforms, the search is expanded with the same +directories and file extensions as used by \fBexec\fR. \fBAuto_exec\fR +remembers information about previous searches in an array named +\fBauto_execs\fR; this avoids the path search in future calls for the +same \fIcmd\fR. The command \fBauto_reset\fR may be used to force +\fBauto_execok\fR to forget its cached information. +.TP +\fBauto_import \fIpattern\fR +\fBAuto_import\fR is invoked during \fBnamespace import\fR to see if +the imported commands specified by \fIpattern\fR reside in an +autoloaded library. If so, the commands are loaded so that they will +be available to the interpreter for creating the import links. If the +commands do not reside in an autoloaded library, \fBauto_import\fR +does nothing. The pattern matching is performed according to the +matching rules of \fBnamespace import\fR. +.TP +\fBauto_load \fIcmd\fR +This command attempts to load the definition for a Tcl command named +\fIcmd\fR. To do this, it searches an \fIauto-load path\fR, which is +a list of one or more directories. The auto-load path is given by the +global variable \fB$auto_path\fR if it exists. If there is no +\fB$auto_path\fR variable, then the TCLLIBPATH environment variable is +used, if it exists. Otherwise the auto-load path consists of just the +Tcl library directory. Within each directory in the auto-load path +there must be a file \fBtclIndex\fR that describes one or more +commands defined in that directory and a script to evaluate to load +each of the commands. The \fBtclIndex\fR file should be generated +with the \fBauto_mkindex\fR command. If \fIcmd\fR is found in an +index file, then the appropriate script is evaluated to create the +command. The \fBauto_load\fR command returns 1 if \fIcmd\fR was +successfully created. The command returns 0 if there was no index +entry for \fIcmd\fR or if the script didn't actually define \fIcmd\fR +(e.g. because index information is out of date). If an error occurs +while processing the script, then that error is returned. +\fBAuto_load\fR only reads the index information once and saves it in +the array \fBauto_index\fR; future calls to \fBauto_load\fR check for +\fIcmd\fR in the array rather than re-reading the index files. The +cached index information may be deleted with the command +\fBauto_reset\fR. This will force the next \fBauto_load\fR command to +reload the index database from disk. +.TP +\fBauto_mkindex \fIdir pattern pattern ...\fR +Generates an index suitable for use by \fBauto_load\fR. The command +searches \fIdir\fR for all files whose names match any of the +\fIpattern\fR arguments (matching is done with the \fBglob\fR +command), generates an index of all the Tcl command procedures defined +in all the matching files, and stores the index information in a file +named \fBtclIndex\fR in \fIdir\fR. If no pattern is given a pattern of +\fB*.tcl\fR will be assumed. For example, the command +.RS +.CS +\fBauto_mkindex foo *.tcl\fR +.CE +.LP +will read all the \fB.tcl\fR files in subdirectory \fBfoo\fR and +generate a new index file \fBfoo/tclIndex\fR. +.PP +\fBAuto_mkindex\fR parses the Tcl scripts by sourcing them into a +slave interpreter and monitoring the proc and namespace commands that +are executed. Extensions can use the (undocumented) +auto_mkindex_parser package to register other commands that can +contribute to the auto_load index. You will have to read through +auto.tcl to see how this works. +.PP +\fBAuto_mkindex_old\fR parses the Tcl scripts in a relatively +unsophisticated way: if any line contains the word \fBproc\fR +as its first characters then it is assumed to be a procedure +definition and the next word of the line is taken as the +procedure's name. +Procedure definitions that don't appear in this way (e.g. they +have spaces before the \fBproc\fR) will not be indexed. If your +script contains "dangerous" code, such as global initialization +code or procedure names with special characters like \fB$\fR, +\fB*\fR, \fB[\fR or \fB]\fR, you are safer using auto_mkindex_old. +.RE +.TP +\fBauto_reset\fR +Destroys all the information cached by \fBauto_execok\fR and +\fBauto_load\fR. This information will be re-read from disk the next +time it is needed. \fBAuto_reset\fR also deletes any procedures +listed in the auto-load index, so that fresh copies of them will be +loaded the next time that they're used. +.TP +\fBauto_qualify \fIcommand namespace\fR +Computes a list of fully qualified names for \fIcommand\fR. This list +mirrors the path a standard Tcl interpreter follows for command +lookups: first it looks for the command in the current namespace, and +then in the global namespace. Accordingly, if \fIcommand\fR is +relative and \fInamespace\fR is not \fB::\fR, the list returned has +two elements: \fIcommand\fR scoped by \fInamespace\fR, as if it were +a command in the \fInamespace\fR namespace; and \fIcommand\fR as if it +were a command in the global namespace. Otherwise, if either +\fIcommand\fR is absolute (it begins with \fB::\fR), or +\fInamespace\fR is \fB::\fR, the list contains only \fIcommand\fR as +if it were a command in the global namespace. +.RS +.PP +\fBAuto_qualify\fR is used by the auto-loading facilities in Tcl, both +for producing auto-loading indexes such as \fIpkgIndex.tcl\fR, and for +performing the actual auto-loading of functions at runtime. +.RE +.TP +\fBtcl_findLibrary \fIbasename version patch initScript enVarName varName\fR +This is a standard search procedure for use by extensions during +their initialization. They call this procedure to look for their +script library in several standard directories. +The last component of the name of the library directory is +normally \fIbasenameversion\fP +(e.g., tk8.0), but it might be "library" when in the build hierarchies. +The \fIinitScript\fR file will be sourced into the interpreter +once it is found. The directory in which this file is found is +stored into the global variable \fIvarName\fP. +If this variable is already defined (e.g., by C code during +application initialization) then no searching is done. +Otherwise the search looks in these directories: +the directory named by the environment variable \fIenVarName\fP; +relative to the Tcl library directory; +relative to the executable file in the standard installation +bin or bin/\fIarch\fP directory; +relative to the executable file in the current build tree; +relative to the executable file in a parallel build tree. +.TP +\fBparray \fIarrayName\fR +Prints on standard output the names and values of all the elements +in the array \fIarrayName\fR. +\fBArrayName\fR must be an array accessible to the caller of \fBparray\fR. +It may be either local or global. +.TP +\fBtcl_endOfWord \fIstr start\fR +.VS +Returns the index of the first end-of-word location that occurs after +a starting index \fIstart\fR in the string \fIstr\fR. An end-of-word +location is defined to be the first non-word character following the +first word character after the starting point. Returns -1 if there +are no more end-of-word locations after the starting point. See the +description of \fBtcl_wordchars\fR and \fBtcl_nonwordchars\fR below +for more details on how Tcl determines which characters are word +characters. +.TP +\fBtcl_startOfNextWord \fIstr start\fR +Returns the index of the first start-of-word location that occurs +after a starting index \fIstart\fR in the string \fIstr\fR. A +start-of-word location is defined to be the first word character +following a non-word character. Returns \-1 if there are no more +start-of-word locations after the starting point. +.TP +\fBtcl_startOfPreviousWord \fIstr start\fR +Returns the index of the first start-of-word location that occurs +before a starting index \fIstart\fR in the string \fIstr\fR. Returns +\-1 if there are no more start-of-word locations before the starting +point. +.TP +\fBtcl_wordBreakAfter \fIstr start\fR +Returns the index of the first word boundary after the starting index +\fIstart\fR in the string \fIstr\fR. Returns \-1 if there are no more +boundaries after the starting point in the given string. The index +returned refers to the second character of the pair that comprises a +boundary. +.TP +\fBtcl_wordBreakBefore \fIstr start\fR +Returns the index of the first word boundary before the starting index +\fIstart\fR in the string \fIstr\fR. Returns \-1 if there are no more +boundaries before the starting point in the given string. The index +returned refers to the second character of the pair that comprises a +boundary. +.VE + +.SH "VARIABLES" +.PP +The following global variables are defined or used by the procedures in +the Tcl library: +.TP +\fBauto_execs\fR +Used by \fBauto_execok\fR to record information about whether +particular commands exist as executable files. +.TP +\fBauto_index\fR +Used by \fBauto_load\fR to save the index information read from +disk. +.TP +\fBauto_noexec\fR +If set to any value, then \fBunknown\fR will not attempt to auto-exec +any commands. +.TP +\fBauto_noload\fR +If set to any value, then \fBunknown\fR will not attempt to auto-load +any commands. +.TP +\fBauto_path\fR +If set, then it must contain a valid Tcl list giving directories to +search during auto-load operations. +This variable is initialized during startup to contain, in order: +the directories listed in the TCLLIBPATH environment variable, +the directory named by the $tcl_library variable, +the parent directory of $tcl_library, +the directories listed in the $tcl_pkgPath variable. +.TP +\fBenv(TCL_LIBRARY)\fR +If set, then it specifies the location of the directory containing +library scripts (the value of this variable will be +assigned to the \fBtcl_library\fR variable and therefore returned by +the command \fBinfo library\fR). If this variable isn't set then +a default value is used. +.TP +\fBenv(TCLLIBPATH)\fR +If set, then it must contain a valid Tcl list giving directories to +search during auto-load operations. Directories must be specified in +Tcl format, using "/" as the path separator, regardless of platform. +This variable is only used when initializing the \fBauto_path\fR variable. +.TP +\fBtcl_nonwordchars\fR +.VS +This variable contains a regular expression that is used by routines +like \fBtcl_endOfWord\fR to identify whether a character is part of a +word or not. If the pattern matches a character, the character is +considered to be a non-word character. On Windows platforms, spaces, +tabs, and newlines are considered non-word characters. Under Unix, +everything but numbers, letters and underscores are considered +non-word characters. +.TP +\fBtcl_wordchars\fR +This variable contains a regular expression that is used by routines +like \fBtcl_endOfWord\fR to identify whether a character is part of a +word or not. If the pattern matches a character, the character is +considered to be a word character. On Windows platforms, words are +comprised of any character that is not a space, tab, or newline. Under +Unix, words are comprised of numbers, letters or underscores. +.VE +.TP +\fBunknown_pending\fR +Used by \fBunknown\fR to record the command(s) for which it is +searching. +It is used to detect errors where \fBunknown\fR recurses on itself +infinitely. +The variable is unset before \fBunknown\fR returns. + +.SH "SEE ALSO" +info(n), re_syntax(n) + +.SH KEYWORDS +auto-exec, auto-load, library, unknown, word, whitespace diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/license.terms b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/license.terms new file mode 100644 index 0000000000000000000000000000000000000000..9df3e600352c50b7526dc4cb90758689d16ecee2 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/license.terms @@ -0,0 +1,39 @@ +This software is copyrighted by the Regents of the University of +California, Sun Microsystems, Inc., Scriptics Corporation, +and other parties. The following terms apply to all files associated +with the software unless explicitly disclaimed in individual files. + +The authors hereby grant permission to use, copy, modify, distribute, +and license this software and its documentation for any purpose, provided +that existing copyright notices are retained in all copies and that this +notice is included verbatim in any distributions. No written agreement, +license, or royalty fee is required for any of the authorized uses. +Modifications to this software may be copyrighted by their authors +and need not follow the licensing terms described here, provided that +the new terms are clearly indicated on the first page of each file where +they apply. + +IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY +FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES +ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY +DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE +IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE +NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR +MODIFICATIONS. + +GOVERNMENT USE: If you are acquiring this software on behalf of the +U.S. government, the Government shall have only "Restricted Rights" +in the software and related documentation as defined in the Federal +Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you +are acquiring the software on behalf of the Department of Defense, the +software shall be classified as "Commercial Computer Software" and the +Government shall have only "Restricted Rights" as defined in Clause +252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the +authors grant the U.S. Government and others acting in its behalf +permission to use and distribute the software in accordance with the +terms specified in this license. diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/lindex.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/lindex.n new file mode 100644 index 0000000000000000000000000000000000000000..ebaa487520e67c6e346d377404250c40d455946e --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/lindex.n @@ -0,0 +1,40 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: lindex.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH lindex n 8.2 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +lindex \- Retrieve an element from a list +.SH SYNOPSIS +\fBlindex \fIlist index\fR +.BE + +.SH DESCRIPTION +.PP +This command treats \fIlist\fR as a Tcl list and returns the +\fIindex\fR'th element from it (0 refers to the first element of the list). +In extracting the element, \fIlindex\fR observes the same rules +concerning braces and quotes and backslashes as the Tcl command +interpreter; however, variable +substitution and command substitution do not occur. +If \fIindex\fR is negative or greater than or equal to the number +of elements in \fIvalue\fR, then an empty +string is returned. +If \fIindex\fR has the value \fBend\fR, it refers to the last element +in the list, and \fBend\-\fIinteger\fR refers to the last element in +the list minus the specified integer offset. + +.SH "SEE ALSO" +list(n), lappend(n), linsert(n), llength(n), lsearch(n), lsort(n), +lrange(n), lreplace(n) + +.SH KEYWORDS +element, index, list diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/linsert.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/linsert.n new file mode 100644 index 0000000000000000000000000000000000000000..f4047737170443f705ede7c4a92ab80c0185ec62 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/linsert.n @@ -0,0 +1,36 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: linsert.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH linsert n 8.2 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +linsert \- Insert elements into a list +.SH SYNOPSIS +\fBlinsert \fIlist index element \fR?\fIelement element ...\fR? +.BE + +.SH DESCRIPTION +.PP +This command produces a new list from \fIlist\fR by inserting all of the +\fIelement\fR arguments just before the \fIindex\fRth element of +\fIlist\fR. Each \fIelement\fR argument will become a separate element of +the new list. If \fIindex\fR is less than or equal to zero, then the new +elements are inserted at the beginning of the list. If \fIindex\fR has the +value \fBend\fR, or if it is greater than or equal to the number of +elements in the list, then the new elements are appended to the list. +\fBend\-\fIinteger\fR refers to the last element in the list minus the +specified integer offset. + +.SH "SEE ALSO" +list(n), lappend(n), llength(n) + +.SH KEYWORDS +element, insert, list diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/list.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/list.n new file mode 100644 index 0000000000000000000000000000000000000000..0f9c2feda472ef37be81e762bb2aa5e11b7d9c04 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/list.n @@ -0,0 +1,49 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: list.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH list n "" Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +list \- Create a list +.SH SYNOPSIS +\fBlist \fR?\fIarg arg ...\fR? +.BE + +.SH DESCRIPTION +.PP +This command returns a list comprised of all the \fIarg\fRs, +or an empty string if no \fIarg\fRs are specified. +Braces and backslashes get added as necessary, so that the \fBindex\fR command +may be used on the result to re-extract the original arguments, and also +so that \fBeval\fR may be used to execute the resulting list, with +\fIarg1\fR comprising the command's name and the other \fIarg\fRs comprising +its arguments. \fBList\fR produces slightly different results than +\fBconcat\fR: \fBconcat\fR removes one level of grouping before forming +the list, while \fBlist\fR works directly from the original arguments. +For example, the command +.CS +\fBlist a b {c d e} {f {g h}}\fR +.CE +will return +.CS +\fBa b {c d e} {f {g h}}\fR +.CE +while \fBconcat\fR with the same arguments will return +.CS +\fBa b c d e f {g h}\fR +.CE + +.SH "SEE ALSO" +lappend(n), lindex(n), linsert(n), llength(n), lsearch(n), lsort(n), +lrange(n), lreplace(n) + +.SH KEYWORDS +element, list diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/llength.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/llength.n new file mode 100644 index 0000000000000000000000000000000000000000..fa84882f043bf0b691dc0dfa8f39bd3b50c4b584 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/llength.n @@ -0,0 +1,29 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: llength.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH llength n "" Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +llength \- Count the number of elements in a list +.SH SYNOPSIS +\fBllength \fIlist\fR +.BE + +.SH DESCRIPTION +.PP +Treats \fIlist\fR as a list and returns a decimal string giving +the number of elements in it. + +.SH "SEE ALSO" +list(n), lindex(n), lrange(n) + +.SH KEYWORDS +element, list, length diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/load.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/load.n new file mode 100644 index 0000000000000000000000000000000000000000..20835aaa5e670eeb0a91377e69c07057f4d480ef --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/load.n @@ -0,0 +1,135 @@ +'\" +'\" Copyright (c) 1995-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: load.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH load n 7.5 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +load \- Load machine code and initialize new commands. +.SH SYNOPSIS +\fBload \fIfileName\fR +.br +\fBload \fIfileName packageName\fR +.br +\fBload \fIfileName packageName interp\fR +.BE + +.SH DESCRIPTION +.PP +This command loads binary code from a file into the +application's address space and calls an initialization procedure +in the package to incorporate it into an interpreter. \fIfileName\fR +is the name of the file containing the code; its exact form varies +from system to system but on most systems it is a shared library, +such as a \fB.so\fR file under Solaris or a DLL under Windows. +\fIpackageName\fR is the name of the package, and is used to +compute the name of an initialization procedure. +\fIinterp\fR is the path name of the interpreter into which to load +the package (see the \fBinterp\fR manual entry for details); +if \fIinterp\fR is omitted, it defaults to the +interpreter in which the \fBload\fR command was invoked. +.PP +Once the file has been loaded into the application's address space, +one of two initialization procedures will be invoked in the new code. +Typically the initialization procedure will add new commands to a +Tcl interpreter. +The name of the initialization procedure is determined by +\fIpackageName\fR and whether or not the target interpreter +is a safe one. For normal interpreters the name of the initialization +procedure will have the form \fIpkg\fB_Init\fR, where \fIpkg\fR +is the same as \fIpackageName\fR except that the first letter is +converted to upper case and all other letters +are converted to lower case. For example, if \fIpackageName\fR is +\fBfoo\fR or \fBFOo\fR, the initialization procedure's name will +be \fBFoo_Init\fR. +.PP +If the target interpreter is a safe interpreter, then the name +of the initialization procedure will be \fIpkg\fB_SafeInit\fR +instead of \fIpkg\fB_Init\fR. +The \fIpkg\fB_SafeInit\fR function should be written carefully, so that it +initializes the safe interpreter only with partial functionality provided +by the package that is safe for use by untrusted code. For more information +on Safe\-Tcl, see the \fBsafe\fR manual entry. +.PP +The initialization procedure must match the following prototype: +.CS +typedef int Tcl_PackageInitProc(Tcl_Interp *\fIinterp\fR); +.CE +The \fIinterp\fR argument identifies the interpreter in which the +package is to be loaded. The initialization procedure must return +\fBTCL_OK\fR or \fBTCL_ERROR\fR to indicate whether or not it completed +successfully; in the event of an error it should set the interpreter's result +to point to an error message. The result of the \fBload\fR command +will be the result returned by the initialization procedure. +.PP +The actual loading of a file will only be done once for each \fIfileName\fR +in an application. If a given \fIfileName\fR is loaded into multiple +interpreters, then the first \fBload\fR will load the code and +call the initialization procedure; subsequent \fBload\fRs will +call the initialization procedure without loading the code again. +It is not possible to unload or reload a package. +.PP +The \fBload\fR command also supports packages that are statically +linked with the application, if those packages have been registered +by calling the \fBTcl_StaticPackage\fR procedure. +If \fIfileName\fR is an empty string, then \fIpackageName\fR must +be specified. +.PP +If \fIpackageName\fR is omitted or specified as an empty string, +Tcl tries to guess the name of the package. +This may be done differently on different platforms. +The default guess, which is used on most UNIX platforms, is to +take the last element of \fIfileName\fR, strip off the first +three characters if they are \fBlib\fR, and use any following +.VS +alphabetic and underline characters as the module name. +.VE +For example, the command \fBload libxyz4.2.so\fR uses the module +name \fBxyz\fR and the command \fBload bin/last.so {}\fR uses the +module name \fBlast\fR. +.VS "" br +.PP +If \fIfileName\fR is an empty string, then \fIpackageName\fR must +be specified. +The \fBload\fR command first searches for a statically loaded package +(one that has been registered by calling the \fBTcl_StaticPackage\fR +procedure) by that name; if one is found, it is used. +Otherwise, the \fBload\fR command searches for a dynamically loaded +package by that name, and uses it if it is found. If several +different files have been \fBload\fRed with different versions of +the package, Tcl picks the file that was loaded first. +.VE + +.SH "PORTABILITY ISSUES" +.TP +\fBWindows\fR\0\0\0\0\0 +. +When a load fails with "library not found" error, it is also possible +that a dependent library was not found. To see the dependent libraries, +type ``dumpbin -imports '' in a DOS console to see what the +library must import. +When loading a DLL in the current directory, Windows will ignore ``./'' as +a path specifier and use a search heuristic to find the DLL instead. +To avoid this, load the DLL with +.CS + load [file join [pwd] mylib.DLL] +.CE + +.SH BUGS +.PP +If the same file is \fBload\fRed by different \fIfileName\fRs, it will +be loaded into the process's address space multiple times. The +behavior of this varies from system to system (some systems may +detect the redundant loads, others may not). + +.SH "SEE ALSO" +\fBinfo sharedlibextension\fR, Tcl_StaticPackage(3), safe(n) + +.SH KEYWORDS +binary code, loading, safe interpreter, shared library diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/lrange.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/lrange.n new file mode 100644 index 0000000000000000000000000000000000000000..de74553ccc16d4440708ae4df4023c8ecb904e8b --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/lrange.n @@ -0,0 +1,42 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: lrange.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH lrange n 7.4 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +lrange \- Return one or more adjacent elements from a list +.SH SYNOPSIS +\fBlrange \fIlist first last\fR +.BE + +.SH DESCRIPTION +.PP +\fIList\fR must be a valid Tcl list. This command will +return a new list consisting of elements +\fIfirst\fR through \fIlast\fR, inclusive. +\fIFirst\fR or \fIlast\fR +may be \fBend\fR (or any abbreviation of it) to refer to the last +element of the list. +If \fIfirst\fR is less than zero, it is treated as if it were zero. +If \fIlast\fR is greater than or equal to the number of elements +in the list, then it is treated as if it were \fBend\fR. +If \fIfirst\fR is greater than \fIlast\fR then an empty string +is returned. +Note: ``\fBlrange \fIlist first first\fR'' does not always produce the +same result as ``\fBlindex \fIlist first\fR'' (although it often does +for simple fields that aren't enclosed in braces); it does, however, +produce exactly the same results as ``\fBlist [lindex \fIlist first\fB]\fR'' + +.SH "SEE ALSO" +lappend(n), lindex(n), linsert(n), list(n), llength(n), lreplace(n) + +.SH KEYWORDS +element, list, range, sublist diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/lreplace.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/lreplace.n new file mode 100644 index 0000000000000000000000000000000000000000..bca9870e121c2401167dbefa2c8d1bad0d0f3aeb --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/lreplace.n @@ -0,0 +1,51 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: lreplace.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH lreplace n 7.4 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +lreplace \- Replace elements in a list with new elements +.SH SYNOPSIS +\fBlreplace \fIlist first last \fR?\fIelement element ...\fR? +.BE + +.SH DESCRIPTION +.PP +\fBlreplace\fR returns a new list formed by replacing one or more elements of +\fIlist\fR with the \fIelement\fR arguments. +\fIfirst\fR and \fIlast\fR specify the first and last index of the +range of elements to replace. 0 refers to the first element of the +list, and \fBend\fR (or any abbreviation of it) may be used to refer +to the last element of the list. If \fIlist\fR is empty, then +\fIfirst\fR and \fIlast\fR are ignored. + +If \fIfirst\fR is less than zero, it is considered to refer to the +first element of the list. For non-empty lists, the element indicated +by \fIfirst\fR must exist. + +If \fIlast\fR is less than zero but greater than \fIfirst\fR, then any +specified elements will be prepended to the list. If \fIlast\fR is +less than \fIfirst\fR then no elements are deleted; the new elements +are simply inserted before \fIfirst\fR. + +The \fIelement\fR arguments specify zero or more new arguments to +be added to the list in place of those that were deleted. +Each \fIelement\fR argument will become a separate element of +the list. If no \fIelement\fR arguments are specified, then the elements +between \fIfirst\fR and \fIlast\fR are simply deleted. If \fIlist\fR +is empty, any \fIelement\fR arguments are added to the end of the list. + +.SH "SEE ALSO" +lappend(n), lindex(n), linsert(n), list(n), llength(n), lrange(n), +lsearch(n), lsort(n) + +.SH KEYWORDS +element, list, replace diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/lsearch.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/lsearch.n new file mode 100644 index 0000000000000000000000000000000000000000..c37e904f278d4d7ab250baefcd235cb35da4db9d --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/lsearch.n @@ -0,0 +1,46 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: lsearch.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH lsearch n 7.0 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +lsearch \- See if a list contains a particular element +.SH SYNOPSIS +\fBlsearch \fR?\fImode\fR? \fIlist pattern\fR +.BE + +.SH DESCRIPTION +.PP +This command searches the elements of \fIlist\fR to see if one +of them matches \fIpattern\fR. +If so, the command returns the index of the first matching +element. +If not, the command returns \fB\-1\fR. +The \fImode\fR argument indicates how the elements of the list are to +be matched against \fIpattern\fR and it must have one of the following +values: +.TP +\fB\-exact\fR +The list element must contain exactly the same string as \fIpattern\fR. +.TP +\fB\-glob\fR +\fIPattern\fR is a glob-style pattern which is matched against each list +element using the same rules as the \fBstring match\fR command. +.TP +\fB\-regexp\fR +\fIPattern\fR is treated as a regular expression and matched against +each list element using the rules described in the \fBre_syntax\fR +reference page. +.PP +If \fImode\fR is omitted then it defaults to \fB\-glob\fR. + +.SH KEYWORDS +list, match, pattern, regular expression, search, string diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/lsort.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/lsort.n new file mode 100644 index 0000000000000000000000000000000000000000..496256fdb2f346e55fe3f861fb3a7f97c42412b1 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/lsort.n @@ -0,0 +1,191 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" Copyright (c) 1999 Scriptics Corporation +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: lsort.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH lsort n 8.3 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +lsort \- Sort the elements of a list +.SH SYNOPSIS +\fBlsort \fR?\fIoptions\fR? \fIlist\fR +.BE + +.SH DESCRIPTION +.PP +This command sorts the elements of \fIlist\fR, returning a new +list in sorted order. The implementation of the \fBlsort\fR command +uses the merge\-sort algorithm which is a stable sort that has O(n log +n) performance characteristics. +.PP +By default ASCII sorting is used with the result returned in +increasing order. However, any of the following options may be +specified before \fIlist\fR to control the sorting process (unique +abbreviations are accepted): +.TP 20 +\fB\-ascii\fR +Use string comparison with ASCII collation order. This is the default. +.TP 20 +\fB\-dictionary\fR +Use dictionary-style comparison. This is the same as \fB\-ascii\fR +except (a) case is ignored except as a tie-breaker and (b) if two +strings contain embedded numbers, the numbers compare as integers, +not characters. For example, in \fB\-dictionary\fR mode, \fBbigBoy\fR +sorts between \fBbigbang\fR and \fBbigboy\fR, and \fBx10y\fR +sorts between \fBx9y\fR and \fBx11y\fR. +.TP 20 +\fB\-integer\fR +Convert list elements to integers and use integer comparison. +.TP 20 +\fB\-real\fR +Convert list elements to floating-point values and use floating comparison. +.TP 20 +\fB\-command\0\fIcommand\fR +Use \fIcommand\fR as a comparison command. +To compare two elements, evaluate a Tcl script consisting of +\fIcommand\fR with the two elements appended as additional +arguments. The script should return an integer less than, +equal to, or greater than zero if the first element is to +be considered less than, equal to, or greater than the second, +respectively. +.TP 20 +\fB\-increasing\fR +Sort the list in increasing order (``smallest'' items first). +This is the default. +.TP 20 +\fB\-decreasing\fR +Sort the list in decreasing order (``largest'' items first). +.TP 20 +\fB\-index\0\fIindex\fR +If this option is specified, each of the elements of \fIlist\fR must +itself be a proper Tcl sublist. Instead of sorting based on whole +sublists, \fBlsort\fR will extract the \fIindex\fR'th element from +each sublist and sort based on the given element. The keyword +\fBend\fP is allowed for the \fIindex\fP to sort on the last sublist +element, +.VS 8.3.4 +and \fBend-\fIindex\fR sorts on a sublist element offset from +the end. +.VE +For example, +.RS +.CS +lsort -integer -index 1 {{First 24} {Second 18} {Third 30}} +.CE +returns \fB{Second 18} {First 24} {Third 30}\fR, and +.VS 8.3.4 +'\" +'\" This example is from the test suite! +'\" +.CS +lsort -index end-1 {{a 1 e i} {b 2 3 f g} {c 4 5 6 d h}} +.CE +returns \fB{c 4 5 6 d h} {a 1 e i} {b 2 3 f g}\fR. +.VE +This option is much more efficient than using \fB\-command\fR +to achieve the same effect. +.RE +.TP 20 +\fB\-unique\fR +If this option is specified, then only the last set of duplicate +elements found in the list will be retained. Note that duplicates are +determined relative to the comparison used in the sort. Thus if +\fI-index 0\fR is used, \fB{1 a}\fR and \fB{1 b}\fR would be +considered duplicates and only the second element, \fB{1 b}\fR, would +be retained. + +.SH "NOTES" +.PP +The options to \fBlsort\fR only control what sort of comparison is +used, and do not necessarily constrain what the values themselves +actually are. This distinction is only noticeable when the list to be +sorted has fewer than two elements. +.PP +The \fBlsort\fR command is reentrant, meaning it is safe to use as +part of the implementation of a command used in the \fB\-command\fR +option. + +.SH "EXAMPLES" + +.PP +Sorting a list using ASCII sorting: +.CS +% lsort {a10 B2 b1 a1 a2} +B2 a1 a10 a2 b1 +.CE + +.PP +Sorting a list using Dictionary sorting: +.CS +% lsort -dictionary {a10 B2 b1 a1 a2} +a1 a2 a10 b1 B2 +.CE + +.PP +Sorting lists of integers: +.CS +% lsort -integer {5 3 1 2 11 4} +1 2 3 4 5 11 +% lsort -integer {1 2 0x5 7 0 4 -1} +-1 0 1 2 4 0x5 7 +.CE + +.PP +Sorting lists of floating-point numbers: +.CS +% lsort -real {5 3 1 2 11 4} +1 2 3 4 5 11 +% lsort -real {.5 0.07e1 0.4 6e-1} +0.4 .5 6e-1 0.07e1 +.CE + +.PP +Sorting using indices: +.CS +% # Note the space character before the c +% lsort {{a 5} { c 3} {b 4} {e 1} {d 2}} +{ c 3} {a 5} {b 4} {d 2} {e 1} +% lsort -index 0 {{a 5} { c 3} {b 4} {e 1} {d 2}} +{a 5} {b 4} { c 3} {d 2} {e 1} +% lsort -index 1 {{a 5} { c 3} {b 4} {e 1} {d 2}} +{e 1} {d 2} { c 3} {b 4} {a 5} +.CE + +.PP +Stripping duplicate values using sorting: +.CS +% lsort -unique {a b c a b c a b c} +a b c +.CE + +.PP +More complex sorting using a comparison function: +.CS +% proc compare {a b} { + set a0 [lindex $a 0] + set b0 [lindex $b 0] + if {$a0 < $b0} { + return -1 + } elseif {$a0 > $b0} { + return 1 + } + return [string compare [lindex $a 1] [lindex $b 1]] +} +% lsort -command compare \\ + {{3 apple} {0x2 carrot} {1 dingo} {2 banana}} +{1 dingo} {2 banana} {0x2 carrot} {3 apple} +.CE + +.SH "SEE ALSO" +lappend(n), lindex(n), linsert(n), list(n), llength(n), lrange(n), +lreplace(n), lsearch(n) + +.SH KEYWORDS +element, list, order, sort diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/man.macros b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/man.macros new file mode 100644 index 0000000000000000000000000000000000000000..4fd1b4b51dc750f7e5b70bc3166130e878b5de0a --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/man.macros @@ -0,0 +1,236 @@ +'\" The definitions below are for supplemental macros used in Tcl/Tk +'\" manual entries. +'\" +'\" .AP type name in/out ?indent? +'\" Start paragraph describing an argument to a library procedure. +'\" type is type of argument (int, etc.), in/out is either "in", "out", +'\" or "in/out" to describe whether procedure reads or modifies arg, +'\" and indent is equivalent to second arg of .IP (shouldn't ever be +'\" needed; use .AS below instead) +'\" +'\" .AS ?type? ?name? +'\" Give maximum sizes of arguments for setting tab stops. Type and +'\" name are examples of largest possible arguments that will be passed +'\" to .AP later. If args are omitted, default tab stops are used. +'\" +'\" .BS +'\" Start box enclosure. From here until next .BE, everything will be +'\" enclosed in one large box. +'\" +'\" .BE +'\" End of box enclosure. +'\" +'\" .CS +'\" Begin code excerpt. +'\" +'\" .CE +'\" End code excerpt. +'\" +'\" .VS ?version? ?br? +'\" Begin vertical sidebar, for use in marking newly-changed parts +'\" of man pages. The first argument is ignored and used for recording +'\" the version when the .VS was added, so that the sidebars can be +'\" found and removed when they reach a certain age. If another argument +'\" is present, then a line break is forced before starting the sidebar. +'\" +'\" .VE +'\" End of vertical sidebar. +'\" +'\" .DS +'\" Begin an indented unfilled display. +'\" +'\" .DE +'\" End of indented unfilled display. +'\" +'\" .SO +'\" Start of list of standard options for a Tk widget. The +'\" options follow on successive lines, in four columns separated +'\" by tabs. +'\" +'\" .SE +'\" End of list of standard options for a Tk widget. +'\" +'\" .OP cmdName dbName dbClass +'\" Start of description of a specific option. cmdName gives the +'\" option's name as specified in the class command, dbName gives +'\" the option's name in the option database, and dbClass gives +'\" the option's class in the option database. +'\" +'\" .UL arg1 arg2 +'\" Print arg1 underlined, then print arg2 normally. +'\" +'\" RCS: @(#) $Id: man.macros,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +'\" # Set up traps and other miscellaneous stuff for Tcl/Tk man pages. +.if t .wh -1.3i ^B +.nr ^l \n(.l +.ad b +'\" # Start an argument description +.de AP +.ie !"\\$4"" .TP \\$4 +.el \{\ +. ie !"\\$2"" .TP \\n()Cu +. el .TP 15 +.\} +.ta \\n()Au \\n()Bu +.ie !"\\$3"" \{\ +\&\\$1 \\fI\\$2\\fP (\\$3) +.\".b +.\} +.el \{\ +.br +.ie !"\\$2"" \{\ +\&\\$1 \\fI\\$2\\fP +.\} +.el \{\ +\&\\fI\\$1\\fP +.\} +.\} +.. +'\" # define tabbing values for .AP +.de AS +.nr )A 10n +.if !"\\$1"" .nr )A \\w'\\$1'u+3n +.nr )B \\n()Au+15n +.\" +.if !"\\$2"" .nr )B \\w'\\$2'u+\\n()Au+3n +.nr )C \\n()Bu+\\w'(in/out)'u+2n +.. +.AS Tcl_Interp Tcl_CreateInterp in/out +'\" # BS - start boxed text +'\" # ^y = starting y location +'\" # ^b = 1 +.de BS +.br +.mk ^y +.nr ^b 1u +.if n .nf +.if n .ti 0 +.if n \l'\\n(.lu\(ul' +.if n .fi +.. +'\" # BE - end boxed text (draw box now) +.de BE +.nf +.ti 0 +.mk ^t +.ie n \l'\\n(^lu\(ul' +.el \{\ +.\" Draw four-sided box normally, but don't draw top of +.\" box if the box started on an earlier page. +.ie !\\n(^b-1 \{\ +\h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul' +.\} +.el \}\ +\h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul' +.\} +.\} +.fi +.br +.nr ^b 0 +.. +'\" # VS - start vertical sidebar +'\" # ^Y = starting y location +'\" # ^v = 1 (for troff; for nroff this doesn't matter) +.de VS +.if !"\\$2"" .br +.mk ^Y +.ie n 'mc \s12\(br\s0 +.el .nr ^v 1u +.. +'\" # VE - end of vertical sidebar +.de VE +.ie n 'mc +.el \{\ +.ev 2 +.nf +.ti 0 +.mk ^t +\h'|\\n(^lu+3n'\L'|\\n(^Yu-1v\(bv'\v'\\n(^tu+1v-\\n(^Yu'\h'-|\\n(^lu+3n' +.sp -1 +.fi +.ev +.\} +.nr ^v 0 +.. +'\" # Special macro to handle page bottom: finish off current +'\" # box/sidebar if in box/sidebar mode, then invoked standard +'\" # page bottom macro. +.de ^B +.ev 2 +'ti 0 +'nf +.mk ^t +.if \\n(^b \{\ +.\" Draw three-sided box if this is the box's first page, +.\" draw two sides but no top otherwise. +.ie !\\n(^b-1 \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c +.el \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c +.\} +.if \\n(^v \{\ +.nr ^x \\n(^tu+1v-\\n(^Yu +\kx\h'-\\nxu'\h'|\\n(^lu+3n'\ky\L'-\\n(^xu'\v'\\n(^xu'\h'|0u'\c +.\} +.bp +'fi +.ev +.if \\n(^b \{\ +.mk ^y +.nr ^b 2 +.\} +.if \\n(^v \{\ +.mk ^Y +.\} +.. +'\" # DS - begin display +.de DS +.RS +.nf +.sp +.. +'\" # DE - end display +.de DE +.fi +.RE +.sp +.. +'\" # SO - start of list of standard options +.de SO +.SH "STANDARD OPTIONS" +.LP +.nf +.ta 5.5c 11c +.ft B +.. +'\" # SE - end of list of standard options +.de SE +.fi +.ft R +.LP +See the \\fBoptions\\fR manual entry for details on the standard options. +.. +'\" # OP - start of full description for a single option +.de OP +.LP +.nf +.ta 4c +Command-Line Name: \\fB\\$1\\fR +Database Name: \\fB\\$2\\fR +Database Class: \\fB\\$3\\fR +.fi +.IP +.. +'\" # CS - begin code excerpt +.de CS +.RS +.nf +.ta .25i .5i .75i 1i +.. +'\" # CE - end code excerpt +.de CE +.fi +.RE +.. +.de UL +\\$1\l'|0\(ul'\\$2 +.. diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/memory.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/memory.n new file mode 100644 index 0000000000000000000000000000000000000000..e815bb6ce848ff08f489b4c6006d54d870919e90 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/memory.n @@ -0,0 +1,80 @@ +'\" +'\" Copyright (c) 1992-1999 by Karl Lehenbauer and Mark Diekhans +'\" Copyright (c) 2000 by Scriptics Corporation. +'\" All rights reserved. +'\" +'\" RCS: @(#) $Id: memory.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH memory n 8.1 Tcl "Tcl Built-In Commands" +.BS +.SH NAME +memory \- Control Tcl memory debugging capabilities. +.SH SYNOPSIS +\fBmemory \fIoption \fR?\fIarg arg ...\fR? + +.SH DESCRIPTION +.PP +The \fBmemory\fR command gives the Tcl developer control of Tcl's memory +debugging capabilities. The memory command has several suboptions, which are +described below. It is only available when Tcl has been compiled with +memory debugging enabled (when \fBTCL_MEM_DEBUG\fR is defined at +compile time). +.TP +\fBmemory info\fR +Produces a report containing the total allocations and frees since +Tcl began, the current packets allocated (the current +number of calls to \fBckalloc\fR not met by a corresponding call +to \fBckfree\fR), the current bytes allocated, and the maximum number +of packets and bytes allocated. +.TP +\fBmemory trace [on|off]\fR +.br +Turns memory tracing on or off. When memory tracing is on, every call +to \fBckalloc\fR causes a line of trace information to be written to +\fIstderr\fR, consisting of the word \fIckalloc\fR, followed by the +address returned, the amount of memory allocated, and the C filename +and line number of the code performing the allocation. For example: +.CS +ckalloc 40e478 98 tclProc.c 1406 +.CE +Calls to \fBckfree\fR are traced in the same manner. +.TP +\fBmemory validate [on|off]\fR +Turns memory validation on or off. When memory validation is enabled, +on every call to \fBckalloc\fR or \fBckfree\fR, the guard zones are +checked for every piece of memory currently in existence that was +allocated by \fBckalloc\fR. This has a large performance impact and +should only be used when overwrite problems are strongly suspected. +The advantage of enabling memory validation is that a guard zone +overwrite can be detected on the first call to \fBckalloc\fR or +\fBckfree\fR after the overwrite occurred, rather than when the +specific memory with the overwritten guard zone(s) is freed, which may +occur long after the overwrite occurred. +.TP +\fBmemory trace_on_at_malloc\fR \fIcount\fR +Enable memory tracing after \fIcount\fR \fBckalloc\fR's have been performed. +For example, if you enter \fBmemory trace_on_at_malloc 100\fR, +after the 100th call to \fBckalloc\fR, memory trace information will begin +being displayed for all allocations and frees. Since there can be a lot +of memory activity before a problem occurs, judicious use of this option +can reduce the slowdown caused by tracing (and the amount of trace information +produced), if you can identify a number of allocations that occur before +the problem sets in. The current number of memory allocations that have +occurred since Tcl started is printed on a guard zone failure. +.TP +\fBmemory break_on_malloc\fR \fIcount\fR +After the \fBcount\fR allocations have been performed, \fBckalloc\fR's +output a message to this effect and that it is now attempting to enter +the C debugger. Tcl will then issue a \fISIGINT\fR signal against itself. +If you are running Tcl under a C debugger, it should then enter the debugger +command mode. +.TP +\fB memory display\fR \fIfile\fR +Write a list of all currently allocated memory to the specified file. + +.SH "SEE ALSO" +ckalloc, ckfree, Tcl_ValidateAllMemory, Tcl_DumpActiveMemory, TCL_MEM_DEBUG + +.SH KEYWORDS +memory, debug diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/msgcat.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/msgcat.n new file mode 100644 index 0000000000000000000000000000000000000000..37c2a76fcd5bd8f929d2e35662920be016e03de4 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/msgcat.n @@ -0,0 +1,244 @@ +'\" +'\" Copyright (c) 1998 Mark Harrison. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" SCCS: @(#) msgcat.n +'\" +.so man.macros +.TH "msgcat" n 8.1 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +msgcat \- Tcl message catalog +.SH SYNOPSIS +\fB::msgcat::mc \fIsrc-string\fR +.sp +\fB::msgcat::mclocale \fR?\fInewLocale\fR? +.sp +\fB::msgcat::mcpreferences\fR +.sp +\fB::msgcat::mcload \fIdirname\fR +.sp +\fB::msgcat::mcset \fIlocale src-string \fR?\fItranslate-string\fR? +.sp +\fB::msgcat::mcunknown \fIlocale src-string\fR +.BE + +.SH DESCRIPTION +.PP +The \fBmsgcat\fR package provides a set of functions +that can be used to manage multi-lingual user interfaces. +Text strings are defined in a ``message catalog'' which +is independent from the application, and +which can be edited or localized without modifying +the application source code. New languages +or locales are provided by adding a new file to +the message catalog. +.PP +Use of the message catalog is optional by any application +or package, but is encouraged if the application or package +wishes to be enabled for multi-lingual applications. + +.SH COMMANDS +.TP +\fB::msgcat::mc \fIsrc-string\fR ?\fIarg arg ...\fR? +Returns a translation of \fIsrc-string\fR according to the +user's current locale. If additional arguments past \fIsrc-string\fR +are given, the \fBformat\fR command is used to substitute the +additional arguments in the translation of \fIsrc-string\fR. + +\fB::msgcat::mc\fR will search the messages defined +in the current namespace for a translation of \fIsrc-string\fR; if +none is found, it will search in the parent of the current namespace, +and so on until it reaches the global namespace. If no translation +string exists, \fB::msgcat::mcunknown\fR is called and the string +returned from \fB::msgcat::mcunknown\fR is returned. +.PP +\fB::msgcat::mc\fR is the main function used to localize an +application. Instead of using an English string directly, an +applicaton can pass the English string through \fB::msgcat::mc\fR and +use the result. If an application is written for a single language in +this fashion, then it is easy to add support for additional languages +later simply by defining new message catalog entries. +.TP +\fB::msgcat::mclocale \fR?\fInewLocale\fR? +This function sets the locale to \fInewLocale\fR. If \fInewLocale\fR +is omitted, the current locale is returned, otherwise the current locale +is set to \fInewLocale\fR. +The initial locale defaults to the locale specified in +the user's environment. See \fBLOCALE AND SUBLOCALE SPECIFICATION\fR +below for a description of the locale string format. +.TP +\fB::msgcat::mcpreferences\fR +Returns an ordered list of the locales preferred by +the user, based on the user's language specification. +The list is ordered from most specific to least +preference. If the user has specified LANG=en_US_funky, +this procedure would return {en_US_funky en_US en}. +.TP +\fB::msgcat::mcload \fIdirname\fR +Searches the specified directory for files that match +the language specifications returned by \fB::msgcat::mcpreferences\fR. +Each file located is sourced. The file extension is ``.msg''. +The number of message files which matched the specification +and were loaded is returned. +.TP +\fB::msgcat::mcset \fIlocale src-string \fR?\fItranslate-string\fR? +Sets the translation for \fIsrc-string\fR to \fItranslate-string\fR +in the specified \fIlocale\fR. If \fItranslate-string\fR is not +specified, \fIsrc-string\fR is used for both. The function +returns \fItranslate-string\fR. +.TP +\fB::msgcat::mcunknown \fIlocale src-string\fR +This routine is called by \fB::msgcat::mc\fR in the case when +a translation for \fIsrc-string\fR is not defined in the +current locale. The default action is to return +\fIsrc-string\fR. This procedure can be redefined by the +application, for example to log error messages for each unknown +string. The \fB::msgcat::mcunknown\fR procedure is invoked at the +same stack context as the call to \fB::msgcat::mc\fR. The return vaue +of \fB::msgcat::mcunknown\fR is used as the return vaue for the call +to \fB::msgcat::mc\fR. + +.SH "LOCALE AND SUBLOCALE SPECIFICATION" +.PP +The locale is specified by a locale string. +The locale string consists of +a language code, an optional country code, and an optional +system-specific code, each separated by ``_''. The country and language +codes are specified in standards ISO-639 and ISO-3166. +For example, the locale ``en'' specifies English and + ``en_US'' specifes U.S. English. +.PP +The locale defaults to the value in \fBenv(LANG)\fR at the time the +\fBmsgcat\fR package is loaded. If \fBenv(LANG)\fR is not defined, then the +locale defaults to ``C''. +.PP +When a locale is specified by the user, a ``best match'' search is +performed during string translation. For example, if a user specifies +en_UK_Funky, the locales ``en_UK_Funky'', ``en_UK'', and ``en'' are +searched in order until a matching translation string is found. If no +translation string is available, then \fB::msgcat::unknown\fR is +called. + +.SH "NAMESPACES AND MESSAGE CATALOGS" +.PP +Strings stored in the message catalog are stored relative +to the namespace from which they were added. This allows +multiple packages to use the same strings without fear +of collisions with other packages. It also allows the +source string to be shorter and less prone to typographical +error. +.PP +For example, executing the code +.CS +mcset en hello "hello from ::" +namespace eval foo {mcset en hello "hello from ::foo"} +puts [mc hello] +namespace eval foo {puts [mc hello]} +.CE +will print +.CS +hello from :: +hello from ::foo +.CE +.PP +When searching for a translation of a message, the +message catalog will search first the current namespace, +then the parent of the current namespace, and so on until +the global namespace is reached. This allows child namespaces +to "inherit" messages from their parent namespace. +.PP +For example, executing the code +.CS +mcset en m1 ":: message1" +mcset en m2 ":: message2" +mcset en m3 ":: message3" +namespace eval ::foo { + mcset en m2 "::foo message2" + mcset en m3 "::foo message3" +} +namespace eval ::foo::bar { + mcset en m3 "::foo::bar message3" +} +puts "[mc m1]; [mc m2]; [mc m3]" +namespace eval ::foo {puts "[mc m1]; [mc m2]; [mc m3]"} +namespace eval ::foo::bar {puts "[mc m1]; [mc m2]; [mc m3]"} +.CE +will print +.CS +:: message1; :: message2; :: message3 +:: message1; ::foo message2; ::foo message3 +:: message1; ::foo message2; ::foo::bar message3 +.CE + +.SH "LOCATION AND FORMAT OF MESSAGE FILES" +.PP +Message files can be located in any directory, subject +to the following conditions: +.IP [1] +All message files for a package are in the same directory. +.IP [2] +The message file name is a locale specifier followed +by ``.msg''. For example: +.CS +es.msg -- spanish +en_UK.msg -- UK English +.CE +.IP [3] +The file contains a series of calls to mcset, setting the +necessary translation strings for the language. For example: +.CS +::msgcat::mcset es "Free Beer!" "Cerveza Gracias!" +.CE + +.SH "RECOMMENDED MESSAGE SETUP FOR PACKAGES" +.PP +If a package is installed into a subdirectory of the +\fBtcl_pkgPath\fR and loaded via \fBpackage require\fR, the +following procedure is recommended. +.IP [1] +During package installation, create a subdirectory +\fBmsgs\fR under your package directory. +.IP [2] +Copy your *.msg files into that directory. +.IP [3] + Add the following command to your package +initialization script: +.CS +# load language files, stored in msgs subdirectory +::msgcat::mcload [file join [file dirname [info script]] msgs] +.CE + +.SH "POSTITIONAL CODES FOR FORMAT AND SCAN COMMANDS" +.PP +It is possible that a message string used as an argument +to \fBformat\fR might have positionally dependent parameters that +might need to be repositioned. For example, it might be +syntactically desirable to rearrange the sentence structure +while translating. +.CS +format "We produced %d units in location %s" $num $city +format "In location %s we produced %d units" $city $num +.CE +.PP +This can be handled by using the positional +parameters: +.CS +format "We produced %1\\$d units in location %2\\$s" $num $city +format "In location %2\\$s we produced %1\\$d units" $num $city +.CE +.PP +Similarly, positional parameters can be used with \fBscan\fR to +extract values from internationalized strings. + +.SH CREDITS +.PP +The message catalog code was developed by Mark Harrison. + +.SH "SEE ALSO" +format(n), scan(n), namespace(n), package(n) +.SH KEYWORDS +internationalization, i18n, localization, l10n, message, text, translation diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/namespace.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/namespace.n new file mode 100644 index 0000000000000000000000000000000000000000..bb749d22eca768c0087e51e384f2b7fec8491303 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/namespace.n @@ -0,0 +1,566 @@ +'\" +'\" Copyright (c) 1993-1997 Bell Labs Innovations for Lucent Technologies +'\" Copyright (c) 1997 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: namespace.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH namespace n 8.0 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +namespace \- create and manipulate contexts for commands and variables +.SH SYNOPSIS +\fBnamespace \fR?\fIoption\fR? ?\fIarg ...\fR? +.BE + +.SH DESCRIPTION +.PP +The \fBnamespace\fR command lets you create, access, and destroy +separate contexts for commands and variables. +See the section \fBWHAT IS A NAMESPACE?\fR below +for a brief overview of namespaces. +The legal \fIoption\fR's are listed below. +Note that you can abbreviate the \fIoption\fR's. +.TP +\fBnamespace children \fR?\fInamespace\fR? ?\fIpattern\fR? +Returns a list of all child namespaces that belong to the +namespace \fInamespace\fR. +If \fInamespace\fR is not specified, +then the children are returned for the current namespace. +This command returns fully-qualified names, +which start with \fB::\fR. +If the optional \fIpattern\fR is given, +then this command returns only the names that match the glob-style pattern. +The actual pattern used is determined as follows: +a pattern that starts with \fB::\fR is used directly, +otherwise the namespace \fInamespace\fR +(or the fully-qualified name of the current namespace) +is prepended onto the the pattern. +.TP +\fBnamespace code \fIscript\fR +Captures the current namespace context for later execution +of the script \fIscript\fR. +It returns a new script in which \fIscript\fR has been wrapped +in a \fBnamespace code\fR command. +The new script has two important properties. +First, it can be evaluated in any namespace and will cause +\fIscript\fR to be evaluated in the current namespace +(the one where the \fBnamespace code\fR command was invoked). +Second, additional arguments can be appended to the resulting script +and they will be passed to \fIscript\fR as additional arguments. +For example, suppose the command +\fBset script [namespace code {foo bar}]\fR +is invoked in namespace \fB::a::b\fR. +Then \fBeval "$script x y"\fR +can be executed in any namespace (assuming the value of +\fBscript\fR has been passed in properly) +and will have the same effect as the command +\fBnamespace eval ::a::b {foo bar x y}\fR. +This command is needed because +extensions like Tk normally execute callback scripts +in the global namespace. +A scoped command captures a command together with its namespace context +in a way that allows it to be executed properly later. +See the section \fBSCOPED VALUES\fR for some examples +of how this is used to create callback scripts. +.TP +\fBnamespace current\fR +Returns the fully-qualified name for the current namespace. +The actual name of the global namespace is ``'' +(i.e., an empty string), +but this command returns \fB::\fR for the global namespace +as a convenience to programmers. +.TP +\fBnamespace delete \fR?\fInamespace namespace ...\fR? +Each namespace \fInamespace\fR is deleted +and all variables, procedures, and child namespaces +contained in the namespace are deleted. +If a procedure is currently executing inside the namespace, +the namespace will be kept alive until the procedure returns; +however, the namespace is marked to prevent other code from +looking it up by name. +If a namespace doesn't exist, this command returns an error. +If no namespace names are given, this command does nothing. +.TP +\fBnamespace eval\fR \fInamespace arg\fR ?\fIarg ...\fR? +Activates a namespace called \fInamespace\fR and evaluates some code +in that context. +If the namespace does not already exist, it is created. +If more than one \fIarg\fR argument is specified, +the arguments are concatenated together with a space between each one +in the same fashion as the \fBeval\fR command, +and the result is evaluated. +.br +.sp +If \fInamespace\fR has leading namespace qualifiers +and any leading namespaces do not exist, +they are automatically created. +.TP +\fBnamespace export \fR?\-\fBclear\fR? ?\fIpattern pattern ...\fR? +Specifies which commands are exported from a namespace. +The exported commands are those that can be later imported +into another namespace using a \fBnamespace import\fR command. +Both commands defined in a namespace and +commands the namespace has previously imported +can be exported by a namespace. +The commands do not have to be defined +at the time the \fBnamespace export\fR command is executed. +Each \fIpattern\fR may contain glob-style special characters, +but it may not include any namespace qualifiers. +That is, the pattern can only specify commands +in the current (exporting) namespace. +Each \fIpattern\fR is appended onto the namespace's list of export patterns. +If the \-\fBclear\fR flag is given, +the namespace's export pattern list is reset to empty before any +\fIpattern\fR arguments are appended. +If no \fIpattern\fRs are given and the \-\fBclear\fR flag isn't given, +this command returns the namespace's current export list. +.TP +\fBnamespace forget \fR?\fIpattern pattern ...\fR? +Removes previously imported commands from a namespace. +Each \fIpattern\fR is a qualified name such as +\fBfoo::x\fR or \fBa::b::p*\fR. +Qualified names contain \fB::\fRs and qualify a name +with the name of one or more namespaces. +Each \fIpattern\fR is qualified with the name of an exporting namespace +and may have glob-style special characters in the command name +at the end of the qualified name. +Glob characters may not appear in a namespace name. +This command first finds the matching exported commands. +It then checks whether any of those those commands +were previously imported by the current namespace. +If so, this command deletes the corresponding imported commands. +In effect, this un-does the action of a \fBnamespace import\fR command. +.TP +\fBnamespace import \fR?\fB\-force\fR? ?\fIpattern\fR \fIpattern ...\fR? +Imports commands into a namespace. +Each \fIpattern\fR is a qualified name like +\fBfoo::x\fR or \fBa::p*\fR. +That is, it includes the name of an exporting namespace +and may have glob-style special characters in the command name +at the end of the qualified name. +Glob characters may not appear in a namespace name. +All the commands that match a \fIpattern\fR string +and which are currently exported from their namespace +are added to the current namespace. +This is done by creating a new command in the current namespace +that points to the exported command in its original namespace; +when the new imported command is called, it invokes the exported command. +This command normally returns an error +if an imported command conflicts with an existing command. +However, if the \-\fBforce\fR option is given, +imported commands will silently replace existing commands. +The \fBnamespace import\fR command has snapshot semantics: +that is, only requested commands that are currently defined +in the exporting namespace are imported. +In other words, you can import only the commands that are in a namespace +at the time when the \fBnamespace import\fR command is executed. +If another command is defined and exported in this namespace later on, +it will not be imported. +.TP +\fBnamespace inscope\fR \fInamespace arg\fR ?\fIarg ...\fR? +Executes a script in the context of a particular namespace. +This command is not expected to be used directly by programmers; +calls to it are generated implicitly when applications +use \fBnamespace code\fR commands to create callback scripts +that the applications then register with, e.g., Tk widgets. +The \fBnamespace inscope\fR command is much like the \fBnamespace eval\fR +command except that it has \fBlappend\fR semantics +and the namespace must already exist. +It treats the first argument as a list, +and appends any arguments after the first +onto the end as proper list elements. +\fBnamespace inscope ::foo a x y z\fR +is equivalent to +\fBnamespace eval ::foo [concat a [list x y z]]\fR +This \fBlappend\fR semantics is important because many callback scripts +are actually prefixes. +.TP +\fBnamespace origin \fIcommand\fR +Returns the fully-qualified name of the original command +to which the imported command \fIcommand\fR refers. +When a command is imported into a namespace, +a new command is created in that namespace +that points to the actual command in the exporting namespace. +If a command is imported into a sequence of namespaces +\fIa, b,...,n\fR where each successive namespace +just imports the command from the previous namespace, +this command returns the fully-qualified name of the original command +in the first namespace, \fIa\fR. +If \fIcommand\fR does not refer to an imported command, +the command's own fully-qualified name is returned. +.TP +\fBnamespace parent\fR ?\fInamespace\fR? +Returns the fully-qualified name of the parent namespace +for namespace \fInamespace\fR. +If \fInamespace\fR is not specified, +the fully-qualified name of the current namespace's parent is returned. +.TP +\fBnamespace qualifiers\fR \fIstring\fR +Returns any leading namespace qualifiers for \fIstring\fR. +Qualifiers are namespace names separated by \fB::\fRs. +For the \fIstring\fR \fB::foo::bar::x\fR, +this command returns \fB::foo::bar\fR, +and for \fB::\fR it returns an empty string. +This command is the complement of the \fBnamespace tail\fR command. +Note that it does not check whether the +namespace names are, in fact, +the names of currently defined namespaces. +.TP +\fBnamespace tail\fR \fIstring\fR +Returns the simple name at the end of a qualified string. +Qualifiers are namespace names separated by \fB::\fRs. +For the \fIstring\fR \fB::foo::bar::x\fR, +this command returns \fBx\fR, +and for \fB::\fR it returns an empty string. +This command is the complement of the \fBnamespace qualifiers\fR command. +It does not check whether the namespace names are, in fact, +the names of currently defined namespaces. +.TP +\fBnamespace which\fR ?\-\fBcommand\fR? ?\-\fBvariable\fR? \fIname\fR +Looks up \fIname\fR as either a command or variable +and returns its fully-qualified name. +For example, if \fIname\fR does not exist in the current namespace +but does exist in the global namespace, +this command returns a fully-qualified name in the global namespace. +If the command or variable does not exist, +this command returns an empty string. If the variable has been +created but not defined, such as with the \fBvariable\fR command +or through a \fBtrace\fR on the variable, this command will return the +fully-qualified name of the variable. +If no flag is given, \fIname\fR is treated as a command name. +See the section \fBNAME RESOLUTION\fR below for an explanation of +the rules regarding name resolution. + +.SH "WHAT IS A NAMESPACE?" +.PP +A namespace is a collection of commands and variables. +It encapsulates the commands and variables to ensure that they +won't interfere with the commands and variables of other namespaces. +Tcl has always had one such collection, +which we refer to as the \fIglobal namespace\fR. +The global namespace holds all global variables and commands. +The \fBnamespace eval\fR command lets you create new namespaces. +For example, +.CS +\fBnamespace eval Counter { + namespace export bump + variable num 0 + + proc bump {} { + variable num + incr num + } +}\fR +.CE +creates a new namespace containing the variable \fBnum\fR and +the procedure \fBbump\fR. +The commands and variables in this namespace are separate from +other commands and variables in the same program. +If there is a command named \fBbump\fR in the global namespace, +for example, it will be different from the command \fBbump\fR +in the \fBCounter\fR namespace. +.PP +Namespace variables resemble global variables in Tcl. +They exist outside of the procedures in a namespace +but can be accessed in a procedure via the \fBvariable\fR command, +as shown in the example above. +.PP +Namespaces are dynamic. +You can add and delete commands and variables at any time, +so you can build up the contents of a +namespace over time using a series of \fBnamespace eval\fR commands. +For example, the following series of commands has the same effect +as the namespace definition shown above: +.CS +\fBnamespace eval Counter { + variable num 0 + proc bump {} { + variable num + return [incr num] + } +} +namespace eval Counter { + proc test {args} { + return $args + } +} +namespace eval Counter { + rename test "" +}\fR +.CE +Note that the \fBtest\fR procedure is added to the \fBCounter\fR namespace, +and later removed via the \fBrename\fR command. +.PP +Namespaces can have other namespaces within them, +so they nest hierarchically. +A nested namespace is encapsulated inside its parent namespace +and can not interfere with other namespaces. + +.SH "QUALIFIED NAMES" +.PP +Each namespace has a textual name such as +\fBhistory\fR or \fB::safe::interp\fR. +Since namespaces may nest, +qualified names are used to refer to +commands, variables, and child namespaces contained inside namespaces. +Qualified names are similar to the hierarchical path names for +Unix files or Tk widgets, +except that \fB::\fR is used as the separator +instead of \fB/\fR or \fB.\fR. +The topmost or global namespace has the name ``'' (i.e., an empty string), +although \fB::\fR is a synonym. +As an example, the name \fB::safe::interp::create\fR +refers to the command \fBcreate\fR in the namespace \fBinterp\fR +that is a child of of namespace \fB::safe\fR, +which in turn is a child of the global namespace \fB::\fR. +.PP +If you want to access commands and variables from another namespace, +you must use some extra syntax. +Names must be qualified by the namespace that contains them. +From the global namespace, +we might access the \fBCounter\fR procedures like this: +.CS +\fBCounter::bump 5 +Counter::Reset\fR +.CE +We could access the current count like this: +.CS +\fBputs "count = $Counter::num"\fR +.CE +When one namespace contains another, you may need more than one +qualifier to reach its elements. +If we had a namespace \fBFoo\fR that contained the namespace \fBCounter\fR, +you could invoke its \fBbump\fR procedure +from the global namespace like this: +.CS +\fBFoo::Counter::bump 3\fR +.CE +.PP +You can also use qualified names when you create and rename commands. +For example, you could add a procedure to the \fBFoo\fR +namespace like this: +.CS +\fBproc Foo::Test {args} {return $args}\fR +.CE +And you could move the same procedure to another namespace like this: +.CS +\fBrename Foo::Test Bar::Test\fR +.CE +.PP +There are a few remaining points about qualified names +that we should cover. +Namespaces have nonempty names except for the global namespace. +\fB::\fR is disallowed in simple command, variable, and namespace names +except as a namespace separator. +Extra \fB:\fRs in a qualified name are ignored; +that is, two or more \fB:\fRs are treated as a namespace separator. +A trailing \fB::\fR in a qualified variable or command name +refers to the variable or command named {}. +However, a trailing \fB::\fR in a qualified namespace name is ignored. + +.SH "NAME RESOLUTION" +.PP +In general, all Tcl commands that take variable and command names +support qualified names. +This means you can give qualified names to such commands as +\fBset\fR, \fBproc\fR, \fBrename\fR, and \fBinterp alias\fR. +If you provide a fully-qualified name that starts with a \fB::\fR, +there is no question about what command, variable, or namespace +you mean. +However, if the name does not start with a \fB::\fR +(i.e., is \fIrelative\fR), +Tcl follows a fixed rule for looking it up: +Command and variable names are always resolved +by looking first in the current namespace, +and then in the global namespace. +Namespace names, on the other hand, are always resolved +by looking in only the current namespace. +.PP +In the following example, +.CS +\fBset traceLevel 0 +namespace eval Debug { + printTrace $traceLevel +}\fR +.CE +Tcl looks for \fBtraceLevel\fR in the namespace \fBDebug\fR +and then in the global namespace. +It looks up the command \fBprintTrace\fR in the same way. +If a variable or command name is not found in either context, +the name is undefined. +To make this point absolutely clear, consider the following example: +.CS +\fBset traceLevel 0 +namespace eval Foo { + variable traceLevel 3 + + namespace eval Debug { + printTrace $traceLevel + } +}\fR +.CE +Here Tcl looks for \fBtraceLevel\fR first in the namespace \fBFoo::Debug\fR. +Since it is not found there, Tcl then looks for it +in the global namespace. +The variable \fBFoo::traceLevel\fR is completely ignored +during the name resolution process. +.PP +You can use the \fBnamespace which\fR command to clear up any question +about name resolution. +For example, the command: +.CS +\fBnamespace eval Foo::Debug {namespace which \-variable traceLevel}\fR +.CE +returns \fB::traceLevel\fR. +On the other hand, the command, +.CS +\fBnamespace eval Foo {namespace which \-variable traceLevel}\fR +.CE +returns \fB::Foo::traceLevel\fR. +.PP +As mentioned above, +namespace names are looked up differently +than the names of variables and commands. +Namespace names are always resolved in the current namespace. +This means, for example, +that a \fBnamespace eval\fR command that creates a new namespace +always creates a child of the current namespace +unless the new namespace name begins with a \fB::\fR. +.PP +Tcl has no access control to limit what variables, commands, +or namespaces you can reference. +If you provide a qualified name that resolves to an element +by the name resolution rule above, +you can access the element. +.PP +You can access a namespace variable +from a procedure in the same namespace +by using the \fBvariable\fR command. +Much like the \fBglobal\fR command, +this creates a local link to the namespace variable. +If necessary, it also creates the variable in the current namespace +and initializes it. +Note that the \fBglobal\fR command only creates links +to variables in the global namespace. +It is not necessary to use a \fBvariable\fR command +if you always refer to the namespace variable using an +appropriate qualified name. + +.SH "IMPORTING COMMANDS" +.PP +Namespaces are often used to represent libraries. +Some library commands are used so frequently +that it is a nuisance to type their qualified names. +For example, suppose that all of the commands in a package +like BLT are contained in a namespace called \fBBlt\fR. +Then you might access these commands like this: +.CS +\fBBlt::graph .g \-background red +Blt::table . .g 0,0\fR +.CE +If you use the \fBgraph\fR and \fBtable\fR commands frequently, +you may want to access them without the \fBBlt::\fR prefix. +You can do this by importing the commands into the current namespace, +like this: +.CS +\fBnamespace import Blt::*\fR +.CE +This adds all exported commands from the \fBBlt\fR namespace +into the current namespace context, so you can write code like this: +.CS +\fBgraph .g \-background red +table . .g 0,0\fR +.CE +The \fBnamespace import\fR command only imports commands +from a namespace that that namespace exported +with a \fBnamespace export\fR command. +.PP +Importing \fIevery\fR command from a namespace is generally +a bad idea since you don't know what you will get. +It is better to import just the specific commands you need. +For example, the command +.CS +\fBnamespace import Blt::graph Blt::table\fR +.CE +imports only the \fBgraph\fR and \fBtable\fR commands into the +current context. +.PP +If you try to import a command that already exists, you will get an +error. This prevents you from importing the same command from two +different packages. But from time to time (perhaps when debugging), +you may want to get around this restriction. You may want to +reissue the \fBnamespace import\fR command to pick up new commands +that have appeared in a namespace. In that case, you can use the +\fB\-force\fR option, and existing commands will be silently overwritten: +.CS +\fBnamespace import \-force Blt::graph Blt::table\fR +.CE +If for some reason, you want to stop using the imported commands, +you can remove them with an \fBnamespace forget\fR command, like this: +.CS +\fBnamespace forget Blt::*\fR +.CE +This searches the current namespace for any commands imported from \fBBlt\fR. +If it finds any, it removes them. Otherwise, it does nothing. +After this, the \fBBlt\fR commands must be accessed with the \fBBlt::\fR +prefix. +.PP +When you delete a command from the exporting namespace like this: +.CS +\fBrename Blt::graph ""\fR +.CE +the command is automatically removed from all namespaces that import it. + +.SH "EXPORTING COMMANDS" +You can export commands from a namespace like this: +.CS +\fBnamespace eval Counter { + namespace export bump reset + variable Num 0 + variable Max 100 + + proc bump {{by 1}} { + variable Num + incr Num $by + Check + return $Num + } + proc reset {} { + variable Num + set Num 0 + } + proc Check {} { + variable Num + variable Max + if {$Num > $Max} { + error "too high!" + } + } +}\fR +.CE +The procedures \fBbump\fR and \fBreset\fR are exported, +so they are included when you import from the \fBCounter\fR namespace, +like this: +.CS +\fBnamespace import Counter::*\fR +.CE +However, the \fBCheck\fR procedure is not exported, +so it is ignored by the import operation. +.PP +The \fBnamespace import\fR command only imports commands +that were declared as exported by their namespace. +The \fBnamespace export\fR command specifies what commands +may be imported by other namespaces. +If a \fBnamespace import\fR command specifies a command +that is not exported, the command is not imported. + +.SH "SEE ALSO" +variable(n) + +.SH KEYWORDS +exported, internal, variable diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/open.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/open.n new file mode 100644 index 0000000000000000000000000000000000000000..b54729c23def0f65596b306eb688fe1d495ca962 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/open.n @@ -0,0 +1,273 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: open.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH open n 7.6 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +open \- Open a file-based or command pipeline channel +.SH SYNOPSIS +.sp +\fBopen \fIfileName\fR +.br +\fBopen \fIfileName access\fR +.br +\fBopen \fIfileName access permissions\fR +.BE + +.SH DESCRIPTION +.PP +.VS +This command opens a file, serial port, or command pipeline and returns a +.VE +channel identifier that may be used in future invocations of commands like +\fBread\fR, \fBputs\fR, and \fBclose\fR. +If the first character of \fIfileName\fR is not \fB|\fR then +the command opens a file: +\fIfileName\fR gives the name of the file to open, and it must conform to the +conventions described in the \fBfilename\fR manual entry. +.PP +The \fIaccess\fR argument, if present, indicates the way in which the file +(or command pipeline) is to be accessed. +In the first form \fIaccess\fR may have any of the following values: +.TP 15 +\fBr\fR +Open the file for reading only; the file must already exist. This is the +default value if \fIaccess\fR is not specified. +.TP 15 +\fBr+\fR +Open the file for both reading and writing; the file must +already exist. +.TP 15 +\fBw\fR +Open the file for writing only. Truncate it if it exists. If it doesn't +exist, create a new file. +.TP 15 +\fBw+\fR +Open the file for reading and writing. Truncate it if it exists. +If it doesn't exist, create a new file. +.TP 15 +\fBa\fR +Open the file for writing only. If the file doesn't exist, +create a new empty file. +Set the initial access position to the end of the file. +.TP 15 +\fBa+\fR +Open the file for reading and writing. If the file doesn't exist, +create a new empty file. +Set the initial access position to the end of the file. +.PP +In the second form, \fIaccess\fR consists of a list of any of the +following flags, all of which have the standard POSIX meanings. +One of the flags must be either \fBRDONLY\fR, \fBWRONLY\fR or \fBRDWR\fR. +.TP 15 +\fBRDONLY\fR +Open the file for reading only. +.TP 15 +\fBWRONLY\fR +Open the file for writing only. +.TP 15 +\fBRDWR\fR +Open the file for both reading and writing. +.TP 15 +\fBAPPEND\fR +Set the file pointer to the end of the file prior to each write. +.TP 15 +\fBCREAT\fR +Create the file if it doesn't already exist (without this flag it +is an error for the file not to exist). +.TP 15 +\fBEXCL\fR +If \fBCREAT\fR is also specified, an error is returned if the +file already exists. +.TP 15 +\fBNOCTTY\fR +If the file is a terminal device, this flag prevents the file from +becoming the controlling terminal of the process. +.TP 15 +\fBNONBLOCK\fR +Prevents the process from blocking while opening the file, and +possibly in subsequent I/O operations. The exact behavior of +this flag is system- and device-dependent; its use is discouraged +(it is better to use the \fBfconfigure\fR command to put a file +in nonblocking mode). +For details refer to your system documentation on the \fBopen\fR system +call's \fBO_NONBLOCK\fR flag. +.TP 15 +\fBTRUNC\fR +If the file exists it is truncated to zero length. +.PP +If a new file is created as part of opening it, \fIpermissions\fR +(an integer) is used to set the permissions for the new file in +conjunction with the process's file mode creation mask. +\fIPermissions\fR defaults to 0666. +.PP +'\" Not versioned as advice applies to all recent versions of Tcl. +'\" Prior to that, Tcl didn't really support binary files anyway... +.VS +Note that if you are going to be reading or writing binary data from +the channel created by this command, you should use the +\fBfconfigure\fR command to change the \fB-translation\fR option of +the channel to \fBbinary\fR before transferring any binary data. This +is in contrast to the ``b'' character passed as part of the equivalent +of the \fIaccess\fR parameter to some versions of the C library +\fIfopen()\fR function. +.VE +.SH "COMMAND PIPELINES" +.PP +If the first character of \fIfileName\fR is ``|'' then the +remaining characters of \fIfileName\fR are treated as a list of arguments +that describe a command pipeline to invoke, in the same style as the +arguments for \fBexec\fR. +In this case, the channel identifier returned by \fBopen\fR may be used +to write to the command's input pipe or read from its output pipe, +depending on the value of \fIaccess\fR. +If write-only access is used (e.g. \fIaccess\fR is \fBw\fR), then +standard output for the pipeline is directed to the current standard +output unless overridden by the command. +If read-only access is used (e.g. \fIaccess\fR is \fBr\fR), +standard input for the pipeline is taken from the current standard +input unless overridden by the command. +.SH "SERIAL COMMUNICATIONS" +.VS +.PP +If \fIfileName\fR refers to a serial port, then the specified serial port +is opened and initialized in a platform-dependent manner. Acceptable +values for the \fIfileName\fR to use to open a serial port are described in +the PORTABILITY ISSUES section. + +.SH "CONFIGURATION OPTIONS" +The \fBfconfigure\fR command can be used to query and set the following +configuration option for open serial ports: +.TP +\fB\-mode \fIbaud\fB,\fIparity\fB,\fIdata\fB,\fIstop\fR +. +This option is a set of 4 comma-separated values: the baud rate, parity, +number of data bits, and number of stop bits for this serial port. The +\fIbaud\fR rate is a simple integer that specifies the connection speed. +\fIParity\fR is one of the following letters: \fBn\fR, \fBo\fR, \fBe\fR, +\fBm\fR, \fBs\fR; respectively signifying the parity options of ``none'', +``odd'', ``even'', ``mark'', or ``space''. \fIData\fR is the number of +data bits and should be an integer from 5 to 8, while \fIstop\fR is the +number of stop bits and should be the integer 1 or 2. +.TP +\fB\-pollinterval \fImsec\fR +. +This option, available only on Windows for serial ports, is used to +set the maximum time between polling for fileevents. This affects the +time interval between checking for events throughout the Tcl +interpreter (the smallest value always wins). Use this option only if +you want to poll the serial port more often than 10 msec (the default). +.TP +\fB\-lasterror\fR +. +This option is available only on Windows for serial ports, and is +query only (will only be reported when directly requested). +In case of a serial communication error, \fBread\fR or \fBputs\fR +returns a general Tcl file I/O error. +\fBfconfigure -lasterror\fR can be called to get a list +of error details (e.g. FRAME RXOVER). +.VE + +.VS +.SH "PORTABILITY ISSUES" +.sp +.TP +\fBWindows \fR(all versions) +. +Valid values for \fIfileName\fR to open a serial port are of the form +\fBcom\fIX\fB:\fR, where \fIX\fR is a number, generally from 1 to 4. +This notation only works for serial ports from 1 to 9, if the system +happens to have more than four. An attempt to open a serial port that +does not exist or has a number greater than 9 will fail. An alternate +form of opening serial ports is to use the filename \fB\e\e.\ecomX\fR, +where X is any number that corresponds to a serial port; please note +that this method is considerably slower on Windows 95 and Windows 98. +.TP +\fBWindows NT\fR +. +When running Tcl interactively, there may be some strange interactions +between the real console, if one is present, and a command pipeline that uses +standard input or output. If a command pipeline is opened for reading, some +of the lines entered at the console will be sent to the command pipeline and +some will be sent to the Tcl evaluator. If a command pipeline is opened for +writing, keystrokes entered into the console are not visible until the the +pipe is closed. This behavior occurs whether the command pipeline is +executing 16-bit or 32-bit applications. These problems only occur because +both Tcl and the child application are competing for the console at +the same time. If the command pipeline is started from a script, so that Tcl +is not accessing the console, or if the command pipeline does not use +standard input or output, but is redirected from or to a file, then the +above problems do not occur. +.TP +\fBWindows 95\fR +. +A command pipeline that executes a 16-bit DOS application cannot be opened +for both reading and writing, since 16-bit DOS applications that receive +standard input from a pipe and send standard output to a pipe run +synchronously. Command pipelines that do not execute 16-bit DOS +applications run asynchronously and can be opened for both reading and +writing. +.sp +When running Tcl interactively, there may be some strange interactions +between the real console, if one is present, and a command pipeline that uses +standard input or output. If a command pipeline is opened for reading from +a 32-bit application, some of the keystrokes entered at the console will be +sent to the command pipeline and some will be sent to the Tcl evaluator. If +a command pipeline is opened for writing to a 32-bit application, no output +is visible on the console until the the pipe is closed. These problems only +occur because both Tcl and the child application are competing for the +console at the same time. If the command pipeline is started from a script, +so that Tcl is not accessing the console, or if the command pipeline does +not use standard input or output, but is redirected from or to a file, then +the above problems do not occur. +.sp +Whether or not Tcl is running interactively, if a command pipeline is opened +for reading from a 16-bit DOS application, the call to \fBopen\fR will not +return until end-of-file has been received from the command pipeline's +standard output. If a command pipeline is opened for writing to a 16-bit DOS +application, no data will be sent to the command pipeline's standard output +until the pipe is actually closed. This problem occurs because 16-bit DOS +applications are run synchronously, as described above. +.TP +\fBMacintosh\fR +. +Opening a serial port is not currently implemented under Macintosh. +.sp +Opening a command pipeline is not supported under Macintosh, since +applications do not support the concept of standard input or output. +.TP +\fBUnix\fR\0\0\0\0\0\0\0 +. +Valid values for \fIfileName\fR to open a serial port are generally of the +form \fB/dev/tty\fIX\fR, where \fIX\fR is \fBa\fR or \fBb\fR, but the name +of any pseudo-file that maps to a serial port may be used. +.sp +When running Tcl interactively, there may be some strange interactions +between the console, if one is present, and a command pipeline that uses +standard input. If a command pipeline is opened for reading, some +of the lines entered at the console will be sent to the command pipeline and +some will be sent to the Tcl evaluator. This problem only occurs because +both Tcl and the child application are competing for the console at the +same time. If the command pipeline is started from a script, so that Tcl is +not accessing the console, or if the command pipeline does not use standard +input, but is redirected from a file, then the above problem does not occur. +.LP +See the PORTABILITY ISSUES section of the \fBexec\fR command for additional +information not specific to command pipelines about executing +applications on the various platforms + +.SH "SEE ALSO" +file(n), close(n), filename(n), fconfigure(n), gets(n), read(n), +puts(n), exec(n), fopen(1) + +.SH KEYWORDS +access mode, append, create, file, non-blocking, open, permissions, +pipeline, process, serial diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/package.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/package.n new file mode 100644 index 0000000000000000000000000000000000000000..0ecf5ab7249bce9bda0b18786df1c1f7650d53b3 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/package.n @@ -0,0 +1,196 @@ +'\" +'\" Copyright (c) 1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: package.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH package n 7.5 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +package \- Facilities for package loading and version control +.SH SYNOPSIS +.nf +\fBpackage forget ?\fIpackage package ...\fR? +\fBpackage ifneeded \fIpackage version\fR ?\fIscript\fR? +\fBpackage names\fR +\fBpackage present \fR?\fB\-exact\fR? \fIpackage \fR?\fIversion\fR? +\fBpackage provide \fIpackage \fR?\fIversion\fR? +\fBpackage require \fR?\fB\-exact\fR? \fIpackage \fR?\fIversion\fR? +\fBpackage unknown \fR?\fIcommand\fR? +\fBpackage vcompare \fIversion1 version2\fR +\fBpackage versions \fIpackage\fR +\fBpackage vsatisfies \fIversion1 version2\fR +.fi +.BE + +.SH DESCRIPTION +.PP +This command keeps a simple database of the packages available for +use by the current interpreter and how to load them into the +interpreter. +It supports multiple versions of each package and arranges +for the correct version of a package to be loaded based on what +is needed by the application. +This command also detects and reports version clashes. +Typically, only the \fBpackage require\fR and \fBpackage provide\fR +commands are invoked in normal Tcl scripts; the other commands are used +primarily by system scripts that maintain the package database. +.PP +The behavior of the \fBpackage\fR command is determined by its first argument. +The following forms are permitted: +.TP +\fBpackage forget ?\fIpackage package ...\fR? +Removes all information about each specified package from this interpreter, +including information provided by both \fBpackage ifneeded\fR and +\fBpackage provide\fR. +.TP +\fBpackage ifneeded \fIpackage version\fR ?\fIscript\fR? +This command typically appears only in system configuration +scripts to set up the package database. +It indicates that a particular version of +a particular package is available if needed, and that the package +can be added to the interpreter by executing \fIscript\fR. +The script is saved in a database for use by subsequent +\fBpackage require\fR commands; typically, \fIscript\fR +sets up auto-loading for the commands in the package (or calls +\fBload\fR and/or \fBsource\fR directly), then invokes +\fBpackage provide\fR to indicate that the package is present. +There may be information in the database for several different +versions of a single package. +If the database already contains information for \fIpackage\fR +and \fIversion\fR, the new \fIscript\fR replaces the existing +one. +If the \fIscript\fR argument is omitted, the current script for +version \fIversion\fR of package \fIpackage\fR is returned, +or an empty string if no \fBpackage ifneeded\fR command has +been invoked for this \fIpackage\fR and \fIversion\fR. +.TP +\fBpackage names\fR +Returns a list of the names of all packages in the +interpreter for which a version has been provided (via +\fBpackage provide\fR) or for which a \fBpackage ifneeded\fR +script is available. +The order of elements in the list is arbitrary. +.TP +\fBpackage present \fR?\fB\-exact\fR? \fIpackage \fR?\fIversion\fR? +This command is equivalent to \fBpackage require\fR except that it +does not try and load the package if it is not already loaded. +.TP +\fBpackage provide \fIpackage \fR?\fIversion\fR? +This command is invoked to indicate that version \fIversion\fR +of package \fIpackage\fR is now present in the interpreter. +It is typically invoked once as part of an \fBifneeded\fR script, +and again by the package itself when it is finally loaded. +An error occurs if a different version of \fIpackage\fR has been +provided by a previous \fBpackage provide\fR command. +If the \fIversion\fR argument is omitted, then the command +returns the version number that is currently provided, or an +empty string if no \fBpackage provide\fR command has been +invoked for \fIpackage\fR in this interpreter. +.TP +\fBpackage require \fR?\fB\-exact\fR? \fIpackage \fR?\fIversion\fR? +This command is typically invoked by Tcl code that wishes to use +a particular version of a particular package. The arguments +indicate which package is wanted, and the command ensures that +a suitable version of the package is loaded into the interpreter. +If the command succeeds, it returns the version number that is +loaded; otherwise it generates an error. +If both the \fB\-exact\fR +switch and the \fIversion\fR argument are specified then only the +given version is acceptable. If \fB\-exact\fR is omitted but +\fIversion\fR is specified, then versions later than \fIversion\fR +are also acceptable as long as they have the same major version +number as \fIversion\fR. +If both \fB\-exact\fR and \fIversion\fR are omitted then any +version whatsoever is acceptable. +If a version of \fIpackage\fR has already been provided (by invoking +the \fBpackage provide\fR command), then its version number must +satisfy the criteria given by \fB\-exact\fR and \fIversion\fR and +the command returns immediately. +Otherwise, the command searches the database of information provided by +previous \fBpackage ifneeded\fR commands to see if an acceptable +version of the package is available. +If so, the script for the highest acceptable version number is invoked; +it must do whatever is necessary to load the package, +including calling \fBpackage provide\fR for the package. +If the \fBpackage ifneeded\fR database does not contain an acceptable +version of the package and a \fBpackage unknown\fR command has been +specified for the interpreter then that command is invoked; when +it completes, Tcl checks again to see if the package is now provided +or if there is a \fBpackage ifneeded\fR script for it. +If all of these steps fail to provide an acceptable version of the +package, then the command returns an error. +.TP +\fBpackage unknown \fR?\fIcommand\fR? +This command supplies a ``last resort'' command to invoke during +\fBpackage require\fR if no suitable version of a package can be found +in the \fBpackage ifneeded\fR database. +If the \fIcommand\fR argument is supplied, it contains the first part +of a command; when the command is invoked during a \fBpackage require\fR +command, Tcl appends two additional arguments giving the desired package +name and version. +For example, if \fIcommand\fR is \fBfoo bar\fR and later the command +\fBpackage require test 2.4\fR is invoked, then Tcl will execute +the command \fBfoo bar test 2.4\fR to load the package. +If no version number is supplied to the \fBpackage require\fR command, +then the version argument for the invoked command will be an empty string. +If the \fBpackage unknown\fR command is invoked without a \fIcommand\fR +argument, then the current \fBpackage unknown\fR script is returned, +or an empty string if there is none. +If \fIcommand\fR is specified as an empty string, then the current +\fBpackage unknown\fR script is removed, if there is one. +.TP +\fBpackage vcompare \fIversion1 version2\fR +Compares the two version numbers given by \fIversion1\fR and \fIversion2\fR. +Returns -1 if \fIversion1\fR is an earlier version than \fIversion2\fR, +0 if they are equal, and 1 if \fIversion1\fR is later than \fBversion2\fR. +.TP +\fBpackage versions \fIpackage\fR +Returns a list of all the version numbers of \fIpackage\fR +for which information has been provided by \fBpackage ifneeded\fR +commands. +.TP +\fBpackage vsatisfies \fIversion1 version2\fR +Returns 1 if scripts written for \fIversion2\fR will work unchanged +with \fIversion1\fR (i.e. \fIversion1\fR is equal to or greater +than \fIversion2\fR and they both have the same major version +number), 0 otherwise. + +.SH "VERSION NUMBERS" +.PP +Version numbers consist of one or more decimal numbers separated +by dots, such as 2 or 1.162 or 3.1.13.1. +The first number is called the major version number. +Larger numbers correspond to later versions of a package, with +leftmost numbers having greater significance. +For example, version 2.1 is later than 1.3 and version +3.4.6 is later than 3.3.5. +Missing fields are equivalent to zeroes: version 1.3 is the +same as version 1.3.0 and 1.3.0.0, so it is earlier than 1.3.1 or 1.3.0.2. +A later version number is assumed to be upwards compatible with +an earlier version number as long as both versions have the same +major version number. +For example, Tcl scripts written for version 2.3 of a package should +work unchanged under versions 2.3.2, 2.4, and 2.5.1. +Changes in the major version number signify incompatible changes: +if code is written to use version 2.1 of a package, it is not guaranteed +to work unmodified with either version 1.7.3 or version 3.1. + +.SH "PACKAGE INDICES" +.PP +The recommended way to use packages in Tcl is to invoke \fBpackage require\fR +and \fBpackage provide\fR commands in scripts, and use the procedure +\fBpkg_mkIndex\fR to create package index files. +Once you've done this, packages will be loaded automatically +in response to \fBpackage require\fR commands. +See the documentation for \fBpkg_mkIndex\fR for details. + +.SH "SEE ALSO" +msgcat(n), packagens(n), pkgMkIndex(n) + +.SH KEYWORDS +package, version diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/packagens.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/packagens.n new file mode 100644 index 0000000000000000000000000000000000000000..18788f4338f7067623daa1d8c16de59ae5c36352 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/packagens.n @@ -0,0 +1,55 @@ +'\" +'\" Copyright (c) 1998-2000 by Scriptics Corporation. +'\" All rights reserved. +'\" +'\" RCS: @(#) $Id: packagens.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH pkg::create n 8.3 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +pkg::create \- Construct an appropriate \fBpackage ifneeded\fR +command for a given package specification +.SH SYNOPSIS +\fB::pkg::create \fI\-name packageName\fR \fI\-version packageVersion\fR ?\fI\-load filespec\fR? ... ?\fI\-source filespec\fR? ... +.BE + +.SH DESCRIPTION +.PP +\fB::pkg::create\fR is a utility procedure that is part of the standard Tcl +library. It is used to create an appropriate \fBpackage ifneeded\fR +command for a given package specification. It can be used to construct a +\fBpkgIndex.tcl\fR file for use with the \fBpackage\fR mechanism. + +.SH OPTIONS +The parameters supported are: +.TP +\fB\-name\fR\0\fIpackageName\fR +This parameter specifies the name of the package. It is required. +.TP +\fB\-version\fR\0\fIpackageVersion\fR +This parameter specifies the version of the package. It is required. +.TP +\fB\-load\fR\0\fIfilespec\fR +This parameter specifies a binary library that must be loaded with the +\fBload\fR command. \fIfilespec\fR is a list with two elements. The +first element is the name of the file to load. The second, optional +element is a list of commands supplied by loading that file. If the +list of procedures is empty or omitted, \fB::pkg::create\fR will +set up the library for direct loading (see \fBpkg_mkIndex\fR). Any +number of \fB\-load\fR parameters may be specified. +.TP +\fB\-source\fR\0\fIfilespec\fR +This parameter is similar to the \fB\-load\fR parameter, except that it +specifies a Tcl library that must be loaded with the +\fBsource\fR command. Any number of \fB\-source\fR parameters may be +specified. +.PP +At least one \fB\-load\fR or \fB\-source\fR paramter must be given. + +.SH "SEE ALSO" +package(n) + +.SH KEYWORDS +auto-load, index, package, version diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/pid.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/pid.n new file mode 100644 index 0000000000000000000000000000000000000000..5a11f1fb7bd2c9acd90ec6026cbc14f0f926db4f --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/pid.n @@ -0,0 +1,37 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: pid.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH pid n 7.0 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +pid \- Retrieve process id(s) +.SH SYNOPSIS +\fBpid \fR?\fIfileId\fR? +.BE + +.SH DESCRIPTION +.PP +If the \fIfileId\fR argument is given then it should normally +refer to a process pipeline created with the \fBopen\fR command. +In this case the \fBpid\fR command will return a list whose elements +are the process identifiers of all the processes in the pipeline, +in order. +The list will be empty if \fIfileId\fR refers to an open file +that isn't a process pipeline. +If no \fIfileId\fR argument is given then \fBpid\fR returns the process +identifier of the current process. +All process identifiers are returned as decimal strings. + +.SH "SEE ALSO" +exec(n), open(n) + +.SH KEYWORDS +file, pipeline, process identifier diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/pkgMkIndex.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/pkgMkIndex.n new file mode 100644 index 0000000000000000000000000000000000000000..a2e963c5786e5b2ee6e8b8de60b0a5281e56ee5a --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/pkgMkIndex.n @@ -0,0 +1,243 @@ +'\" +'\" Copyright (c) 1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: pkgMkIndex.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH pkg_mkIndex n 8.3 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +pkg_mkIndex \- Build an index for automatic loading of packages +.SH SYNOPSIS +.nf +.VS 8.3.0 +\fBpkg_mkIndex ?\fI\-direct\fR? ?\fI\-lazy\fR? ?\fI\-load pkgPat\fR? ?\fI\-verbose\fR? \fIdir\fR ?\fIpattern pattern ...\fR? +.VE +.fi +.BE + +.SH DESCRIPTION +.PP +\fBPkg_mkIndex\fR is a utility procedure that is part of the standard +Tcl library. +It is used to create index files that allow packages to be loaded +automatically when \fBpackage require\fR commands are executed. +To use \fBpkg_mkIndex\fR, follow these steps: +.IP [1] +Create the package(s). +Each package may consist of one or more Tcl script files or binary files. +Binary files must be suitable for loading with the \fBload\fR command +with a single argument; for example, if the file is \fBtest.so\fR it must +be possible to load this file with the command \fBload test.so\fR. +Each script file must contain a \fBpackage provide\fR command to declare +the package and version number, and each binary file must contain +a call to \fBTcl_PkgProvide\fR. +.IP [2] +Create the index by invoking \fBpkg_mkIndex\fR. +The \fIdir\fR argument gives the name of a directory and each +\fIpattern\fR argument is a \fBglob\fR-style pattern that selects +script or binary files in \fIdir\fR. +.VS 8.0.3 +The default pattern is \fB*.tcl\fR and \fB*.[info sharedlibextension]\fR. +.VE +.br +\fBPkg_mkIndex\fR will create a file \fBpkgIndex.tcl\fR in \fIdir\fR +with package information about all the files given by the \fIpattern\fR +arguments. +It does this by loading each file into a slave +interpreter and seeing what packages +and new commands appear (this is why it is essential to have +\fBpackage provide\fR commands or \fBTcl_PkgProvide\fR calls +in the files, as described above). +If you have a package split among scripts and binary files, +or if you have dependencies among files, +you may have to use the \fB\-load\fP option +or adjust the order in which \fBpkg_mkIndex\fR processes +the files. See COMPLEX CASES below. + +.IP [3] +Install the package as a subdirectory of one of the directories given by +the \fBtcl_pkgPath\fR variable. If \fB$tcl_pkgPath\fR contains more +than one directory, machine-dependent packages (e.g., those that +contain binary shared libraries) should normally be installed +under the first directory and machine-independent packages (e.g., +those that contain only Tcl scripts) should be installed under the +second directory. +The subdirectory should include +the package's script and/or binary files as well as the \fBpkgIndex.tcl\fR +file. As long as the package is installed as a subdirectory of a +directory in \fB$tcl_pkgPath\fR it will automatically be found during +\fBpackage require\fR commands. +.br +If you install the package anywhere else, then you must ensure that +the directory containing the package is in the \fBauto_path\fR global variable +or an immediate subdirectory of one of the directories in \fBauto_path\fR. +\fBAuto_path\fR contains a list of directories that are searched +by both the auto-loader and the package loader; by default it +includes \fB$tcl_pkgPath\fR. +The package loader also checks all of the subdirectories of the +directories in \fBauto_path\fR. +You can add a directory to \fBauto_path\fR explicitly in your +application, or you can add the directory to your \fBTCLLIBPATH\fR +environment variable: if this environment variable is present, +Tcl initializes \fBauto_path\fR from it during application startup. +.IP [4] +Once the above steps have been taken, all you need to do to use a +package is to invoke \fBpackage require\fR. +For example, if versions 2.1, 2.3, and 3.1 of package \fBTest\fR +have been indexed by \fBpkg_mkIndex\fR, the command +\fBpackage require Test\fR will make version 3.1 available +and the command \fBpackage require \-exact Test 2.1\fR will +make version 2.1 available. +There may be many versions of a package in the various index files +in \fBauto_path\fR, but only one will actually be loaded in a given +interpreter, based on the first call to \fBpackage require\fR. +Different versions of a package may be loaded in different +interpreters. + +.SH OPTIONS +The optional switches are: +.TP 15 +\fB\-direct\fR +The generated index will implement direct loading of the package +upon \fBpackage require\fR. This is the default. +.TP 15 +\fB\-lazy\fR +The generated index will manage to delay loading the package until the +use of one of the commands provided by the package, instead of loading +it immediately upon \fBpackage require\fR. +.TP 15 +\fB\-load \fIpkgPat\fR +The index process will pre-load any packages that exist in the +current interpreter and match \fIpkgPat\fP into the slave interpreter used to +generate the index. The pattern match uses string match rules. +See COMPLEX CASES below. +.TP 15 +\fB\-verbose\fR +Generate output during the indexing process. Output is via +the \fBtclLog\fP procedure, which by default prints to stderr. +.TP 15 +\fB\-\-\fR +End of the flags, in case \fIdir\fP begins with a dash. + +.SH "PACKAGES AND THE AUTO-LOADER" +.PP +The package management facilities overlap somewhat with the auto-loader, +in that both arrange for files to be loaded on-demand. +However, package management is a higher-level mechanism that uses +the auto-loader for the last step in the loading process. +It is generally better to index a package with \fBpkg_mkIndex\fR +rather than \fBauto_mkindex\fR because the package mechanism provides +version control: several versions of a package can be made available +in the index files, with different applications using different +versions based on \fBpackage require\fR commands. +In contrast, \fBauto_mkindex\fR does not understand versions so +it can only handle a single version of each package. +It is probably not a good idea to index a given package with both +\fBpkg_mkIndex\fR and \fBauto_mkindex\fR. +If you use \fBpkg_mkIndex\fR to index a package, its commands cannot +be invoked until \fBpackage require\fR has been used to select a +version; in contrast, packages indexed with \fBauto_mkindex\fR +can be used immediately since there is no version control. + +.SH "HOW IT WORKS" +.PP +\fBPkg_mkIndex\fR depends on the \fBpackage unknown\fR command, +the \fBpackage ifneeded\fR command, and the auto-loader. +The first time a \fBpackage require\fR command is invoked, +the \fBpackage unknown\fR script is invoked. +This is set by Tcl initialization to a script that +evaluates all of the \fBpkgIndex.tcl\fR files in the +\fBauto_path\fR. +The \fBpkgIndex.tcl\fR files contain \fBpackage ifneeded\fR +commands for each version of each available package; these commands +invoke \fBpackage provide\fR commands to announce the +availability of the package, and they setup auto-loader +information to load the files of the package. +.VS 8.3 +If the \fI\-lazy\fR flag was provided when the \fBpkgIndex.tcl\fR +was generated, +.VE +a given file of a given version of a given package isn't +actually loaded until the first time one of its commands +is invoked. +Thus, after invoking \fBpackage require\fR you may +not see the package's commands in the interpreter, but you will be able +to invoke the commands and they will be auto-loaded. + +.VS 8.3 +.SH "DIRECT LOADING" +.PP +Some packages, for instance packages which use namespaces and export +commands or those which require special initialization, might select +that their package files be loaded immediately upon \fBpackage require\fR +instead of delaying the actual loading to the first use of one of the +package's command. This is the default mode when generating the package +index. It can be overridden by specifying the \fI\-lazy\fR argument. +.VE + +.SH "COMPLEX CASES" +Most complex cases of dependencies among scripts +and binary files, and packages being split among scripts and +binary files are handled OK. However, you may have to adjust +the order in which files are processed by \fBpkg_mkIndex\fR. +These issues are described in detail below. +.PP +If each script or file contains one package, and packages +are only contained in one file, then things are easy. +You simply specify all files to be indexed in any order +with some glob patterns. +.PP +In general, it is OK for scripts to have dependencies on other +packages. +If scripts contain \fBpackage require\fP commands, these are +stubbed out in the interpreter used to process the scripts, +so these do not cause problems. +If scripts call into other packages in global code, +these calls are handled by a stub \fBunknown\fP command. +However, if scripts make variable references to other package's +variables in global code, these will cause errors. That is +also bad coding style. +.PP +If binary files have dependencies on other packages, things +can become tricky because it is not possible to stub out +C-level API's such as \fBTcl_PkgRequire\fP API +when loading a binary file. +For example, suppose the BLT package requires Tk, and expresses +this with a call to \fBTcl_PkgRequire\fP in its \fBBlt_Init\fP routine. +To support this, you must run \fBpkg_mkIndex\fR in an interpreter that +has Tk loaded. You can achieve this with the +\fB\-load \fIpkgPat\fR option. If you specify this option, +\fBpkg_mkIndex\fR will load any packages listed by +\fBinfo loaded\fP and that match \fIpkgPat\fP +into the interpreter used to process files. +In most cases this will satisfy the \fBTcl_PkgRequire\fP calls +made by binary files. +.PP +If you are indexing two binary files and one depends on the other, +you should specify the one that has dependencies last. +This way the one without dependencies will get loaded and indexed, +and then the package it provides +will be available when the second file is processed. +You may also need to load the first package into the +temporary interpreter used to create the index by using +the \fB\-load\fP flag; +it won't hurt to specify package patterns that are not yet loaded. +.PP +If you have a package that is split across scripts and a binary file, +then you should avoid the \fB\-load\fP flag. The problem is that +if you load a package before computing the index it masks any +other files that provide part of the same package. +If you must use \fB\-load\fP, +then you must specify the scripts first; otherwise the package loaded from +the binary file may mask the package defined by the scripts. + +.SH "SEE ALSO" +package(n) + +.SH KEYWORDS +auto-load, index, package, version diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/proc.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/proc.n new file mode 100644 index 0000000000000000000000000000000000000000..0509d703f058feeecf4bd11a8ec87ab926ffea05 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/proc.n @@ -0,0 +1,77 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: proc.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH proc n "" Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +proc \- Create a Tcl procedure +.SH SYNOPSIS +\fBproc \fIname args body\fR +.BE + +.SH DESCRIPTION +.PP +The \fBproc\fR command creates a new Tcl procedure named +\fIname\fR, replacing +any existing command or procedure there may have been by that name. +Whenever the new command is invoked, the contents of \fIbody\fR will +be executed by the Tcl interpreter. +Normally, \fIname\fR is unqualified +(does not include the names of any containing namespaces), +and the new procedure is created in the current namespace. +If \fIname\fR includes any namespace qualifiers, +the procedure is created in the specified namespace. +\fIArgs\fR specifies the formal arguments to the +procedure. It consists of a list, possibly empty, each of whose +elements specifies +one argument. Each argument specifier is also a list with either +one or two fields. If there is only a single field in the specifier +then it is the name of the argument; if there are two fields, then +the first is the argument name and the second is its default value. +.PP +When \fIname\fR is invoked a local variable +will be created for each of the formal arguments to the procedure; its +value will be the value of corresponding argument in the invoking command +or the argument's default value. +Arguments with default values need not be +specified in a procedure invocation. However, there must be enough +actual arguments for all the +formal arguments that don't have defaults, and there must not be any extra +actual arguments. There is one special case to permit procedures with +variable numbers of arguments. If the last formal argument has the name +\fBargs\fR, then a call to the procedure may contain more actual arguments +than the procedure has formals. In this case, all of the actual arguments +starting at the one that would be assigned to \fBargs\fR are combined into +a list (as if the \fBlist\fR command had been used); this combined value +is assigned to the local variable \fBargs\fR. +.PP +When \fIbody\fR is being executed, variable names normally refer to +local variables, which are created automatically when referenced and +deleted when the procedure returns. One local variable is automatically +created for each of the procedure's arguments. +Global variables can only be accessed by invoking +the \fBglobal\fR command or the \fBupvar\fR command. +Namespace variables can only be accessed by invoking +the \fBvariable\fR command or the \fBupvar\fR command. +.PP +The \fBproc\fR command returns an empty string. When a procedure is +invoked, the procedure's return value is the value specified in a +\fBreturn\fR command. If the procedure doesn't execute an explicit +\fBreturn\fR, then its return value is the value of the last command +executed in the procedure's body. +If an error occurs while executing the procedure +body, then the procedure-as-a-whole will return that same error. + +.SH "SEE ALSO" +info(n), unknown(n) + +.SH KEYWORDS +argument, procedure diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/puts.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/puts.n new file mode 100644 index 0000000000000000000000000000000000000000..9f0d053843710df9efc641191df07bc956155b06 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/puts.n @@ -0,0 +1,69 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: puts.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH puts n 7.5 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +puts \- Write to a channel +.SH SYNOPSIS +\fBputs \fR?\fB\-nonewline\fR? ?\fIchannelId\fR? \fIstring\fR +.BE + +.SH DESCRIPTION +.PP +Writes the characters given by \fIstring\fR to the channel given +by \fIchannelId\fR. +\fIChannelId\fR must be a channel identifier such as returned from a +previous invocation of \fBopen\fR or \fBsocket\fR. It must have been opened +for output. If no \fIchannelId\fR is specified then it defaults to +\fBstdout\fR. \fBPuts\fR normally outputs a newline character after +\fIstring\fR, but this feature may be suppressed by specifying the +\fB\-nonewline\fR switch. +.PP +Newline characters in the output are translated by \fBputs\fR to +platform-specific end-of-line sequences according to the current +value of the \fB\-translation\fR option for the channel (for example, +on PCs newlines are normally replaced with carriage-return-linefeed +sequences; on Macintoshes newlines are normally replaced with +carriage-returns). +See the \fBfconfigure\fR manual entry for a discussion on ways in +which \fBfconfigure\fR will alter output. +.PP +Tcl buffers output internally, so characters written with \fBputs\fR +may not appear immediately on the output file or device; Tcl will +normally delay output until the buffer is full or the channel is +closed. +You can force output to appear immediately with the \fBflush\fR +command. +.PP +When the output buffer fills up, the \fBputs\fR command will normally +block until all the buffered data has been accepted for output by the +operating system. +If \fIchannelId\fR is in nonblocking mode then the \fBputs\fR command +will not block even if the operating system cannot accept the data. +Instead, Tcl continues to buffer the data and writes it in the +background as fast as the underlying file or device can accept it. +The application must use the Tcl event loop for nonblocking output +to work; otherwise Tcl never finds out that the file or device is +ready for more output data. +It is possible for an arbitrarily large amount of data to be +buffered for a channel in nonblocking mode, which could consume a +large amount of memory. +To avoid wasting memory, nonblocking I/O should normally +be used in an event-driven fashion with the \fBfileevent\fR command +(don't invoke \fBputs\fR unless you have recently been notified +via a file event that the channel is ready for more output data). + +.SH "SEE ALSO" +file(n), fileevent(n) + +.SH KEYWORDS +channel, newline, output, write diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/pwd.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/pwd.n new file mode 100644 index 0000000000000000000000000000000000000000..c530b3dfbb7a9739f9070ad09a0eee700b4bd684 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/pwd.n @@ -0,0 +1,28 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: pwd.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH pwd n "" Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +pwd \- Return the current working directory +.SH SYNOPSIS +\fBpwd\fR +.BE + +.SH DESCRIPTION +.PP +Returns the path name of the current working directory. + +.SH "SEE ALSO" +file(n), cd(n), glob(n), filename(n) + +.SH KEYWORDS +working directory diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/re_syntax.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/re_syntax.n new file mode 100644 index 0000000000000000000000000000000000000000..0f1aaa3628af6364f468ca43c69e3fe22daf43ae --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/re_syntax.n @@ -0,0 +1,932 @@ +'\" +'\" Copyright (c) 1998 Sun Microsystems, Inc. +'\" Copyright (c) 1999 Scriptics Corporation +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: re_syntax.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH re_syntax n "8.1" Tcl "Tcl Built-In Commands" +.BS +.SH NAME +re_syntax \- Syntax of Tcl regular expressions. +.BE + +.SH DESCRIPTION +.PP +A \fIregular expression\fR describes strings of characters. +It's a pattern that matches certain strings and doesn't match others. + +.SH "DIFFERENT FLAVORS OF REs" +Regular expressions (``RE''s), as defined by POSIX, come in two +flavors: \fIextended\fR REs (``EREs'') and \fIbasic\fR REs (``BREs''). +EREs are roughly those of the traditional \fIegrep\fR, while BREs are +roughly those of the traditional \fIed\fR. This implementation adds +a third flavor, \fIadvanced\fR REs (``AREs''), basically EREs with +some significant extensions. +.PP +This manual page primarily describes AREs. BREs mostly exist for +backward compatibility in some old programs; they will be discussed at +the end. POSIX EREs are almost an exact subset of AREs. Features of +AREs that are not present in EREs will be indicated. + +.SH "REGULAR EXPRESSION SYNTAX" +.PP +Tcl regular expressions are implemented using the package written by +Henry Spencer, based on the 1003.2 spec and some (not quite all) of +the Perl5 extensions (thanks, Henry!). Much of the description of +regular expressions below is copied verbatim from his manual entry. +.PP +An ARE is one or more \fIbranches\fR, +separated by `\fB|\fR', +matching anything that matches any of the branches. +.PP +A branch is zero or more \fIconstraints\fR or \fIquantified atoms\fR, +concatenated. +It matches a match for the first, followed by a match for the second, etc; +an empty branch matches the empty string. +.PP +A quantified atom is an \fIatom\fR possibly followed +by a single \fIquantifier\fR. +Without a quantifier, it matches a match for the atom. +The quantifiers, +and what a so-quantified atom matches, are: +.RS 2 +.TP 6 +\fB*\fR +a sequence of 0 or more matches of the atom +.TP +\fB+\fR +a sequence of 1 or more matches of the atom +.TP +\fB?\fR +a sequence of 0 or 1 matches of the atom +.TP +\fB{\fIm\fB}\fR +a sequence of exactly \fIm\fR matches of the atom +.TP +\fB{\fIm\fB,}\fR +a sequence of \fIm\fR or more matches of the atom +.TP +\fB{\fIm\fB,\fIn\fB}\fR +a sequence of \fIm\fR through \fIn\fR (inclusive) matches of the atom; +\fIm\fR may not exceed \fIn\fR +.TP +\fB*? +? ?? {\fIm\fB}? {\fIm\fB,}? {\fIm\fB,\fIn\fB}?\fR +\fInon-greedy\fR quantifiers, +which match the same possibilities, +but prefer the smallest number rather than the largest number +of matches (see MATCHING) +.RE +.PP +The forms using +\fB{\fR and \fB}\fR +are known as \fIbound\fRs. +The numbers +\fIm\fR and \fIn\fR are unsigned decimal integers +with permissible values from 0 to 255 inclusive. +.PP +An atom is one of: +.RS 2 +.TP 6 +\fB(\fIre\fB)\fR +(where \fIre\fR is any regular expression) +matches a match for +\fIre\fR, with the match noted for possible reporting +.TP +\fB(?:\fIre\fB)\fR +as previous, +but does no reporting +(a ``non-capturing'' set of parentheses) +.TP +\fB()\fR +matches an empty string, +noted for possible reporting +.TP +\fB(?:)\fR +matches an empty string, +without reporting +.TP +\fB[\fIchars\fB]\fR +a \fIbracket expression\fR, +matching any one of the \fIchars\fR (see BRACKET EXPRESSIONS for more detail) +.TP + \fB.\fR +matches any single character +.TP +\fB\e\fIk\fR +(where \fIk\fR is a non-alphanumeric character) +matches that character taken as an ordinary character, +e.g. \e\e matches a backslash character +.TP +\fB\e\fIc\fR +where \fIc\fR is alphanumeric +(possibly followed by other characters), +an \fIescape\fR (AREs only), +see ESCAPES below +.TP +\fB{\fR +when followed by a character other than a digit, +matches the left-brace character `\fB{\fR'; +when followed by a digit, it is the beginning of a +\fIbound\fR (see above) +.TP +\fIx\fR +where \fIx\fR is +a single character with no other significance, matches that character. +.RE +.PP +A \fIconstraint\fR matches an empty string when specific conditions +are met. +A constraint may not be followed by a quantifier. +The simple constraints are as follows; some more constraints are +described later, under ESCAPES. +.RS 2 +.TP 8 +\fB^\fR +matches at the beginning of a line +.TP +\fB$\fR +matches at the end of a line +.TP +\fB(?=\fIre\fB)\fR +\fIpositive lookahead\fR (AREs only), matches at any point +where a substring matching \fIre\fR begins +.TP +\fB(?!\fIre\fB)\fR +\fInegative lookahead\fR (AREs only), matches at any point +where no substring matching \fIre\fR begins +.RE +.PP +The lookahead constraints may not contain back references (see later), +and all parentheses within them are considered non-capturing. +.PP +An RE may not end with `\fB\e\fR'. + +.SH "BRACKET EXPRESSIONS" +A \fIbracket expression\fR is a list of characters enclosed in `\fB[\|]\fR'. +It normally matches any single character from the list (but see below). +If the list begins with `\fB^\fR', +it matches any single character +(but see below) \fInot\fR from the rest of the list. +.PP +If two characters in the list are separated by `\fB\-\fR', +this is shorthand +for the full \fIrange\fR of characters between those two (inclusive) in the +collating sequence, +e.g. +\fB[0\-9]\fR +in ASCII matches any decimal digit. +Two ranges may not share an +endpoint, so e.g. +\fBa\-c\-e\fR +is illegal. +Ranges are very collating-sequence-dependent, +and portable programs should avoid relying on them. +.PP +To include a literal +\fB]\fR +or +\fB\-\fR +in the list, +the simplest method is to +enclose it in +\fB[.\fR and \fB.]\fR +to make it a collating element (see below). +Alternatively, +make it the first character +(following a possible `\fB^\fR'), +or (AREs only) precede it with `\fB\e\fR'. +Alternatively, for `\fB\-\fR', +make it the last character, +or the second endpoint of a range. +To use a literal +\fB\-\fR +as the first endpoint of a range, +make it a collating element +or (AREs only) precede it with `\fB\e\fR'. +With the exception of these, some combinations using +\fB[\fR +(see next +paragraphs), and escapes, +all other special characters lose their +special significance within a bracket expression. +.PP +Within a bracket expression, a collating element (a character, +a multi-character sequence that collates as if it were a single character, +or a collating-sequence name for either) +enclosed in +\fB[.\fR and \fB.]\fR +stands for the +sequence of characters of that collating element. +The sequence is a single element of the bracket expression's list. +A bracket expression in a locale that has +multi-character collating elements +can thus match more than one character. +.VS 8.2 +So (insidiously), a bracket expression that starts with \fB^\fR +can match multi-character collating elements even if none of them +appear in the bracket expression! +(\fINote:\fR Tcl currently has no multi-character collating elements. +This information is only for illustration.) +.PP +For example, assume the collating sequence includes a \fBch\fR +multi-character collating element. +Then the RE \fB[[.ch.]]*c\fR (zero or more \fBch\fP's followed by \fBc\fP) +matches the first five characters of `\fBchchcc\fR'. +Also, the RE \fB[^c]b\fR matches all of `\fBchb\fR' +(because \fB[^c]\fR matches the multi-character \fBch\fR). +.VE 8.2 +.PP +Within a bracket expression, a collating element enclosed in +\fB[=\fR +and +\fB=]\fR +is an equivalence class, standing for the sequences of characters +of all collating elements equivalent to that one, including itself. +(If there are no other equivalent collating elements, +the treatment is as if the enclosing delimiters were `\fB[.\fR'\& +and `\fB.]\fR'.) +For example, if +\fBo\fR +and +\fB\o'o^'\fR +are the members of an equivalence class, +then `\fB[[=o=]]\fR', `\fB[[=\o'o^'=]]\fR', +and `\fB[o\o'o^']\fR'\& +are all synonymous. +An equivalence class may not be an endpoint +of a range. +.VS 8.2 +(\fINote:\fR +Tcl currently implements only the Unicode locale. +It doesn't define any equivalence classes. +The examples above are just illustrations.) +.VE 8.2 +.PP +Within a bracket expression, the name of a \fIcharacter class\fR enclosed +in +\fB[:\fR +and +\fB:]\fR +stands for the list of all characters +(not all collating elements!) +belonging to that +class. +Standard character classes are: +.PP +.RS +.ne 5 +.nf +.ta 3c +\fBalpha\fR A letter. +\fBupper\fR An upper-case letter. +\fBlower\fR A lower-case letter. +\fBdigit\fR A decimal digit. +\fBxdigit\fR A hexadecimal digit. +\fBalnum\fR An alphanumeric (letter or digit). +\fBprint\fR An alphanumeric (same as alnum). +\fBblank\fR A space or tab character. +\fBspace\fR A character producing white space in displayed text. +\fBpunct\fR A punctuation character. +\fBgraph\fR A character with a visible representation. +\fBcntrl\fR A control character. +.fi +.RE +.PP +A locale may provide others. +.VS 8.2 +(Note that the current Tcl implementation has only one locale: +the Unicode locale.) +.VE 8.2 +A character class may not be used as an endpoint of a range. +.PP +There are two special cases of bracket expressions: +the bracket expressions +\fB[[:<:]]\fR +and +\fB[[:>:]]\fR +are constraints, matching empty strings at +the beginning and end of a word respectively. +'\" note, discussion of escapes below references this definition of word +A word is defined as a sequence of +word characters +that is neither preceded nor followed by +word characters. +A word character is an +\fIalnum\fR +character +or an underscore +(\fB_\fR). +These special bracket expressions are deprecated; +users of AREs should use constraint escapes instead (see below). +.SH ESCAPES +Escapes (AREs only), which begin with a +\fB\e\fR +followed by an alphanumeric character, +come in several varieties: +character entry, class shorthands, constraint escapes, and back references. +A +\fB\e\fR +followed by an alphanumeric character but not constituting +a valid escape is illegal in AREs. +In EREs, there are no escapes: +outside a bracket expression, +a +\fB\e\fR +followed by an alphanumeric character merely stands for that +character as an ordinary character, +and inside a bracket expression, +\fB\e\fR +is an ordinary character. +(The latter is the one actual incompatibility between EREs and AREs.) +.PP +Character-entry escapes (AREs only) exist to make it easier to specify +non-printing and otherwise inconvenient characters in REs: +.RS 2 +.TP 5 +\fB\ea\fR +alert (bell) character, as in C +.TP +\fB\eb\fR +backspace, as in C +.TP +\fB\eB\fR +synonym for +\fB\e\fR +to help reduce backslash doubling in some +applications where there are multiple levels of backslash processing +.TP +\fB\ec\fIX\fR +(where X is any character) the character whose +low-order 5 bits are the same as those of +\fIX\fR, +and whose other bits are all zero +.TP +\fB\ee\fR +the character whose collating-sequence name +is `\fBESC\fR', +or failing that, the character with octal value 033 +.TP +\fB\ef\fR +formfeed, as in C +.TP +\fB\en\fR +newline, as in C +.TP +\fB\er\fR +carriage return, as in C +.TP +\fB\et\fR +horizontal tab, as in C +.TP +\fB\eu\fIwxyz\fR +(where +\fIwxyz\fR +is exactly four hexadecimal digits) +the Unicode character +\fBU+\fIwxyz\fR +in the local byte ordering +.TP +\fB\eU\fIstuvwxyz\fR +(where +\fIstuvwxyz\fR +is exactly eight hexadecimal digits) +reserved for a somewhat-hypothetical Unicode extension to 32 bits +.TP +\fB\ev\fR +vertical tab, as in C +are all available. +.TP +\fB\ex\fIhhh\fR +(where +\fIhhh\fR +is any sequence of hexadecimal digits) +the character whose hexadecimal value is +\fB0x\fIhhh\fR +(a single character no matter how many hexadecimal digits are used). +.TP +\fB\e0\fR +the character whose value is +\fB0\fR +.TP +\fB\e\fIxy\fR +(where +\fIxy\fR +is exactly two octal digits, +and is not a +\fIback reference\fR (see below)) +the character whose octal value is +\fB0\fIxy\fR +.TP +\fB\e\fIxyz\fR +(where +\fIxyz\fR +is exactly three octal digits, +and is not a +back reference (see below)) +the character whose octal value is +\fB0\fIxyz\fR +.RE +.PP +Hexadecimal digits are `\fB0\fR'-`\fB9\fR', `\fBa\fR'-`\fBf\fR', +and `\fBA\fR'-`\fBF\fR'. +Octal digits are `\fB0\fR'-`\fB7\fR'. +.PP +The character-entry escapes are always taken as ordinary characters. +For example, +\fB\e135\fR +is +\fB]\fR +in ASCII, +but +\fB\e135\fR +does not terminate a bracket expression. +Beware, however, that some applications (e.g., C compilers) interpret +such sequences themselves before the regular-expression package +gets to see them, which may require doubling (quadrupling, etc.) the `\fB\e\fR'. +.PP +Class-shorthand escapes (AREs only) provide shorthands for certain commonly-used +character classes: +.RS 2 +.TP 10 +\fB\ed\fR +\fB[[:digit:]]\fR +.TP +\fB\es\fR +\fB[[:space:]]\fR +.TP +\fB\ew\fR +\fB[[:alnum:]_]\fR +(note underscore) +.TP +\fB\eD\fR +\fB[^[:digit:]]\fR +.TP +\fB\eS\fR +\fB[^[:space:]]\fR +.TP +\fB\eW\fR +\fB[^[:alnum:]_]\fR +(note underscore) +.RE +.PP +Within bracket expressions, `\fB\ed\fR', `\fB\es\fR', +and `\fB\ew\fR'\& +lose their outer brackets, +and `\fB\eD\fR', `\fB\eS\fR', +and `\fB\eW\fR'\& +are illegal. +.VS 8.2 +(So, for example, \fB[a-c\ed]\fR is equivalent to \fB[a-c[:digit:]]\fR. +Also, \fB[a-c\eD]\fR, which is equivalent to \fB[a-c^[:digit:]]\fR, is illegal.) +.VE 8.2 +.PP +A constraint escape (AREs only) is a constraint, +matching the empty string if specific conditions are met, +written as an escape: +.RS 2 +.TP 6 +\fB\eA\fR +matches only at the beginning of the string +(see MATCHING, below, for how this differs from `\fB^\fR') +.TP +\fB\em\fR +matches only at the beginning of a word +.TP +\fB\eM\fR +matches only at the end of a word +.TP +\fB\ey\fR +matches only at the beginning or end of a word +.TP +\fB\eY\fR +matches only at a point that is not the beginning or end of a word +.TP +\fB\eZ\fR +matches only at the end of the string +(see MATCHING, below, for how this differs from `\fB$\fR') +.TP +\fB\e\fIm\fR +(where +\fIm\fR +is a nonzero digit) a \fIback reference\fR, see below +.TP +\fB\e\fImnn\fR +(where +\fIm\fR +is a nonzero digit, and +\fInn\fR +is some more digits, +and the decimal value +\fImnn\fR +is not greater than the number of closing capturing parentheses seen so far) +a \fIback reference\fR, see below +.RE +.PP +A word is defined as in the specification of +\fB[[:<:]]\fR +and +\fB[[:>:]]\fR +above. +Constraint escapes are illegal within bracket expressions. +.PP +A back reference (AREs only) matches the same string matched by the parenthesized +subexpression specified by the number, +so that (e.g.) +\fB([bc])\e1\fR +matches +\fBbb\fR +or +\fBcc\fR +but not `\fBbc\fR'. +The subexpression must entirely precede the back reference in the RE. +Subexpressions are numbered in the order of their leading parentheses. +Non-capturing parentheses do not define subexpressions. +.PP +There is an inherent historical ambiguity between octal character-entry +escapes and back references, which is resolved by heuristics, +as hinted at above. +A leading zero always indicates an octal escape. +A single non-zero digit, not followed by another digit, +is always taken as a back reference. +A multi-digit sequence not starting with a zero is taken as a back +reference if it comes after a suitable subexpression +(i.e. the number is in the legal range for a back reference), +and otherwise is taken as octal. +.SH "METASYNTAX" +In addition to the main syntax described above, there are some special +forms and miscellaneous syntactic facilities available. +.PP +Normally the flavor of RE being used is specified by +application-dependent means. +However, this can be overridden by a \fIdirector\fR. +If an RE of any flavor begins with `\fB***:\fR', +the rest of the RE is an ARE. +If an RE of any flavor begins with `\fB***=\fR', +the rest of the RE is taken to be a literal string, +with all characters considered ordinary characters. +.PP +An ARE may begin with \fIembedded options\fR: +a sequence +\fB(?\fIxyz\fB)\fR +(where +\fIxyz\fR +is one or more alphabetic characters) +specifies options affecting the rest of the RE. +These supplement, and can override, +any options specified by the application. +The available option letters are: +.RS 2 +.TP 3 +\fBb\fR +rest of RE is a BRE +.TP 3 +\fBc\fR +case-sensitive matching (usual default) +.TP 3 +\fBe\fR +rest of RE is an ERE +.TP 3 +\fBi\fR +case-insensitive matching (see MATCHING, below) +.TP 3 +\fBm\fR +historical synonym for +\fBn\fR +.TP 3 +\fBn\fR +newline-sensitive matching (see MATCHING, below) +.TP 3 +\fBp\fR +partial newline-sensitive matching (see MATCHING, below) +.TP 3 +\fBq\fR +rest of RE is a literal (``quoted'') string, all ordinary characters +.TP 3 +\fBs\fR +non-newline-sensitive matching (usual default) +.TP 3 +\fBt\fR +tight syntax (usual default; see below) +.TP 3 +\fBw\fR +inverse partial newline-sensitive (``weird'') matching (see MATCHING, below) +.TP 3 +\fBx\fR +expanded syntax (see below) +.RE +.PP +Embedded options take effect at the +\fB)\fR +terminating the sequence. +They are available only at the start of an ARE, +and may not be used later within it. +.PP +In addition to the usual (\fItight\fR) RE syntax, in which all characters are +significant, there is an \fIexpanded\fR syntax, +available in all flavors of RE +with the \fB-expanded\fR switch, or in AREs with the embedded x option. +In the expanded syntax, +white-space characters are ignored +and all characters between a +\fB#\fR +and the following newline (or the end of the RE) are ignored, +permitting paragraphing and commenting a complex RE. +There are three exceptions to that basic rule: +.RS 2 +.PP +a white-space character or `\fB#\fR' preceded by `\fB\e\fR' is retained +.PP +white space or `\fB#\fR' within a bracket expression is retained +.PP +white space and comments are illegal within multi-character symbols +like the ARE `\fB(?:\fR' or the BRE `\fB\e(\fR' +.RE +.PP +Expanded-syntax white-space characters are blank, tab, newline, and +.VS 8.2 +any character that belongs to the \fIspace\fR character class. +.VE 8.2 +.PP +Finally, in an ARE, +outside bracket expressions, the sequence `\fB(?#\fIttt\fB)\fR' +(where +\fIttt\fR +is any text not containing a `\fB)\fR') +is a comment, +completely ignored. +Again, this is not allowed between the characters of +multi-character symbols like `\fB(?:\fR'. +Such comments are more a historical artifact than a useful facility, +and their use is deprecated; +use the expanded syntax instead. +.PP +\fINone\fR of these metasyntax extensions is available if the application +(or an initial +\fB***=\fR +director) +has specified that the user's input be treated as a literal string +rather than as an RE. +.SH MATCHING +In the event that an RE could match more than one substring of a given +string, +the RE matches the one starting earliest in the string. +If the RE could match more than one substring starting at that point, +its choice is determined by its \fIpreference\fR: +either the longest substring, or the shortest. +.PP +Most atoms, and all constraints, have no preference. +A parenthesized RE has the same preference (possibly none) as the RE. +A quantified atom with quantifier +\fB{\fIm\fB}\fR +or +\fB{\fIm\fB}?\fR +has the same preference (possibly none) as the atom itself. +A quantified atom with other normal quantifiers (including +\fB{\fIm\fB,\fIn\fB}\fR +with +\fIm\fR +equal to +\fIn\fR) +prefers longest match. +A quantified atom with other non-greedy quantifiers (including +\fB{\fIm\fB,\fIn\fB}?\fR +with +\fIm\fR +equal to +\fIn\fR) +prefers shortest match. +A branch has the same preference as the first quantified atom in it +which has a preference. +An RE consisting of two or more branches connected by the +\fB|\fR +operator prefers longest match. +.PP +Subject to the constraints imposed by the rules for matching the whole RE, +subexpressions also match the longest or shortest possible substrings, +based on their preferences, +with subexpressions starting earlier in the RE taking priority over +ones starting later. +Note that outer subexpressions thus take priority over +their component subexpressions. +.PP +Note that the quantifiers +\fB{1,1}\fR +and +\fB{1,1}?\fR +can be used to force longest and shortest preference, respectively, +on a subexpression or a whole RE. +.PP +Match lengths are measured in characters, not collating elements. +An empty string is considered longer than no match at all. +For example, +\fBbb*\fR +matches the three middle characters of `\fBabbbc\fR', +\fB(week|wee)(night|knights)\fR +matches all ten characters of `\fBweeknights\fR', +when +\fB(.*).*\fR +is matched against +\fBabc\fR +the parenthesized subexpression +matches all three characters, and +when +\fB(a*)*\fR +is matched against +\fBbc\fR +both the whole RE and the parenthesized +subexpression match an empty string. +.PP +If case-independent matching is specified, +the effect is much as if all case distinctions had vanished from the +alphabet. +When an alphabetic that exists in multiple cases appears as an +ordinary character outside a bracket expression, it is effectively +transformed into a bracket expression containing both cases, +so that +\fBx\fR +becomes `\fB[xX]\fR'. +When it appears inside a bracket expression, all case counterparts +of it are added to the bracket expression, so that +\fB[x]\fR +becomes +\fB[xX]\fR +and +\fB[^x]\fR +becomes `\fB[^xX]\fR'. +.PP +If newline-sensitive matching is specified, \fB.\fR +and bracket expressions using +\fB^\fR +will never match the newline character +(so that matches will never cross newlines unless the RE +explicitly arranges it) +and +\fB^\fR +and +\fB$\fR +will match the empty string after and before a newline +respectively, in addition to matching at beginning and end of string +respectively. +ARE +\fB\eA\fR +and +\fB\eZ\fR +continue to match beginning or end of string \fIonly\fR. +.PP +If partial newline-sensitive matching is specified, +this affects \fB.\fR +and bracket expressions +as with newline-sensitive matching, but not +\fB^\fR +and `\fB$\fR'. +.PP +If inverse partial newline-sensitive matching is specified, +this affects +\fB^\fR +and +\fB$\fR +as with +newline-sensitive matching, +but not \fB.\fR +and bracket expressions. +This isn't very useful but is provided for symmetry. +.SH "LIMITS AND COMPATIBILITY" +No particular limit is imposed on the length of REs. +Programs intended to be highly portable should not employ REs longer +than 256 bytes, +as a POSIX-compliant implementation can refuse to accept such REs. +.PP +The only feature of AREs that is actually incompatible with +POSIX EREs is that +\fB\e\fR +does not lose its special +significance inside bracket expressions. +All other ARE features use syntax which is illegal or has +undefined or unspecified effects in POSIX EREs; +the +\fB***\fR +syntax of directors likewise is outside the POSIX +syntax for both BREs and EREs. +.PP +Many of the ARE extensions are borrowed from Perl, but some have +been changed to clean them up, and a few Perl extensions are not present. +Incompatibilities of note include `\fB\eb\fR', `\fB\eB\fR', +the lack of special treatment for a trailing newline, +the addition of complemented bracket expressions to the things +affected by newline-sensitive matching, +the restrictions on parentheses and back references in lookahead constraints, +and the longest/shortest-match (rather than first-match) matching semantics. +.PP +The matching rules for REs containing both normal and non-greedy quantifiers +have changed since early beta-test versions of this package. +(The new rules are much simpler and cleaner, +but don't work as hard at guessing the user's real intentions.) +.PP +Henry Spencer's original 1986 \fIregexp\fR package, +still in widespread use (e.g., in pre-8.1 releases of Tcl), +implemented an early version of today's EREs. +There are four incompatibilities between \fIregexp\fR's near-EREs +(`RREs' for short) and AREs. +In roughly increasing order of significance: +.PP +.RS +In AREs, +\fB\e\fR +followed by an alphanumeric character is either an +escape or an error, +while in RREs, it was just another way of writing the +alphanumeric. +This should not be a problem because there was no reason to write +such a sequence in RREs. +.PP +\fB{\fR +followed by a digit in an ARE is the beginning of a bound, +while in RREs, +\fB{\fR +was always an ordinary character. +Such sequences should be rare, +and will often result in an error because following characters +will not look like a valid bound. +.PP +In AREs, +\fB\e\fR +remains a special character within `\fB[\|]\fR', +so a literal +\fB\e\fR +within +\fB[\|]\fR +must be written `\fB\e\e\fR'. +\fB\e\e\fR +also gives a literal +\fB\e\fR +within +\fB[\|]\fR +in RREs, +but only truly paranoid programmers routinely doubled the backslash. +.PP +AREs report the longest/shortest match for the RE, +rather than the first found in a specified search order. +This may affect some RREs which were written in the expectation that +the first match would be reported. +(The careful crafting of RREs to optimize the search order for fast +matching is obsolete (AREs examine all possible matches +in parallel, and their performance is largely insensitive to their +complexity) but cases where the search order was exploited to deliberately +find a match which was \fInot\fR the longest/shortest will need rewriting.) +.RE + +.SH "BASIC REGULAR EXPRESSIONS" +BREs differ from EREs in several respects. `\fB|\fR', `\fB+\fR', +and +\fB?\fR +are ordinary characters and there is no equivalent +for their functionality. +The delimiters for bounds are +\fB\e{\fR +and `\fB\e}\fR', +with +\fB{\fR +and +\fB}\fR +by themselves ordinary characters. +The parentheses for nested subexpressions are +\fB\e(\fR +and `\fB\e)\fR', +with +\fB(\fR +and +\fB)\fR +by themselves ordinary characters. +\fB^\fR +is an ordinary character except at the beginning of the +RE or the beginning of a parenthesized subexpression, +\fB$\fR +is an ordinary character except at the end of the +RE or the end of a parenthesized subexpression, +and +\fB*\fR +is an ordinary character if it appears at the beginning of the +RE or the beginning of a parenthesized subexpression +(after a possible leading `\fB^\fR'). +Finally, +single-digit back references are available, +and +\fB\e<\fR +and +\fB\e>\fR +are synonyms for +\fB[[:<:]]\fR +and +\fB[[:>:]]\fR +respectively; +no other escapes are available. + +.SH "SEE ALSO" +RegExp(3), regexp(n), regsub(n), lsearch(n), switch(n), text(n) + +.SH KEYWORDS +match, regular expression, string diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/read.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/read.n new file mode 100644 index 0000000000000000000000000000000000000000..46829815f731721be85f8dab052d6795a7b88178 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/read.n @@ -0,0 +1,58 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: read.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH read n 8.1 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +read \- Read from a channel +.SH SYNOPSIS +\fBread \fR?\fB\-nonewline\fR? \fIchannelId\fR +.sp +\fBread \fIchannelId numChars\fR +.BE + +.SH DESCRIPTION +.PP +In the first form, the \fBread\fR command reads all of the data from +\fIchannelId\fR up to the end of the file. +If the \fB\-nonewline\fR switch is specified then the last character +of the file is discarded if it is a newline. +.VS 8.1 +In the second form, the extra argument specifies how many characters to +read. Exactly that many characters will be read and returned, unless +there are fewer than \fInumChars\fR left in the file; in this case +all the remaining characters are returned. If the channel is +configured to use a multi-byte encoding, then the number of characters +read may not be the same as the number of bytes read. +.PP +If \fIchannelId\fR is in nonblocking mode, the command may not read as +many characters as requested: once all available input has been read, +the command will return the data that is available rather than +blocking for more input. If the channel is configured to use a +multi-byte encoding, then there may actually be some bytes remaining +in the internal buffers that do not form a complete character. These +bytes will not be returned until a complete character is available or +end-of-file is reached. +.VE 8.1 +The \fB\-nonewline\fR switch is ignored if the command returns +before reaching the end of the file. +.PP +\fBRead\fR translates end-of-line sequences in the input into +newline characters according to the \fB\-translation\fR option +for the channel. +See the \fBfconfigure\fR manual entry for a discussion on ways in +which \fBfconfigure\fR will alter input. + +.SH "SEE ALSO" +file(n), eof(n), fblocked(n), fconfigure(n) + +.SH KEYWORDS +blocking, channel, end of line, end of file, nonblocking, read, translation, encoding diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/regexp.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/regexp.n new file mode 100644 index 0000000000000000000000000000000000000000..e62db12a137702362ce6aec3c825fe359ca6a8aa --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/regexp.n @@ -0,0 +1,133 @@ +'\" +'\" Copyright (c) 1998 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: regexp.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH regexp n 8.3 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +regexp \- Match a regular expression against a string + +.SH SYNOPSIS +\fBregexp \fR?\fIswitches\fR? \fIexp string \fR?\fImatchVar\fR? ?\fIsubMatchVar subMatchVar ...\fR? +.BE + +.SH DESCRIPTION +.PP +Determines whether the regular expression \fIexp\fR matches part or +all of \fIstring\fR and returns 1 if it does, 0 if it doesn't, unless +\fB-inline\fR is specified (see below). +(Regular expression matching is described in the \fBre_syntax\fR +reference page.) +.LP +If additional arguments are specified after \fIstring\fR then they +are treated as the names of variables in which to return +information about which part(s) of \fIstring\fR matched \fIexp\fR. +\fIMatchVar\fR will be set to the range of \fIstring\fR that +matched all of \fIexp\fR. The first \fIsubMatchVar\fR will contain +the characters in \fIstring\fR that matched the leftmost parenthesized +subexpression within \fIexp\fR, the next \fIsubMatchVar\fR will +contain the characters that matched the next parenthesized +subexpression to the right in \fIexp\fR, and so on. +.PP +If the initial arguments to \fBregexp\fR start with \fB\-\fR then +they are treated as switches. The following switches are +currently supported: +.TP 15 +\fB\-about\fR +Instead of attempting to match the regular expression, returns a list +containing information about the regular expression. The first +element of the list is a subexpression count. The second element is a +list of property names that describe various attributes of the regular +expression. This switch is primarily intended for debugging purposes. +.TP 15 +\fB\-expanded\fR +Enables use of the expanded regular expression syntax where +whitespace and comments are ignored. This is the same as specifying +the \fB(?x)\fR embedded option (see METASYNTAX, below). +.TP 15 +\fB\-indices\fR +Changes what is stored in the \fIsubMatchVar\fRs. +Instead of storing the matching characters from \fIstring\fR, +each variable +will contain a list of two decimal strings giving the indices +in \fIstring\fR of the first and last characters in the matching +range of characters. +.TP 15 +\fB\-line\fR +Enables newline-sensitive matching. By default, newline is a +completely ordinary character with no special meaning. With this +flag, `[^' bracket expressions and `.' never match newline, `^' +matches an empty string after any newline in addition to its normal +function, and `$' matches an empty string before any newline in +addition to its normal function. This flag is equivalent to +specifying both \fB\-linestop\fR and \fB\-lineanchor\fR, or the +\fB(?n)\fR embedded option (see METASYNTAX, below). +.TP 15 +\fB\-linestop\fR +Changes the behavior of `[^' bracket expressions and `.' so that they +stop at newlines. This is the same as specifying the \fB(?p)\fR +embedded option (see METASYNTAX, below). +.TP 15 +\fB\-lineanchor\fR +Changes the behavior of `^' and `$' (the ``anchors'') so they match the +beginning and end of a line respectively. This is the same as +specifying the \fB(?w)\fR embedded option (see METASYNTAX, below). +.TP 15 +\fB\-nocase\fR +Causes upper-case characters in \fIstring\fR to be treated as +lower case during the matching process. +.VS 8.3 +.TP 15 +\fB\-all\fR +Causes the regular expression to be matched as many times as possible +in the string, returning the total number of matches found. If this +is specified with match variables, they will continue information for +the last match only. +.TP 15 +\fB\-inline\fR +Causes the command to return, as a list, the data that would otherwise +be placed in match variables. When using \fB-inline\fR, +match variables may not be specified. If used with \fB-all\fR, the +list will be concatenated at each iteration, such that a flat list is +always returned. For each match iteration, the command will append the +overall match data, plus one element for each subexpression in the +regular expression. Examples are: +.CS + regexp -inline -- {\\w(\\w)} " inlined " + => {in n} + regexp -all -inline -- {\\w(\\w)} " inlined " + => {in n li i ne e} +.CE +.TP 15 +\fB\-start\fR \fIindex\fR +Specifies a character index offset into the string to start +matching the regular expression at. When using this switch, `^' +will not match the beginning of the line, and \\A will still +match the start of the string at \fIindex\fR. If \fB\-indices\fR +is specified, the indices will be indexed starting from the +absolute beginning of the input string. +\fIindex\fR will be constrained to the bounds of the input string. +.VE 8.3 +.TP 15 +\fB\-\|\-\fR +Marks the end of switches. The argument following this one will +be treated as \fIexp\fR even if it starts with a \fB\-\fR. +.PP +If there are more \fIsubMatchVar\fR's than parenthesized +subexpressions within \fIexp\fR, or if a particular subexpression +in \fIexp\fR doesn't match the string (e.g. because it was in a +portion of the expression that wasn't matched), then the corresponding +\fIsubMatchVar\fR will be set to ``\fB\-1 \-1\fR'' if \fB\-indices\fR +has been specified or to an empty string otherwise. + +.SH "SEE ALSO" +re_syntax(n), regsub(n) + +.SH KEYWORDS +match, regular expression, string diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/registry.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/registry.n new file mode 100644 index 0000000000000000000000000000000000000000..98a107ed6be6a9afdfa81b801beb35d3321754fa --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/registry.n @@ -0,0 +1,168 @@ +'\" +'\" Copyright (c) 1997 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: registry.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH registry n 8.0 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +registry \- Manipulate the Windows registry +.SH SYNOPSIS +.sp +\fBpackage require registry 1.0\fR +.sp +\fBregistry \fIoption\fR \fIkeyName\fR ?\fIarg arg ...\fR? +.BE + +.SH DESCRIPTION +.PP +The \fBregistry\fR package provides a general set of operations for +manipulating the Windows registry. The package implements the +\fBregistry\fR Tcl command. This command is only supported on the +Windows platform. Warning: this command should be used with caution +as a corrupted registry can leave your system in an unusable state. +.PP +\fIKeyName\fR is the name of a registry key. Registry keys must be +one of the following forms: +.IP +\fB\e\e\fIhostname\fB\e\fIrootname\fB\e\fIkeypath\fR +.IP +\fIrootname\fB\e\fIkeypath\fR +.IP +\fIrootname\fR +.PP +\fIHostname\fR specifies the name of any valid Windows +host that exports its registry. The \fIrootname\fR component must be +one of \fBHKEY_LOCAL_MACHINE\fR, \fBHKEY_USERS\fR, +.VS +\fBHKEY_CLASSES_ROOT\fR, \fBHKEY_CURRENT_USER\fR, +\fBHKEY_CURRENT_CONFIG\fR, \fBHKEY_PERFORMANCE_DATA\fR, or +\fBHKEY_DYN_DATA\fR. The \fIkeypath\fR can be one or more +.VE +registry key names separated by backslash (\fB\e\fR) characters. +.PP +\fIOption\fR indicates what to do with the registry key name. Any +unique abbreviation for \fIoption\fR is acceptable. The valid options +are: +.TP +\fBregistry delete \fIkeyName\fR ?\fIvalueName\fR? +. +If the optional \fIvalueName\fR argument is present, the specified +value under \fIkeyName\fR will be deleted from the registry. If the +optional \fIvalueName\fR is omitted, the specified key and any subkeys +or values beneath it in the registry heirarchy will be deleted. If +the key could not be deleted then an error is generated. If the key +did not exist, the command has no effect. +.TP +\fBregistry get \fIkeyName valueName\fR +. +Returns the data associated with the value \fIvalueName\fR under the key +\fIkeyName\fR. If either the key or the value does not exist, then an +error is generated. For more details on the format of the returned +data, see SUPPORTED TYPES, below. +.TP +\fBregistry keys \fIkeyName\fR ?\fIpattern\fR? +. +If \fIpattern\fR isn't specified, returns a list of names of all the +subkeys of \fIkeyName\fR. If \fIpattern\fR is specified, only those +names matching \fIpattern\fR are returned. Matching is determined +using the same rules as for \fBstring\fR \fBmatch\fR. If the +specified \fIkeyName\fR does not exist, then an error is generated. +.TP +\fBregistry set \fIkeyName\fR ?\fIvalueName data \fR?\fItype\fR?? +. +If \fIvalueName\fR isn't specified, creates the key \fIkeyName\fR if +it doesn't already exist. If \fIvalueName\fR is specified, creates +the key \fIkeyName\fR and value \fIvalueName\fR if necessary. The +contents of \fIvalueName\fR are set to \fIdata\fR with the type +indicated by \fItype\fR. If \fItype\fR isn't specified, the type +\fBsz\fR is assumed. For more details on the data and type arguments, +see SUPPORTED TYPES below. +.TP +\fBregistry type \fIkeyName valueName\fR +. +Returns the type of the value \fIvalueName\fR in the key +\fIkeyName\fR. For more information on the possible types, see +SUPPORTED TYPES, below. +.TP +\fBregistry values \fIkeyName\fR ?\fIpattern\fR? +. +If \fIpattern\fR isn't specified, returns a list of names of all the +values of \fIkeyName\fR. If \fIpattern\fR is specified, only those +names matching \fIpattern\fR are returned. Matching is determined +using the same rules as for \fBstring\fR \fBmatch\fR. + +.SH "SUPPORTED TYPES" +Each value under a key in the registry contains some data of a +particular type in a type-specific representation. The \fBregistry\fR +command converts between this internal representation and one that can +be manipulated by Tcl scripts. In most cases, the data is simply +returned as a Tcl string. The type indicates the intended use for the +data, but does not actually change the representation. For some +types, the \fBregistry\fR command returns the data in a different form to +make it easier to manipulate. The following types are recognized by the +registry command: +.TP 17 +\fBbinary\fR +. +The registry value contains arbitrary binary data. The data is represented +exactly in Tcl, including any embedded nulls. +.TP +\fBnone\fR +. +The registry value contains arbitrary binary data with no defined +type. The data is represented exactly in Tcl, including any embedded +nulls. +.TP +\fBsz\fR +. +The registry value contains a null-terminated string. The data is +represented in Tcl as a string. +.TP +\fBexpand_sz\fR +. +The registry value contains a null-terminated string that contains +unexpanded references to environment variables in the normal Windows +style (for example, "%PATH%"). The data is represented in Tcl as a +string. +.TP +\fBdword\fR +. +The registry value contains a little-endian 32-bit number. The data is +represented in Tcl as a decimal string. +.TP +\fBdword_big_endian\fR +. +The registry value contains a big-endian 32-bit number. The data is +represented in Tcl as a decimal string. +.TP +\fBlink\fR +. +The registry value contains a symbolic link. The data is represented +exactly in Tcl, including any embedded nulls. +.TP +\fBmulti_sz\fR +. +The registry value contains an array of null-terminated strings. The +data is represented in Tcl as a list of strings. +.TP +\fBresource_list\fR +. +The registry value contains a device-driver resource list. The data +is represented exactly in Tcl, including any embedded nulls. +.PP +In addition to the symbolically named types listed above, unknown +types are identified using a 32-bit integer that corresponds to the +type code returned by the system interfaces. In this case, the data +is represented exactly in Tcl, including any embedded nulls. + +.SH "PORTABILITY ISSUES" +The registry command is only available on Windows. + +.SH KEYWORDS +registry diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/regsub.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/regsub.n new file mode 100644 index 0000000000000000000000000000000000000000..f8c8ec4178fa71c704ed06406d021f8e3f1343cb --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/regsub.n @@ -0,0 +1,112 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" Copyright (c) 2000 Scriptics Corporation. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: regsub.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH regsub n 8.3 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +regsub \- Perform substitutions based on regular expression pattern matching +.SH SYNOPSIS +\fBregsub \fR?\fIswitches\fR? \fIexp string subSpec varName\fR +.BE + +.SH DESCRIPTION +.PP +This command matches the regular expression \fIexp\fR against +\fIstring\fR, +and it copies \fIstring\fR to the variable whose name is +given by \fIvarName\fR. +(Regular expression matching is described in the \fBre_syntax\fR +reference page.) +If there is a match, then while copying \fIstring\fR to \fIvarName\fR +the portion of \fIstring\fR that +matched \fIexp\fR is replaced with \fIsubSpec\fR. +If \fIsubSpec\fR contains a ``&'' or ``\e0'', then it is replaced +in the substitution with the portion of \fIstring\fR that +matched \fIexp\fR. +If \fIsubSpec\fR contains a ``\e\fIn\fR'', where \fIn\fR is a digit +between 1 and 9, then it is replaced in the substitution with +the portion of \fIstring\fR that matched the \fIn\fR-th +parenthesized subexpression of \fIexp\fR. +Additional backslashes may be used in \fIsubSpec\fR to prevent special +interpretation of ``&'' or ``\e0'' or ``\e\fIn\fR'' or +backslash. +The use of backslashes in \fIsubSpec\fR tends to interact badly +with the Tcl parser's use of backslashes, so it's generally +safest to enclose \fIsubSpec\fR in braces if it includes +backslashes. +.LP +If the initial arguments to \fBregexp\fR start with \fB\-\fR then +they are treated as switches. The following switches are +currently supported: +.TP 10 +\fB\-all\fR +All ranges in \fIstring\fR that match \fIexp\fR are found and +substitution is performed for each of these ranges. +Without this switch only the first +matching range is found and substituted. +If \fB\-all\fR is specified, then ``&'' and ``\e\fIn\fR'' +sequences are handled for each substitution using the information +from the corresponding match. +.TP 15 +\fB\-expanded\fR +Enables use of the expanded regular expression syntax where +whitespace and comments are ignored. This is the same as specifying +the \fB(?x)\fR embedded option (see METASYNTAX, below). +.TP 15 +\fB\-line\fR +Enables newline-sensitive matching. By default, newline is a +completely ordinary character with no special meaning. With this +flag, `[^' bracket expressions and `.' never match newline, `^' +matches an empty string after any newline in addition to its normal +function, and `$' matches an empty string before any newline in +addition to its normal function. This flag is equivalent to +specifying both \fB\-linestop\fR and \fB\-lineanchor\fR, or the +\fB(?n)\fR embedded option (see METASYNTAX, below). +.TP 15 +\fB\-linestop\fR +Changes the behavior of `[^' bracket expressions and `.' so that they +stop at newlines. This is the same as specifying the \fB(?p)\fR +embedded option (see METASYNTAX, below). +.TP 15 +\fB\-lineanchor\fR +Changes the behavior of `^' and `$' (the ``anchors'') so they match the +beginning and end of a line respectively. This is the same as +specifying the \fB(?w)\fR embedded option (see METASYNTAX, below). +.TP 10 +\fB\-nocase\fR +Upper-case characters in \fIstring\fR will be converted to lower-case +before matching against \fIexp\fR; however, substitutions specified +by \fIsubSpec\fR use the original unconverted form of \fIstring\fR. +.VS 8.3 +.TP 10 +\fB\-start\fR \fIindex\fR +Specifies a character index offset into the string to start +matching the regular expression at. When using this switch, `^' +will not match the beginning of the line, and \\A will still +match the start of the string at \fIindex\fR. +\fIindex\fR will be constrained to the bounds of the input string. +.VE 8.3 +.TP 10 +\fB\-\|\-\fR +Marks the end of switches. The argument following this one will +be treated as \fIexp\fR even if it starts with a \fB\-\fR. +.PP +The command returns a count of the number of matching ranges that +were found and replaced. +See the manual entry for \fBregexp\fR for details on the interpretation +of regular expressions. + +.SH "SEE ALSO" +regexp(n), re_syntax(n) + +.SH KEYWORDS +match, pattern, regular expression, substitute diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/rename.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/rename.n new file mode 100644 index 0000000000000000000000000000000000000000..ca666177805481767f7df98b9cea30d27833ff5b --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/rename.n @@ -0,0 +1,35 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1997 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: rename.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH rename n "" Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +rename \- Rename or delete a command +.SH SYNOPSIS +\fBrename \fIoldName newName\fR +.BE + +.SH DESCRIPTION +.PP +Rename the command that used to be called \fIoldName\fR so that it +is now called \fInewName\fR. +If \fInewName\fR is an empty string then \fIoldName\fR is deleted. +\fIoldName\fR and \fInewName\fR may include namespace qualifiers +(names of containing namespaces). +If a command is renamed into a different namespace, +future invocations of it will execute in the new namespace. +The \fBrename\fR command returns an empty string as result. + +.SH "SEE ALSO" +namespace(n), proc(n) + +.SH KEYWORDS +command, delete, namespace, rename diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/resource.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/resource.n new file mode 100644 index 0000000000000000000000000000000000000000..06cfffcc21d40aa955314cb8fe4898da095707ba --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/resource.n @@ -0,0 +1,155 @@ +'\" +'\" Copyright (c) 1997 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" RCS: @(#) $Id: resource.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH resource n 8.0 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +resource \- Manipulate Macintosh resources +.SH SYNOPSIS +\fBresource \fIoption\fR ?\fIarg arg ...\fR? +.BE + +.SH DESCRIPTION +.PP +The \fBresource\fR command provides some generic operations for +dealing with Macintosh resources. This command is only supported on +the Macintosh platform. Each Macintosh file consists of two +\fIforks\fR: a \fIdata\fR fork and a \fIresource\fR fork. You use the +normal open, puts, close, etc. commands to manipulate the data fork. +You must use this command, however, to interact with the resource +fork. \fIOption\fR indicates what resource command to perform. Any +unique abbreviation for \fIoption\fR is acceptable. The valid options +are: +.TP +\fBresource close \fIrsrcRef\fR +Closes the given resource reference (obtained from \fBresource +open\fR). Resources from that resource file will no longer be +available. +.TP +\fBresource delete\fR ?\fIoptions\fR? \fIresourceType\fR +This command will delete the resource specified by \fIoptions\fR and +type \fIresourceType\fR (see RESOURCE TYPES below). The options +give you several ways to specify the resource to be deleted. +.RS +.TP +\fB\-id\fR \fIresourceId\fR +If the \fB-id\fR option is given the id \fIresourceId\fR (see RESOURCE +IDS below) is used to specify the resource to be deleted. The id must +be a number - to specify a name use the \fB\-name\fR option. +.TP +\fB\-name\fR \fIresourceName\fR +If \fB-name\fR is specified, the resource named +\fIresourceName\fR will be deleted. If the \fB-id\fR is also +provided, then there must be a resource with BOTH this name and +this id. If no name is provided, then the id will be used regardless +of the name of the actual resource. +.TP +\fB\-file\fR \fIresourceRef\fR +If the \fB-file\fR option is specified then the resource will be +deleted from the file pointed to by \fIresourceRef\fR. Otherwise the +first resource with the given \fIresourceName\fR and or +\fIresourceId\fR which is found on the resource file path will be +deleted. To inspect the file path, use the \fIresource files\fR command. +.RE +.TP +\fBresource files ?\fIresourceRef\fR? +If \fIresourceRef\fRis not provided, this command returns a Tcl list +of the resource references for all the currently open resource files. +The list is in the normal Macintosh search order for resources. If +\fIresourceRef\fR is specified, the command will +return the path to the file whose resource fork is represented by that +token. +.TP +\fBresource list \fIresourceType\fR ?\fIresourceRef\fR? +List all of the resources ids of type \fIresourceType\fR (see RESOURCE +TYPES below). If \fIresourceRef\fR is specified then the command will +limit the search to that particular resource file. Otherwise, all +resource files currently opened by the application will be searched. +A Tcl list of either the resource name's or resource id's of the found +resources will be returned. See the RESOURCE IDS section below for +more details about what a resource id is. +.TP +\fBresource open \fIfileName\fR ?\fIaccess\fR? +Open the resource for the file \fIfileName\fR. Standard file access +permissions may also be specified (see the manual entry for \fBopen\fR +for details). A resource reference (\fIresourceRef\fR) is returned +that can be used by the other resource commands. An error can occur +if the file doesn't exist or the file does not have a resource fork. +However, if you open the file with write permissions the file and/or +resource fork will be created instead of generating an error. +.TP +\fBresource read \fIresourceType\fR \fIresourceId\fR ?\fIresourceRef\fR? +Read the entire resource of type \fIresourceType\fR (see RESOURCE +TYPES below) and the name or id of \fIresourceId\fR (see RESOURCE IDS +below) into memory and return the result. If \fIresourceRef\fR is +specified we limit our search to that resource file, otherwise we +search all open resource forks in the application. It is important to +note that most Macintosh resource use a binary format and the data +returned from this command may have embedded NULLs or other non-ASCII +data. +.TP +\fBresource types ?\fIresourceRef\fR? +This command returns a Tcl list of all resource types (see RESOURCE +TYPES below) found in the resource file pointed to by +\fIresourceRef\fR. If \fIresourceRef\fR is not specified it will +return all the resource types found in every resource file currently +opened by the application. +.TP +\fBresource write\fR ?\fIoptions\fR? \fIresourceType\fR \fIdata\fR +This command will write the passed in \fIdata\fR as a new resource of +type \fIresourceType\fR (see RESOURCE TYPES below). Several options +are available that describe where and how the resource is stored. +.RS +.TP +\fB\-id\fR \fIresourceId\fR +If the \fB-id\fR option is given the id \fIresourceId\fR (see RESOURCE +IDS below) is used for the new resource, otherwise a unique id will be +generated that will not conflict with any existing resource. However, +the id must be a number - to specify a name use the \fB\-name\fR option. +.TP +\fB\-name\fR \fIresourceName\fR +If \fB-name\fR is specified the resource will be named +\fIresourceName\fR, otherwise it will have the empty string as the +name. +.TP +\fB\-file\fR \fIresourceRef\fR +If the \fB-file\fR option is specified then the resource will be +written in the file pointed to by \fIresourceRef\fR, otherwise the +most resently open resource will be used. +.TP +\fB\-force\fR +If the target resource already exists, then by default Tcl will not +overwrite it, but raise an error instead. Use the -force flag to +force overwriting the extant resource. +.RE + +.SH "RESOURCE TYPES" +Resource types are defined as a four character string that is then +mapped to an underlying id. For example, \fBTEXT\fR refers to the +Macintosh resource type for text. The type \fBSTR#\fR is a list of +counted strings. All Macintosh resources must be of some type. See +Macintosh documentation for a more complete list of resource types +that are commonly used. + +.SH "RESOURCE IDS" +For this command the notion of a resource id actually refers to two +ideas in Macintosh resources. Every place you can use a resource Id +you can use either the resource name or a resource number. Names are +always searched or returned in preference to numbers. For example, +the \fBresource list\fR command will return names if they exist or +numbers if the name is NULL. + +.SH "PORTABILITY ISSUES" +The resource command is only available on Macintosh. + +.SH "SEE ALSO" +open(n) + +.SH KEYWORDS +open, resource diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/return.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/return.n new file mode 100644 index 0000000000000000000000000000000000000000..edaeabdf360d0b4b177eae7dbb8cb9f9c511bc2e --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/return.n @@ -0,0 +1,92 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: return.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH return n 7.0 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +return \- Return from a procedure +.SH SYNOPSIS +\fBreturn \fR?\fB\-code \fIcode\fR? ?\fB\-errorinfo \fIinfo\fR? ?\fB\-errorcode\fI code\fR? ?\fIstring\fR? +.BE + +.SH DESCRIPTION +.PP +Return immediately from the current procedure +(or top-level command or \fBsource\fR command), +with \fIstring\fR as the return value. If \fIstring\fR is not specified then +an empty string will be returned as result. + +.SH "EXCEPTIONAL RETURNS" +.PP +In the usual case where the \fB\-code\fR option isn't +specified the procedure will return normally (its completion +code will be TCL_OK). +However, the \fB\-code\fR option may be used to generate an +exceptional return from the procedure. +\fICode\fR may have any of the following values: +.TP 10 +\fBok\fR +Normal return: same as if the option is omitted. +.TP 10 +\fBerror\fR +Error return: same as if the \fBerror\fR command were used to +terminate the procedure, except for handling of \fBerrorInfo\fR +and \fBerrorCode\fR variables (see below). +.TP 10 +\fBreturn\fR +The current procedure will return with a completion code of +TCL_RETURN, so that the procedure that invoked it will return +also. +.TP 10 +\fBbreak\fR +The current procedure will return with a completion code of +TCL_BREAK, which will terminate the innermost nested loop in +the code that invoked the current procedure. +.TP 10 +\fBcontinue\fR +The current procedure will return with a completion code of +TCL_CONTINUE, which will terminate the current iteration of +the innermost nested loop in the code that invoked the current +procedure. +.TP 10 +\fIvalue\fR +\fIValue\fR must be an integer; it will be returned as the +completion code for the current procedure. +.LP +The \fB\-code\fR option is rarely used. +It is provided so that procedures that implement +new control structures can reflect exceptional conditions back to +their callers. +.PP +Two additional options, \fB\-errorinfo\fR and \fB\-errorcode\fR, +may be used to provide additional information during error +returns. +These options are ignored unless \fIcode\fR is \fBerror\fR. +.PP +The \fB\-errorinfo\fR option specifies an initial stack +trace for the \fBerrorInfo\fR variable; if it is not specified then +the stack trace left in \fBerrorInfo\fR will include the call to +the procedure and higher levels on the stack but it will not include +any information about the context of the error within the procedure. +Typically the \fIinfo\fR value is supplied from the value left +in \fBerrorInfo\fR after a \fBcatch\fR command trapped an error within +the procedure. +.PP +If the \fB\-errorcode\fR option is specified then \fIcode\fR provides +a value for the \fBerrorCode\fR variable. +If the option is not specified then \fBerrorCode\fR will +default to \fBNONE\fR. + +.SH "SEE ALSO" +break(n), continue(n), error(n), proc(n) + +.SH KEYWORDS +break, continue, error, procedure, return diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/safe.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/safe.n new file mode 100644 index 0000000000000000000000000000000000000000..86aa2454cf4744400bdcb656b0411bcce5d76b01 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/safe.n @@ -0,0 +1,350 @@ +'\" +'\" Copyright (c) 1995-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: safe.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH "Safe Tcl" n 8.0 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +Safe\ Base \- A mechanism for creating and manipulating safe interpreters. +.SH SYNOPSIS +\fB::safe::interpCreate\fR ?\fIslave\fR? ?\fIoptions...\fR? +.sp +\fB::safe::interpInit\fR \fIslave\fR ?\fIoptions...\fR? +.sp +\fB::safe::interpConfigure\fR \fIslave\fR ?\fIoptions...\fR? +.sp +\fB::safe::interpDelete\fR \fIslave\fR +.sp +\fB::safe::interpAddToAccessPath\fR \fIslave\fR \fIdirectory\fR +.sp +\fB::safe::interpFindInAccessPath\fR \fIslave\fR \fIdirectory\fR +.sp +\fB::safe::setLogCmd\fR ?\fIcmd arg...\fR? +.SH OPTIONS +.PP +?\fB\-accessPath\fR \fIpathList\fR? +?\fB\-statics\fR \fIboolean\fR? ?\fB\-noStatics\fR? +?\fB\-nested\fR \fIboolean\fR? ?\fB\-nestedLoadOk\fR? +?\fB\-deleteHook\fR \fIscript\fR? +.BE + +.SH DESCRIPTION +Safe Tcl is a mechanism for executing untrusted Tcl scripts +safely and for providing mediated access by such scripts to +potentially dangerous functionality. +.PP +The Safe Base ensures that untrusted Tcl scripts cannot harm the +hosting application. +The Safe Base prevents integrity and privacy attacks. Untrusted Tcl +scripts are prevented from corrupting the state of the hosting +application or computer. Untrusted scripts are also prevented from +disclosing information stored on the hosting computer or in the +hosting application to any party. +.PP +The Safe Base allows a master interpreter to create safe, restricted +interpreters that contain a set of predefined aliases for the \fBsource\fR, +\fBload\fR, \fBfile\fR, \fBencoding\fR, and \fBexit\fR commands and +are able to use the auto-loading and package mechanisms. +.PP +No knowledge of the file system structure is leaked to the +safe interpreter, because it has access only to a virtualized path +containing tokens. When the safe interpreter requests to source a file, it +uses the token in the virtual path as part of the file name to source; the +master interpreter transparently +translates the token into a real directory name and executes the +requested operation (see the section \fBSECURITY\fR below for details). +Different levels of security can be selected by using the optional flags +of the commands described below. +.PP +All commands provided in the master interpreter by the Safe Base reside in +the \fBsafe\fR namespace: + +.SH COMMANDS +The following commands are provided in the master interpreter: +.TP +\fB::safe::interpCreate\fR ?\fIslave\fR? ?\fIoptions...\fR? +Creates a safe interpreter, installs the aliases described in the section +\fBALIASES\fR and initializes the auto-loading and package mechanism as +specified by the supplied \fBoptions\fR. +See the \fBOPTIONS\fR section below for a description of the +optional arguments. +If the \fIslave\fR argument is omitted, a name will be generated. +\fB::safe::interpCreate\fR always returns the interpreter name. +.TP +\fB::safe::interpInit\fR \fIslave\fR ?\fIoptions...\fR? +This command is similar to \fBinterpCreate\fR except it that does not +create the safe interpreter. \fIslave\fR must have been created by some +other means, like \fBinterp create \-safe\fR. +.TP +\fB::safe::interpConfigure\fR \fIslave\fR ?\fIoptions...\fR? +If no \fIoptions\fR are given, returns the settings for all options for the +named safe interpreter as a list of options and their current values +for that \fIslave\fR. +If a single additional argument is provided, +it will return a list of 2 elements \fIname\fR and \fIvalue\fR where +\fIname\fR is the full name of that option and \fIvalue\fR the current value +for that option and the \fIslave\fR. +If more than two additional arguments are provided, it will reconfigure the +safe interpreter and change each and only the provided options. +See the section on \fBOPTIONS\fR below for options description. +Example of use: +.RS +.CS +# Create a new interp with the same configuration as "$i0" : +set i1 [eval safe::interpCreate [safe::interpConfigure $i0]] +# Get the current deleteHook +set dh [safe::interpConfigure $i0 \-del] +# Change (only) the statics loading ok attribute of an interp +# and its deleteHook (leaving the rest unchanged) : +safe::interpConfigure $i0 \-delete {foo bar} \-statics 0 ; +.CE +.RE +.TP +\fB::safe::interpDelete\fR \fIslave\fR +Deletes the safe interpreter and cleans up the corresponding +master interpreter data structures. +If a \fIdeleteHook\fR script was specified for this interpreter it is +evaluated before the interpreter is deleted, with the name of the +interpreter as an additional argument. +.TP +\fB::safe::interpFindInAccessPath\fR \fIslave\fR \fIdirectory\fR +This command finds and returns the token for the real directory +\fIdirectory\fR in the safe interpreter's current virtual access path. +It generates an error if the directory is not found. +Example of use: +.RS +.CS +$slave eval [list set tk_library [::safe::interpFindInAccessPath $name $tk_library]] +.CE +.RE +.TP +\fB::safe::interpAddToAccessPath\fR \fIslave\fR \fIdirectory\fR +This command adds \fIdirectory\fR to the virtual path maintained for the +safe interpreter in the master, and returns the token that can be used in +the safe interpreter to obtain access to files in that directory. +If the directory is already in the virtual path, it only returns the token +without adding the directory to the virtual path again. +Example of use: +.RS +.CS +$slave eval [list set tk_library [::safe::interpAddToAccessPath $name $tk_library]] +.CE +.RE +.TP +\fB::safe::setLogCmd\fR ?\fIcmd arg...\fR? +This command installs a script that will be called when interesting +life cycle events occur for a safe interpreter. +When called with no arguments, it returns the currently installed script. +When called with one argument, an empty string, the currently installed +script is removed and logging is turned off. +The script will be invoked with one additional argument, a string +describing the event of interest. +The main purpose is to help in debugging safe interpreters. +Using this facility you can get complete error messages while the safe +interpreter gets only generic error messages. +This prevents a safe interpreter from seeing messages about failures +and other events that might contain sensitive information such as real +directory names. +.RS +Example of use: +.CS +::safe::setLogCmd puts stderr +.CE +Below is the output of a sample session in which a safe interpreter +attempted to source a file not found in its virtual access path. +Note that the safe interpreter only received an error message saying that +the file was not found: +.CS +NOTICE for slave interp10 : Created +NOTICE for slave interp10 : Setting accessPath=(/foo/bar) staticsok=1 nestedok=0 deletehook=() +NOTICE for slave interp10 : auto_path in interp10 has been set to {$p(:0:)} +ERROR for slave interp10 : /foo/bar/init.tcl: no such file or directory +.CE +.RE + +.SH OPTIONS +The following options are common to +\fB::safe::interpCreate\fR, \fB::safe::interpInit\fR, +and \fB::safe::interpConfigure\fR. +Any option name can be abbreviated to its minimal +non-ambiguous name. +Option names are not case sensitive. +.TP +\fB\-accessPath\fR \fIdirectoryList\fR +This option sets the list of directories from which the safe interpreter +can \fBsource\fR and \fBload\fR files. +If this option is not specified, or if it is given as the +empty list, the safe interpreter will use the same directories as its +master for auto-loading. +See the section \fBSECURITY\fR below for more detail about virtual paths, +tokens and access control. +.TP +\fB\-statics\fR \fIboolean\fR +This option specifies if the safe interpreter will be allowed +to load statically linked packages (like \fBload {} Tk\fR). +The default value is \fBtrue\fR : +safe interpreters are allowed to load statically linked packages. +.TP +\fB\-noStatics\fR +This option is a convenience shortcut for \fB-statics false\fR and +thus specifies that the safe interpreter will not be allowed +to load statically linked packages. +.TP +\fB\-nested\fR \fIboolean\fR +This option specifies if the safe interpreter will be allowed +to load packages into its own sub-interpreters. +The default value is \fBfalse\fR : +safe interpreters are not allowed to load packages into +their own sub-interpreters. +.TP +\fB\-nestedLoadOk\fR +This option is a convenience shortcut for \fB-nested true\fR and +thus specifies the safe interpreter will be allowed +to load packages into its own sub-interpreters. +.TP +\fB\-deleteHook\fR \fIscript\fR +When this option is given an non empty \fIscript\fR, it will be +evaluated in the master with the name of +the safe interpreter as an additional argument +just before actually deleting the safe interpreter. +Giving an empty value removes any currently installed deletion hook +script for that safe interpreter. +The default value (\fB{}\fR) is not to have any deletion call back. +.SH ALIASES +The following aliases are provided in a safe interpreter: +.TP +\fBsource\fR \fIfileName\fR +The requested file, a Tcl source file, is sourced into the safe interpreter +if it is found. +The \fBsource\fR alias can only source files from directories in +the virtual path for the safe interpreter. The \fBsource\fR alias requires +the safe interpreter to +use one of the token names in its virtual path to denote the directory in +which the file to be sourced can be found. +See the section on \fBSECURITY\fR for more discussion of restrictions on +valid filenames. +.TP +\fBload\fR \fIfileName\fR +The requested file, a shared object file, is dynamically loaded into the +safe interpreter if it is found. +The filename must contain a token name mentioned in the virtual path for +the safe interpreter for it to be found successfully. +Additionally, the shared object file must contain a safe entry point; see +the manual page for the \fBload\fR command for more details. +.TP +\fBfile\fR ?\fIsubCmd args...\fR? +The \fBfile\fR alias provides access to a safe subset of the subcommands of +the \fBfile\fR command; it allows only \fBdirname\fR, \fBjoin\fR, +\fBextension\fR, \fBroot\fR, \fBtail\fR, \fBpathname\fR and \fBsplit\fR +subcommands. For more details on what these subcommands do see the manual +page for the \fBfile\fR command. +.TP +\fBencoding\fR ?\fIsubCmd args...\fR? +The \fBenconding\fR alias provides access to a safe subset of the +subcommands of the \fBencoding\fR command; it disallows setting of +the system encoding, but allows all other subcommands including +\fBsystem\fR to check the current encoding. +.TP +\fBexit\fR +The calling interpreter is deleted and its computation is stopped, but the +Tcl process in which this interpreter exists is not terminated. + +.SH SECURITY +The Safe Base does not attempt to completely prevent annoyance and +denial of service attacks. These forms of attack prevent the +application or user from temporarily using the computer to perform +useful work, for example by consuming all available CPU time or +all available screen real estate. +These attacks, while aggravating, are deemed to be of lesser importance +in general than integrity and privacy attacks that the Safe Base +is to prevent. +.PP +The commands available in a safe interpreter, in addition to +the safe set as defined in \fBinterp\fR manual page, are mediated aliases +for \fBsource\fR, \fBload\fR, \fBexit\fR, and safe subsets of +\fBfile\fR and \fBencoding\fR. The safe interpreter can also auto-load +code and it can request that packages be loaded. +.PP +Because some of these commands access the local file system, there is a +potential for information leakage about its directory structure. +To prevent this, commands that take file names as arguments in a safe +interpreter use tokens instead of the real directory names. +These tokens are translated to the real directory name while a request to, +e.g., source a file is mediated by the master interpreter. +This virtual path system is maintained in the master interpreter for each safe +interpreter created by \fB::safe::interpCreate\fR or initialized by +\fB::safe::interpInit\fR and +the path maps tokens accessible in the safe interpreter into real path +names on the local file system thus preventing safe interpreters +from gaining knowledge about the +structure of the file system of the host on which the interpreter is +executing. +The only valid file names arguments +for the \fBsource\fR and \fBload\fR aliases provided to the slave +are path in the form of +\fB[file join \fR\fItoken filename\fR\fB]\fR (ie, when using the +native file path formats: \fItoken\fR\fB/\fR\fIfilename\fR +on Unix, \fItoken\fR\fB\\\fIfilename\fR on Windows, +and \fItoken\fR\fB:\fR\fIfilename\fR on the Mac), +where \fItoken\fR is representing one of the directories +of the \fIaccessPath\fR list and \fIfilename\fR is +one file in that directory (no sub directories access are allowed). +.PP +When a token is used in a safe interpreter in a request to source or +load a file, the token is checked and +translated to a real path name and the file to be +sourced or loaded is located on the file system. +The safe interpreter never gains knowledge of the actual path name under +which the file is stored on the file system. +.PP +To further prevent potential information leakage from sensitive files that +are accidentally included in the set of files that can be sourced by a safe +interpreter, the \fBsource\fR alias restricts access to files +meeting the following constraints: the file name must +fourteen characters or shorter, must not contain more than one dot ("\fB.\fR"), +must end up with the extension \fB.tcl\fR or be called \fBtclIndex\fR. +.PP +Each element of the initial access path +list will be assigned a token that will be set in +the slave \fBauto_path\fR and the first element of that list will be set as +the \fBtcl_library\fR for that slave. +.PP +If the access path argument is not given or is the empty list, +the default behavior is to let the slave access the same packages +as the master has access to (Or to be more precise: +only packages written in Tcl (which by definition can't be dangerous +as they run in the slave interpreter) and C extensions that +provides a Safe_Init entry point). For that purpose, the master's +\fBauto_path\fR will be used to construct the slave access path. +In order that the slave successfully loads the Tcl library files +(which includes the auto-loading mechanism itself) the \fBtcl_library\fR will be +added or moved to the first position if necessary, in the +slave access path, so the slave +\fBtcl_library\fR will be the same as the master's (its real +path will still be invisible to the slave though). +In order that auto-loading works the same for the slave and +the master in this by default case, the first-level +sub directories of each directory in the master \fBauto_path\fR will +also be added (if not already included) to the slave access path. +You can always specify a more +restrictive path for which sub directories will never be searched by +explicitly specifying your directory list with the \fB\-accessPath\fR flag +instead of relying on this default mechanism. +.PP +When the \fIaccessPath\fR is changed after the first creation or +initialization (ie through \fBinterpConfigure -accessPath \fR\fIlist\fR), +an \fBauto_reset\fR is automatically evaluated in the safe interpreter +to synchronize its \fBauto_index\fR with the new token list. + +.SH "SEE ALSO" +interp(n), library(n), load(n), package(n), source(n), unknown(n) + +.SH KEYWORDS +alias, auto\-loading, auto_mkindex, load, master interpreter, safe +interpreter, slave interpreter, source diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/scan.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/scan.n new file mode 100644 index 0000000000000000000000000000000000000000..541830079ab3d3ced97b777f3b307fbba18646b3 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/scan.n @@ -0,0 +1,195 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" Copyright (c) 2000 Scriptics Corporation. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: scan.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH scan n 8.3 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +scan \- Parse string using conversion specifiers in the style of sscanf +.SH SYNOPSIS +\fBscan \fIstring format \fR?\fIvarName varName ...\fR? +.BE + +.SH INTRODUCTION +.PP +This command parses fields from an input string in the same fashion as the +ANSI C \fBsscanf\fR procedure and returns a count of the number of +conversions performed, or -1 if the end of the input string is reached +before any conversions have been performed. \fIString\fR gives the input +to be parsed and \fIformat\fR indicates how to parse it, using \fB%\fR +conversion specifiers as in \fBsscanf\fR. Each \fIvarName\fR gives the +name of a variable; when a field is scanned from \fIstring\fR the result is +converted back into a string and assigned to the corresponding variable. +.VS 8.3 +If no \fIvarName\fR variables are specified, then \fBscan\fR works in an +inline manner, returning the data that would otherwise be stored in the +variables as a list. In the inline case, an empty string is returned when +the end of the input string is reached before any conversions have been +performed. +.VE 8.3 + +.SH "DETAILS ON SCANNING" +.PP +\fBScan\fR operates by scanning \fIstring\fR and \fIformat\fR together. +If the next character in \fIformat\fR is a blank or tab then it +matches any number of white space characters in \fIstring\fR (including +zero). +Otherwise, if it isn't a \fB%\fR character then it +must match the next character of \fIstring\fR. +When a \fB%\fR is encountered in \fIformat\fR, it indicates +the start of a conversion specifier. +A conversion specifier contains up to four fields after the \fB%\fR: +a \fB*\fR, which indicates that the converted value is to be discarded +instead of assigned to a variable; a XPG3 position specifier; a number +indicating a maximum field width; and a conversion character. +All of these fields are optional except for the conversion character. +The fields that are present must appear in the order given above. +.PP +When \fBscan\fR finds a conversion specifier in \fIformat\fR, it +first skips any white-space characters in \fIstring\fR (unless the +specifier is \fB[\fR or \fBc\fR). +Then it converts the next input characters according to the +conversion specifier and stores the result in the variable given +by the next argument to \fBscan\fR. +.PP +If the \fB%\fR is followed by a decimal number and a \fB$\fR, as in +``\fB%2$d\fR'', then the variable to use is not taken from the next +sequential argument. Instead, it is taken from the argument indicated +by the number, where 1 corresponds to the first \fIvarName\fR. If +there are any positional specifiers in \fIformat\fR then all of the +specifiers must be positional. Every \fIvarName\fR on the argument +list must correspond to exactly one conversion specifier or an error +is generated, or in the inline case, any position can be specified +at most once and the empty positions will be filled in with empty strings. +.PP +The following conversion characters are supported: +.TP 10 +\fBd\fR +The input field must be a decimal integer. +It is read in and the value is stored in the variable as a decimal string. +.TP 10 +\fBo\fR +The input field must be an octal integer. It is read in and the +value is stored in the variable as a decimal string. +.VS 8.4 +If the value exceeds MAX_INT (017777777777 on platforms using 32-bit +integers), it will be truncated to a signed integer. Hence, 037777777777 +will appear as -1 on a 32-bit machine. +.VE 8.4 +.TP 10 +\fBx\fR +The input field must be a hexadecimal integer. It is read in +and the value is stored in the variable as a decimal string. +.VS 8.4 +If the value exceeds MAX_INT (0x7FFFFFFF on platforms using 32-bit +integers), it will be truncated to a signed integer. Hence, 0xFFFFFFFF +will appear as -1 on a 32-bit machine. +.VE 8.4 +.TP 10 +\fBu\fR +The input field must be a decimal integer. The value is stored in the +variable as an unsigned decimal integer string. +.TP 10 +\fBi\fR +The input field must be an integer. The base (i.e. decimal, octal, or +hexadecimal) is determined in the same fashion as described in +\fBexpr\fR. The value is stored in the variable as a decimal string. +.TP 10 +\fBc\fR +A single character is read in and its binary value is stored in +the variable as a decimal string. +Initial white space is not skipped in this case, so the input +field may be a white-space character. +This conversion is different from the ANSI standard in that the +input field always consists of a single character and no field +width may be specified. +.TP 10 +\fBs\fR +The input field consists of all the characters up to the next +white-space character; the characters are copied to the variable. +.TP 10 +\fBe\fR or \fBf\fR or \fBg\fR +The input field must be a floating-point number consisting +of an optional sign, a string of decimal digits possibly +containing a decimal point, and an optional exponent consisting +of an \fBe\fR or \fBE\fR followed by an optional sign and a string of +decimal digits. +It is read in and stored in the variable as a floating-point string. +.TP 10 +\fB[\fIchars\fB]\fR +The input field consists of any number of characters in +\fIchars\fR. +The matching string is stored in the variable. +If the first character between the brackets is a \fB]\fR then +it is treated as part of \fIchars\fR rather than the closing +bracket for the set. +If \fIchars\fR +contains a sequence of the form \fIa\fB\-\fIb\fR then any +character between \fIa\fR and \fIb\fR (inclusive) will match. +If the first or last character between the brackets is a \fB\-\fR, then +it is treated as part of \fIchars\fR rather than indicating a range. +.TP 10 +\fB[^\fIchars\fB]\fR +The input field consists of any number of characters not in +\fIchars\fR. +The matching string is stored in the variable. +If the character immediately following the \fB^\fR is a \fB]\fR then it is +treated as part of the set rather than the closing bracket for +the set. +If \fIchars\fR +contains a sequence of the form \fIa\fB\-\fIb\fR then any +character between \fIa\fR and \fIb\fR (inclusive) will be excluded +from the set. +If the first or last character between the brackets is a \fB\-\fR, then +it is treated as part of \fIchars\fR rather than indicating a range. +.TP 10 +\fBn\fR +No input is consumed from the input string. Instead, the total number +of chacters scanned from the input string so far is stored in the variable. +.LP +The number of characters read from the input for a conversion is the +largest number that makes sense for that particular conversion (e.g. +as many decimal digits as possible for \fB%d\fR, as +many octal digits as possible for \fB%o\fR, and so on). +The input field for a given conversion terminates either when a +white-space character is encountered or when the maximum field +width has been reached, whichever comes first. +If a \fB*\fR is present in the conversion specifier +then no variable is assigned and the next scan argument is not consumed. + +.SH "DIFFERENCES FROM ANSI SSCANF" +.PP +The behavior of the \fBscan\fR command is the same as the behavior of +the ANSI C \fBsscanf\fR procedure except for the following differences: +.IP [1] +\fB%p\fR conversion specifier is not currently supported. +.IP [2] +For \fB%c\fR conversions a single character value is +converted to a decimal string, which is then assigned to the +corresponding \fIvarName\fR; +no field width may be specified for this conversion. +.IP [3] +The \fBl\fR, \fBh\fR, and \fBL\fR modifiers are ignored; integer +values are always converted as if there were no modifier present +and real values are always converted as if the \fBl\fR modifier +were present (i.e. type \fBdouble\fR is used for the internal +representation). +.IP [4] +.VS 8.3 +If the end of the input string is reached before any conversions have been +performed and no variables are given, and empty string is returned. +.VE 8.3 + +.SH "SEE ALSO" +format(n), sscanf(3) + +.SH KEYWORDS +conversion specifier, parse, scan diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/seek.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/seek.n new file mode 100644 index 0000000000000000000000000000000000000000..739837cdac03047f79154ec80d319e22fed303f3 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/seek.n @@ -0,0 +1,64 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: seek.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH seek n 8.1 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +seek \- Change the access position for an open channel +.SH SYNOPSIS +\fBseek \fIchannelId offset \fR?\fIorigin\fR? +.BE + +.SH DESCRIPTION +.PP +Changes the current access position for \fIchannelId\fR. +\fIChannelId\fR must be a channel identifier such as returned from a +previous invocation of \fBopen\fR or \fBsocket\fR. +The \fIoffset\fR and \fIorigin\fR +arguments specify the position at which the next read or write will occur +for \fIchannelId\fR. \fIOffset\fR must be an integer (which may be +negative) and \fIorigin\fR must be one of the following: +.TP 10 +\fBstart\fR +The new access position will be \fIoffset\fR bytes from the start +of the underlying file or device. +.TP 10 +\fBcurrent\fR +The new access position will be \fIoffset\fR bytes from the current +access position; a negative \fIoffset\fR moves the access position +backwards in the underlying file or device. +.TP 10 +\fBend\fR +The new access position will be \fIoffset\fR bytes from the end of +the file or device. A negative \fIoffset\fR places the access position +before the end of file, and a positive \fIoffset\fR places the access +position after the end of file. +.LP +The \fIorigin\fR argument defaults to \fBstart\fR. +.PP +The command flushes all buffered output for the channel before the command +returns, even if the channel is in nonblocking mode. +It also discards any buffered and unread input. +This command returns an empty string. +An error occurs if this command is applied to channels whose underlying +file or device does not support seeking. +.PP +.VS 8.1 +Note that \fIoffset\fR values are byte offsets, not character +offsets. Both \fBseek\fR and \fBtell\fR operate in terms of bytes, +not characters, unlike \fBread\fR. +.VE 8.1 + +.SH "SEE ALSO" +file(n), open(n), close(n), gets(n), tell(n) + +.SH KEYWORDS +access position, file, seek diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/set.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/set.n new file mode 100644 index 0000000000000000000000000000000000000000..9cae2469f1ed6f963e87add1bb1437fd5907c7fc --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/set.n @@ -0,0 +1,51 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: set.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH set n "" Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +set \- Read and write variables +.SH SYNOPSIS +\fBset \fIvarName \fR?\fIvalue\fR? +.BE + +.SH DESCRIPTION +.PP +Returns the value of variable \fIvarName\fR. +If \fIvalue\fR is specified, then set +the value of \fIvarName\fR to \fIvalue\fR, creating a new variable +if one doesn't already exist, and return its value. +If \fIvarName\fR contains an open parenthesis and ends with a +close parenthesis, then it refers to an array element: the characters +before the first open parenthesis are the name of the array, +and the characters between the parentheses are the index within the array. +Otherwise \fIvarName\fR refers to a scalar variable. +Normally, \fIvarName\fR is unqualified +(does not include the names of any containing namespaces), +and the variable of that name in the current namespace is read or written. +If \fIvarName\fR includes namespace qualifiers +(in the array name if it refers to an array element), +the variable in the specified namespace is read or written. +.PP +If no procedure is active, +then \fIvarName\fR refers to a namespace variable +(global variable if the current namespace is the global namespace). +If a procedure is active, then \fIvarName\fR refers to a parameter +or local variable of the procedure unless the \fBglobal\fR command +was invoked to declare \fIvarName\fR to be global, +or unless a \fBvariable\fR command +was invoked to declare \fIvarName\fR to be a namespace variable. + +.SH "SEE ALSO" +expr(n), proc(n), trace(n), unset(n) + +.SH KEYWORDS +read, write, variable diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/socket.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/socket.n new file mode 100644 index 0000000000000000000000000000000000000000..145a63295908fade375aaec1ab837fe6ff091462 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/socket.n @@ -0,0 +1,134 @@ +'\" +'\" Copyright (c) 1996 Sun Microsystems, Inc. +'\" Copyright (c) 1998-1999 by Scriptics Corporation. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: socket.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +.so man.macros +.TH socket n 8.0 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +socket \- Open a TCP network connection +.SH SYNOPSIS +.sp +\fBsocket \fR?\fIoptions\fR? \fIhost port\fR +.sp +\fBsocket\fR \fB\-server \fIcommand\fR ?\fIoptions\fR? \fIport\fR +.BE + +.SH DESCRIPTION +.PP +This command opens a network socket and returns a channel +identifier that may be used in future invocations of commands like +\fBread\fR, \fBputs\fR and \fBflush\fR. +At present only the TCP network protocol is supported; future +releases may include support for additional protocols. +The \fBsocket\fR command may be used to open either the client or +server side of a connection, depending on whether the \fB\-server\fR +switch is specified. + +.SH "CLIENT SOCKETS" +.PP +If the \fB\-server\fR option is not specified, then the client side of a +connection is opened and the command returns a channel identifier +that can be used for both reading and writing. +\fIPort\fR and \fIhost\fR specify a port +to connect to; there must be a server accepting connections on +this port. \fIPort\fR is an integer port number and \fIhost\fR +is either a domain-style name such as \fBwww.sunlabs.com\fR or +a numerical IP address such as \fB127.0.0.1\fR. +Use \fIlocalhost\fR to refer to the host on which the command is invoked. +.PP +The following options may also be present before \fIhost\fR +to specify additional information about the connection: +.TP +\fB\-myaddr\fI addr\fR +\fIAddr\fR gives the domain-style name or numerical IP address of +the client-side network interface to use for the connection. +This option may be useful if the client machine has multiple network +interfaces. If the option is omitted then the client-side interface +will be chosen by the system software. +.TP +\fB\-myport\fI port\fR +\fIPort\fR specifies an integer port number to use for the client's +side of the connection. If this option is omitted, the client's +port number will be chosen at random by the system software. +.TP +\fB\-async\fR +The \fB\-async\fR option will cause the client socket to be connected +asynchronously. This means that the socket will be created immediately but +may not yet be connected to the server, when the call to \fBsocket\fR +returns. When a \fBgets\fR or \fBflush\fR is done on the socket before the +connection attempt succeeds or fails, if the socket is in blocking mode, the +operation will wait until the connection is completed or fails. If the +socket is in nonblocking mode and a \fBgets\fR or \fBflush\fR is done on +the socket before the connection attempt succeeds or fails, the operation +returns immediately and \fBfblocked\fR on the socket returns 1. + +.SH "SERVER SOCKETS" +.PP +If the \fB\-server\fR option is specified then the new socket +will be a server for the port given by \fIport\fR. +Tcl will automatically accept connections to the given port. +For each connection Tcl will create a new channel that may be used to +communicate with the client. Tcl then invokes \fIcommand\fR +with three additional arguments: the name of the new channel, the +address, in network address notation, of the client's host, and +the client's port number. +.PP +The following additional option may also be specified before \fIhost\fR: +.TP +\fB\-myaddr\fI addr\fR +\fIAddr\fR gives the domain-style name or numerical IP address of +the server-side network interface to use for the connection. +This option may be useful if the server machine has multiple network +interfaces. If the option is omitted then the server socket is bound +to the special address INADDR_ANY so that it can accept connections from +any interface. +.PP +Server channels cannot be used for input or output; their sole use is to +accept new client connections. The channels created for each incoming +client connection are opened for input and output. Closing the server +channel shuts down the server so that no new connections will be +accepted; however, existing connections will be unaffected. +.PP +Server sockets depend on the Tcl event mechanism to find out when +new connections are opened. If the application doesn't enter the +event loop, for example by invoking the \fBvwait\fR command or +calling the C procedure \fBTcl_DoOneEvent\fR, then no connections +will be accepted. + +.SH "CONFIGURATION OPTIONS" +The \fBfconfigure\fR command can be used to query several readonly +configuration options for socket channels: +.VS 8.0.5 +.TP +\fB\-error\fR +This option gets the current error status of the given socket. This +is useful when you need to determine if an asynchronous connect +operation succeeded. If there was an error, the error message is +returned. If there was no error, an empty string is returned. +.VE 8.0.5 +.TP +\fB\-sockname\fR +This option returns a list of three elements, the address, the host name +and the port number for the socket. If the host name cannot be computed, +the second element is identical to the address, the first element of the +list. +.TP +\fB\-peername\fR +This option is not supported by server sockets. For client and accepted +sockets, this option returns a list of three elements; these are the +address, the host name and the port to which the peer socket is connected +or bound. If the host name cannot be computed, the second element of the +list is identical to the address, its first element. +.PP + +.SH "SEE ALSO" +flush(n), open(n), read(n) + +.SH KEYWORDS +bind, channel, connection, domain name, host, network address, socket, tcp diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/source.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/source.n new file mode 100644 index 0000000000000000000000000000000000000000..7567fdf2061ed327aa78c2e77ddbd93b1dfb03ca --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/source.n @@ -0,0 +1,44 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: source.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH source n "" Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +source \- Evaluate a file or resource as a Tcl script +.SH SYNOPSIS +\fBsource \fIfileName\fR +.sp +\fBsource\fR \fB\-rsrc \fIresourceName \fR?\fIfileName\fR? +.sp +\fBsource\fR \fB\-rsrcid \fIresourceId \fR?\fIfileName\fR? +.BE + +.SH DESCRIPTION +.PP +This command takes the contents of the specified file or resource +and passes it to the Tcl interpreter as a text script. The return +value from \fBsource\fR is the return value of the last command +executed in the script. If an error occurs in evaluating the contents +of the script then the \fBsource\fR command will return that error. +If a \fBreturn\fR command is invoked from within the script then the +remainder of the file will be skipped and the \fBsource\fR command +will return normally with the result from the \fBreturn\fR command. + +The \fI\-rsrc\fR and \fI\-rsrcid\fR forms of this command are only +available on Macintosh computers. These versions of the command +allow you to source a script from a \fBTEXT\fR resource. You may specify +what \fBTEXT\fR resource to source by either name or id. By default Tcl +searches all open resource files, which include the current +application and any loaded C extensions. Alternatively, you may +specify the \fIfileName\fR where the \fBTEXT\fR resource can be found. + +.SH KEYWORDS +file, script diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/split.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/split.n new file mode 100644 index 0000000000000000000000000000000000000000..87157d44f6c34be076449b1ab19713fc3adf2976 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/split.n @@ -0,0 +1,47 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: split.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH split n "" Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +split \- Split a string into a proper Tcl list +.SH SYNOPSIS +\fBsplit \fIstring \fR?\fIsplitChars\fR? +.BE + +.SH DESCRIPTION +.PP +Returns a list created by splitting \fIstring\fR at each character +that is in the \fIsplitChars\fR argument. +Each element of the result list will consist of the +characters from \fIstring\fR that lie between instances of the +characters in \fIsplitChars\fR. +Empty list elements will be generated if \fIstring\fR contains +adjacent characters in \fIsplitChars\fR, or if the first or last +character of \fIstring\fR is in \fIsplitChars\fR. +If \fIsplitChars\fR is an empty string then each character of +\fIstring\fR becomes a separate element of the result list. +\fISplitChars\fR defaults to the standard white-space characters. +For example, +.CS +\fBsplit "comp.unix.misc" .\fR +.CE +returns \fB"comp unix misc"\fR and +.CS +\fBsplit "Hello world" {}\fR +.CE +returns \fB"H e l l o { } w o r l d"\fR. + +.SH "SEE ALSO" +join(n), list(n), string(n) + +.SH KEYWORDS +list, split, string diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/string.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/string.n new file mode 100644 index 0000000000000000000000000000000000000000..298212ccc8408376ca71c666cb4628ac70aa939d --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/string.n @@ -0,0 +1,341 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: string.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH string n 8.1 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +string \- Manipulate strings +.SH SYNOPSIS +\fBstring \fIoption arg \fR?\fIarg ...?\fR +.BE + +.SH DESCRIPTION +.PP +Performs one of several string operations, depending on \fIoption\fR. +The legal \fIoption\fRs (which may be abbreviated) are: +.VS 8.1 +.TP +\fBstring bytelength \fIstring\fR +Returns a decimal string giving the number of bytes used to represent +\fIstring\fR in memory. Because UTF\-8 uses one to three bytes to +represent Unicode characters, the byte length will not be the same as +the character length in general. The cases where a script cares about +the byte length are rare. In almost all cases, you should use the +\fBstring length\fR operation. Refer to the \fBTcl_NumUtfChars\fR +manual entry for more details on the UTF\-8 representation. +.TP +\fBstring compare\fR ?\fB\-nocase\fR? ?\fB\-length int\fR? \fIstring1 string2\fR +.VE 8.1 +Perform a character-by-character comparison of strings \fIstring1\fR and +\fIstring2\fR. Returns +\-1, 0, or 1, depending on whether \fIstring1\fR is lexicographically +less than, equal to, or greater than \fIstring2\fR. +.VS 8.1 +If \fB\-length\fR is specified, then only the first \fIlength\fR characters +are used in the comparison. If \fB\-length\fR is negative, it is +ignored. If \fB\-nocase\fR is specified, then the strings are +compared in a case-insensitive manner. +.TP +\fBstring equal\fR ?\fB\-nocase\fR? ?\fB-length int\fR? \fIstring1 string2\fR +Perform a character-by-character comparison of strings +\fIstring1\fR and \fIstring2\fR. Returns 1 if \fIstring1\fR and +\fIstring2\fR are identical, or 0 when not. If \fB\-length\fR is +specified, then only the first \fIlength\fR characters are used in the +comparison. If \fB\-length\fR is negative, it is ignored. If +\fB\-nocase\fR is specified, then the strings are compared in a +case-insensitive manner. +.TP +\fBstring first \fIstring1 string2\fR ?\fIstartIndex\fR? +.VE 8.1 +Search \fIstring2\fR for a sequence of characters that exactly match +the characters in \fIstring1\fR. If found, return the index of the +first character in the first such match within \fIstring2\fR. If not +found, return \-1. +.VS 8.1 +If \fIstartIndex\fR is specified (in any of the forms accepted by the +\fBindex\fR method), then the search is constrained to start with the +character in \fIstring2\fR specified by the index. For example, +.RS +.CS +\fBstring first a 0a23456789abcdef 5\fR +.CE +will return \fB10\fR, but +.CS +\fBstring first a 0123456789abcdef 11\fR +.CE +will return \fB\-1\fR. +.RE +.VE 8.1 +.TP +\fBstring index \fIstring charIndex\fR +Returns the \fIcharIndex\fR'th character of the \fIstring\fR +argument. A \fIcharIndex\fR of 0 corresponds to the first +character of the string. +.VS 8.1 +\fIcharIndex\fR may be specified as +follows: +.RS +.IP \fIinteger\fR 10 +The char specified at this integral index +.IP \fBend\fR 10 +The last char of the string. +.IP \fBend\-\fIinteger\fR 10 +The last char of the string minus the specified integer +offset (e.g. \fBend\-1\fR would refer to the "c" in "abcd"). +.PP +.VE 8.1 +If \fIcharIndex\fR is less than 0 or greater than +or equal to the length of the string then an empty string is +returned. +.VS 8.1 +.RE +.TP +\fBstring is \fIclass\fR ?\fB\-strict\fR? ?\fB\-failindex \fIvarname\fR? \fIstring\fR +Returns 1 if \fIstring\fR is a valid member of the specified character +class, otherwise returns 0. If \fB\-strict\fR is specified, then an +empty string returns 0, otherwise and empty string will return 1 on +any class. If \fB\-failindex\fR is specified, then if the function +returns 0, the index in the string where the class was no longer valid +will be stored in the variable named \fIvarname\fR. The \fIvarname\fR +will not be set if the function returns 1. The following character classes +are recognized (the class name can be abbreviated): +.RS +.IP \fBalnum\fR 10 +Any Unicode alphabet or digit character. +.IP \fBalpha\fR 10 +Any Unicode alphabet character. +.IP \fBascii\fR 10 +Any character with a value less than \\u0080 (those that +are in the 7\-bit ascii range). +.IP \fBboolean\fR 10 +Any of the forms allowed to \fBTcl_GetBoolean\fR. +.IP \fBcontrol\fR 10 +Any Unicode control character. +.IP \fBdigit\fR 10 +Any Unicode digit character. Note that this includes characters +outside of the [0\-9] range. +.IP \fBdouble\fR 10 +Any of the valid forms for a double in Tcl, with optional surrounding +whitespace. In case of under/overflow in the value, 0 is returned +and the \fIvarname\fR will contain \-1. +.IP \fBfalse\fR 10 +Any of the forms allowed to \fBTcl_GetBoolean\fR where the value is false. +.IP \fBgraph\fR 10 +Any Unicode printing character, except space. +.IP \fBinteger\fR 10 +Any of the valid forms for an integer in Tcl, with optional surrounding +whitespace. In case of under/overflow in the value, 0 is returned +and the \fIvarname\fR will contain \-1. +.IP \fBlower\fR 10 +Any Unicode lower case alphabet character. +.IP \fBprint\fR 10 +Any Unicode printing character, including space. +.IP \fBpunct\fR 10 +Any Unicode punctuation character. +.IP \fBspace\fR 10 +Any Unicode space character. +.IP \fBtrue\fR 10 +Any of the forms allowed to \fBTcl_GetBoolean\fR where the value is true. +.IP \fBupper\fR 10 +Any upper case alphabet character in the Unicode character set. +.IP \fBwordchar\fR 10 +Any Unicode word character. That is any alphanumeric character, +and any Unicode connector punctuation characters (e.g. underscore). +.IP \fBxdigit\fR 10 +Any hexadecimal digit character ([0\-9A\-Fa\-f]). +.PP +In the case of \fBboolean\fR, \fBtrue\fR and \fBfalse\fR, if the +function will return 0, then the \fIvarname\fR will always be set to 0, +due to the varied nature of a valid boolean value. +.RE +.TP +\fBstring last \fIstring1 string2\fR ?\fIstartIndex\fR? +.VE 8.1 +Search \fIstring2\fR for a sequence of characters that exactly match +the characters in \fIstring1\fR. If found, return the index of the +first character in the last such match within \fIstring2\fR. If there +is no match, then return \-1. +.VS 8.1 +If \fIstartIndex\fR is specified (in any of the forms accepted by the +\fBindex\fR method), then only the characters in \fIstring2\fR at or before the +specified \fIstartIndex\fR will be considered by the search. For example, +.RS +.CS +\fBstring last a 0a23456789abcdef 15\fR +.CE +will return \fB10\fR, but +.CS +\fBstring last a 0a23456789abcdef 9\fR +.CE +will return \fB1\fR. +.RE +.VE 8.1 +.TP +\fBstring length \fIstring\fR +Returns a decimal string giving the number of characters in +\fIstring\fR. Note that this is not necessarily the same as the +number of bytes used to store the string. +.VS 8.1 +.TP +\fBstring map\fR ?\fB\-nocase\fR? \fIcharMap string\fR +Replaces characters in \fIstring\fR based on the key-value pairs in +\fIcharMap\fR. \fIcharMap\fR is a list of \fIkey value key value\fR ... +as in the form returned by \fBarray get\fR. Each instance of a +key in the string will be replaced with its corresponding value. If +\fB\-nocase\fR is specified, then matching is done without regard to +case differences. Both \fIkey\fR and \fIvalue\fR may be multiple +characters. Replacement is done in an ordered manner, so the key appearing +first in the list will be checked first, and so on. \fIstring\fR is +only iterated over once, so earlier key replacements will have no +affect for later key matches. For example, +.RS +.CS +\fBstring map {abc 1 ab 2 a 3 1 0} 1abcaababcabababc\fR +.CE +will return the string \fB01321221\fR. +.RE +.TP +\fBstring match\fR ?\fB\-nocase\fR? \fIpattern\fR \fIstring\fR +.VE 8.1 +See if \fIpattern\fR matches \fIstring\fR; return 1 if it does, 0 +if it doesn't. +.VS 8.1 +If \fB\-nocase\fR is specified, then the pattern attempts to match +against the string in a case insensitive manner. +.VE 8.1 +For the two strings to match, their contents +must be identical except that the following special sequences +may appear in \fIpattern\fR: +.RS +.IP \fB*\fR 10 +Matches any sequence of characters in \fIstring\fR, +including a null string. +.IP \fB?\fR 10 +Matches any single character in \fIstring\fR. +.IP \fB[\fIchars\fB]\fR 10 +Matches any character in the set given by \fIchars\fR. If a sequence +of the form +\fIx\fB\-\fIy\fR appears in \fIchars\fR, then any character +between \fIx\fR and \fIy\fR, inclusive, will match. +.VS 8.1 +When used with \fB\-nocase\fR, the end points of the range are converted +to lower case first. Whereas {[A\-z]} matches '_' when matching +case-sensitively ('_' falls between the 'Z' and 'a'), with \fB\-nocase\fR +this is considered like {[A\-Za\-z]} (and probably what was meant in the +first place). +.VE 8.1 +.IP \fB\e\fIx\fR 10 +Matches the single character \fIx\fR. This provides a way of +avoiding the special interpretation of the characters +\fB*?[]\e\fR in \fIpattern\fR. +.RE +.TP +\fBstring range \fIstring first last\fR +Returns a range of consecutive characters from \fIstring\fR, starting +with the character whose index is \fIfirst\fR and ending with the +character whose index is \fIlast\fR. An index of 0 refers to the +.VS 8.1 +first character of the string. \fIfirst\fR and \fIlast\fR may be +specified as for the \fBindex\fR method. +.VE 8.1 +If \fIfirst\fR is less than zero then it is treated as if it were zero, and +if \fIlast\fR is greater than or equal to the length of the string then +it is treated as if it were \fBend\fR. If \fIfirst\fR is greater than +\fIlast\fR then an empty string is returned. +.VS 8.1 +.TP +\fBstring repeat \fIstring count\fR +Returns \fIstring\fR repeated \fIcount\fR number of times. +.TP +\fBstring replace \fIstring first last\fR ?\fInewstring\fR? +Removes a range of consecutive characters from \fIstring\fR, starting +with the character whose index is \fIfirst\fR and ending with the +character whose index is \fIlast\fR. An index of 0 refers to the +first character of the string. \fIFirst\fR and \fIlast\fR may be +specified as for the \fBindex\fR method. If \fInewstring\fR is +specified, then it is placed in the removed character range. +If \fIfirst\fR is less than zero then it is treated as if it were zero, and +if \fIlast\fR is greater than or equal to the length of the string then +it is treated as if it were \fBend\fR. If \fIfirst\fR is greater than +\fIlast\fR or the length of the initial string, or \fIlast\fR is less +than 0, then the initial string is returned untouched. +.TP +\fBstring tolower \fIstring\fR ?\fIfirst\fR? ?\fIlast\fR? +Returns a value equal to \fIstring\fR except that all upper (or title) case +letters have been converted to lower case. If \fIfirst\fR is specified, it +refers to the first char index in the string to start modifying. If +\fIlast\fR is specified, it refers to the char index in the string to stop +at (inclusive). \fIfirst\fR and \fIlast\fR may be +specified as for the \fBindex\fR method. +.TP +\fBstring totitle \fIstring\fR ?\fIfirst\fR? ?\fIlast\fR? +Returns a value equal to \fIstring\fR except that the first character +in \fIstring\fR is converted to its Unicode title case variant (or upper +case if there is no title case variant) and the rest of the string is +converted to lower case. If \fIfirst\fR is specified, it +refers to the first char index in the string to start modifying. If +\fIlast\fR is specified, it refers to the char index in the string to stop +at (inclusive). \fIfirst\fR and \fIlast\fR may be +specified as for the \fBindex\fR method. +.TP +\fBstring toupper \fIstring\fR ?\fIfirst\fR? ?\fIlast\fR? +Returns a value equal to \fIstring\fR except that all lower (or title) case +letters have been converted to upper case. If \fIfirst\fR is specified, it +refers to the first char index in the string to start modifying. If +\fIlast\fR is specified, it refers to the char index in the string to stop +at (inclusive). \fIfirst\fR and \fIlast\fR may be specified as for the +\fBindex\fR method. +.VE 8.1 +.TP +\fBstring trim \fIstring\fR ?\fIchars\fR? +Returns a value equal to \fIstring\fR except that any leading +or trailing characters from the set given by \fIchars\fR are +removed. +If \fIchars\fR is not specified then white space is removed +(spaces, tabs, newlines, and carriage returns). +.TP +\fBstring trimleft \fIstring\fR ?\fIchars\fR? +Returns a value equal to \fIstring\fR except that any +leading characters from the set given by \fIchars\fR are +removed. +If \fIchars\fR is not specified then white space is removed +(spaces, tabs, newlines, and carriage returns). +.TP +\fBstring trimright \fIstring\fR ?\fIchars\fR? +Returns a value equal to \fIstring\fR except that any +trailing characters from the set given by \fIchars\fR are +removed. +If \fIchars\fR is not specified then white space is removed +(spaces, tabs, newlines, and carriage returns). +.VS 8.1 +.TP +\fBstring wordend \fIstring charIndex\fR +Returns the index of the character just after the last one in the word +containing character \fIcharIndex\fR of \fIstring\fR. \fIcharIndex\fR +may be specified as for the \fBindex\fR method. A word is +considered to be any contiguous range of alphanumeric (Unicode letters +or decimal digits) or underscore (Unicode connector punctuation) +characters, or any single character other than these. +.TP +\fBstring wordstart \fIstring charIndex\fR +Returns the index of the first character in the word containing +character \fIcharIndex\fR of \fIstring\fR. \fIcharIndex\fR may be +specified as for the \fBindex\fR method. A word is considered to be any +contiguous range of alphanumeric (Unicode letters or decimal digits) +or underscore (Unicode connector punctuation) characters, or any +single character other than these. +.VE 8.1 + +.SH "SEE ALSO" +expr(n), list(n) + +.SH KEYWORDS +case conversion, compare, index, match, pattern, string, word, equal, ctype diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/subst.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/subst.n new file mode 100644 index 0000000000000000000000000000000000000000..4ce227edfcb910b41c41ab35c529b9dbbafe551c --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/subst.n @@ -0,0 +1,51 @@ +'\" +'\" Copyright (c) 1994 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: subst.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH subst n 7.4 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +subst \- Perform backslash, command, and variable substitutions +.SH SYNOPSIS +\fBsubst \fR?\fB\-nobackslashes\fR? ?\fB\-nocommands\fR? ?\fB\-novariables\fR? \fIstring\fR +.BE + +.SH DESCRIPTION +.PP +This command performs variable substitutions, command substitutions, +and backslash substitutions on its \fIstring\fR argument and +returns the fully-substituted result. +The substitutions are performed in exactly the same way as for +Tcl commands. +As a result, the \fIstring\fR argument is actually substituted twice, +once by the Tcl parser in the usual fashion for Tcl commands, and +again by the \fIsubst\fR command. +.PP +If any of the \fB\-nobackslashes\fR, \fB\-nocommands\fR, or +\fB\-novariables\fR are specified, then the corresponding substitutions +are not performed. +For example, if \fB\-nocommands\fR is specified, no command substitution +is performed: open and close brackets are treated as ordinary characters +with no special interpretation. +.PP +Note: when it performs its substitutions, \fIsubst\fR does not +give any special treatment to double quotes or curly braces. For +example, the script +.CS +\fBset a 44 +subst {xyz {$a}}\fR +.CE +returns ``\fBxyz {44}\fR'', not ``\fBxyz {$a}\fR''. + +.SH "SEE ALSO" +eval(n) + +.SH KEYWORDS +backslash substitution, command substitution, variable substitution diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/switch.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/switch.n new file mode 100644 index 0000000000000000000000000000000000000000..a058a777fa3bfb7a9f7000e20852400c298c5dd9 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/switch.n @@ -0,0 +1,117 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1997 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: switch.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH switch n 7.0 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +switch \- Evaluate one of several scripts, depending on a given value +.SH SYNOPSIS +\fBswitch \fR?\fIoptions\fR?\fI string pattern body \fR?\fIpattern body \fR...? +.sp +\fBswitch \fR?\fIoptions\fR?\fI string \fR{\fIpattern body \fR?\fIpattern body \fR...?} +.BE + +.SH DESCRIPTION +.PP +The \fBswitch\fR command matches its \fIstring\fR argument against each of +the \fIpattern\fR arguments in order. +As soon as it finds a \fIpattern\fR that matches \fIstring\fR it +evaluates the following \fIbody\fR argument by passing it recursively +to the Tcl interpreter and returns the result of that evaluation. +If the last \fIpattern\fR argument is \fBdefault\fR then it matches +anything. +If no \fIpattern\fR argument +matches \fIstring\fR and no default is given, then the \fBswitch\fR +command returns an empty string. +.PP +If the initial arguments to \fBswitch\fR start with \fB\-\fR then +they are treated as options. The following options are +currently supported: +.TP 10 +\fB\-exact\fR +Use exact matching when comparing \fIstring\fR to a pattern. This +is the default. +.TP 10 +\fB\-glob\fR +When matching \fIstring\fR to the patterns, use glob-style matching +(i.e. the same as implemented by the \fBstring match\fR command). +.TP 10 +\fB\-regexp\fR +When matching \fIstring\fR to the patterns, use regular +expression matching +(as described in the \fBre_syntax\fR reference page). +.TP 10 +\fB\-\|\-\fR +Marks the end of options. The argument following this one will +be treated as \fIstring\fR even if it starts with a \fB\-\fR. +.PP +Two syntaxes are provided for the \fIpattern\fR and \fIbody\fR arguments. +The first uses a separate argument for each of the patterns and commands; +this form is convenient if substitutions are desired on some of the +patterns or commands. +The second form places all of the patterns and commands together into +a single argument; the argument must have proper list structure, with +the elements of the list being the patterns and commands. +The second form makes it easy to construct multi-line switch commands, +since the braces around the whole list make it unnecessary to include a +backslash at the end of each line. +Since the \fIpattern\fR arguments are in braces in the second form, +no command or variable substitutions are performed on them; this makes +the behavior of the second form different than the first form in some +cases. +.PP +If a \fIbody\fR is specified as ``\fB\-\fR'' it means that the \fIbody\fR +for the next pattern should also be used as the body for this +pattern (if the next pattern also has a body of ``\fB\-\fR'' +then the body after that is used, and so on). +This feature makes it possible to share a single \fIbody\fR among +several patterns. +.PP +Beware of how you place comments in \fBswitch\fR commands. Comments +should only be placed \fBinside\fR the execution body of one of the +patterns, and not intermingled with the patterns. +.PP +Below are some examples of \fBswitch\fR commands: +.CS +\fBswitch\0abc\0a\0\-\0b\0{format 1}\0abc\0{format 2}\0default\0{format 3}\fR +.CE +will return \fB2\fR, +.CS +\fBswitch\0\-regexp\0aaab { + ^a.*b$\0\- + b\0{format 1} + a*\0{format 2} + default\0{format 3} +}\fR +.CE +will return \fB1\fR, and +.CS +\fBswitch\0xyz { + a + \- + b + { + # Correct Comment Placement + format 1 + } + a* + {format 2} + default + {format 3} +}\fR +.CE +will return \fB3\fR. + +.SH "SEE ALSO" +for(n), if(n), regexp(n) + +.SH KEYWORDS +switch, match, regular expression diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/tclsh.1 b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/tclsh.1 new file mode 100644 index 0000000000000000000000000000000000000000..0cb781d0975b49eb564b5846a68d1351492e5fe0 --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/tclsh.1 @@ -0,0 +1,127 @@ +'\" +'\" Copyright (c) 1993 The Regents of the University of California. +'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: tclsh.1,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH tclsh 1 "" Tcl "Tcl Applications" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +tclsh \- Simple shell containing Tcl interpreter +.SH SYNOPSIS +\fBtclsh\fR ?\fIfileName arg arg ...\fR? +.BE + +.SH DESCRIPTION +.PP +\fBTclsh\fR is a shell-like application that reads Tcl commands +from its standard input or from a file and evaluates them. +If invoked with no arguments then it runs interactively, reading +Tcl commands from standard input and printing command results and +error messages to standard output. +It runs until the \fBexit\fR command is invoked or until it +reaches end-of-file on its standard input. +If there exists a file \fB.tclshrc\fR (or \fBtclshrc.tcl\fR on +the Windows platforms) in the home directory of +the user, \fBtclsh\fR evaluates the file as a Tcl script +just before reading the first command from standard input. + +.SH "SCRIPT FILES" +.PP +If \fBtclsh\fR is invoked with arguments then the first argument +is the name of a script file and any additional arguments +are made available to the script as variables (see below). +Instead of reading commands from standard input \fBtclsh\fR will +read Tcl commands from the named file; \fBtclsh\fR will exit +when it reaches the end of the file. +There is no automatic evaluation of \fB.tclshrc\fR in this +case, but the script file can always \fBsource\fR it if desired. +.PP +If you create a Tcl script in a file whose first line is +.CS +\fB#!/usr/local/bin/tclsh\fR +.CE +then you can invoke the script file directly from your shell if +you mark the file as executable. +This assumes that \fBtclsh\fR has been installed in the default +location in /usr/local/bin; if it's installed somewhere else +then you'll have to modify the above line to match. +Many UNIX systems do not allow the \fB#!\fR line to exceed about +30 characters in length, so be sure that the \fBtclsh\fR +executable can be accessed with a short file name. +.PP +An even better approach is to start your script files with the +following three lines: +.CS +\fB#!/bin/sh +# the next line restarts using tclsh \e +exec tclsh "$0" "$@"\fR +.CE +This approach has three advantages over the approach in the previous +paragraph. First, the location of the \fBtclsh\fR binary doesn't have +to be hard-wired into the script: it can be anywhere in your shell +search path. Second, it gets around the 30-character file name limit +in the previous approach. +Third, this approach will work even if \fBtclsh\fR is +itself a shell script (this is done on some systems in order to +handle multiple architectures or operating systems: the \fBtclsh\fR +script selects one of several binaries to run). The three lines +cause both \fBsh\fR and \fBtclsh\fR to process the script, but the +\fBexec\fR is only executed by \fBsh\fR. +\fBsh\fR processes the script first; it treats the second +line as a comment and executes the third line. +The \fBexec\fR statement cause the shell to stop processing and +instead to start up \fBtclsh\fR to reprocess the entire script. +When \fBtclsh\fR starts up, it treats all three lines as comments, +since the backslash at the end of the second line causes the third +line to be treated as part of the comment on the second line. +.PP +.VS +You should note that it is also common practise to install tclsh with +its version number as part of the name. This has the advantage of +allowing multiple versions of Tcl to exist on the same system at once, +but also the disadvantage of making it harder to write scripts that +start up uniformly across different versions of Tcl. +.VE + +.SH "VARIABLES" +.PP +\fBTclsh\fR sets the following Tcl variables: +.TP 15 +\fBargc\fR +Contains a count of the number of \fIarg\fR arguments (0 if none), +not including the name of the script file. +.TP 15 +\fBargv\fR +Contains a Tcl list whose elements are the \fIarg\fR arguments, +in order, or an empty string if there are no \fIarg\fR arguments. +.TP 15 +\fBargv0\fR +Contains \fIfileName\fR if it was specified. +Otherwise, contains the name by which \fBtclsh\fR was invoked. +.TP 15 +\fBtcl_interactive\fR +Contains 1 if \fBtclsh\fR is running interactively (no +\fIfileName\fR was specified and standard input is a terminal-like +device), 0 otherwise. + +.SH PROMPTS +.PP +When \fBtclsh\fR is invoked interactively it normally prompts for each +command with ``\fB% \fR''. You can change the prompt by setting the +variables \fBtcl_prompt1\fR and \fBtcl_prompt2\fR. If variable +\fBtcl_prompt1\fR exists then it must consist of a Tcl script +to output a prompt; instead of outputting a prompt \fBtclsh\fR +will evaluate the script in \fBtcl_prompt1\fR. +The variable \fBtcl_prompt2\fR is used in a similar way when +a newline is typed but the current command isn't yet complete; +if \fBtcl_prompt2\fR isn't set then no prompt is output for +incomplete commands. + +.SH KEYWORDS +argument, interpreter, prompt, script file, shell diff --git a/lc-continuity/mk4/modtcl/tcl8.3.4/doc/tcltest.n b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/tcltest.n new file mode 100644 index 0000000000000000000000000000000000000000..02fef8e465ffef358837195348efa6155748baeb --- /dev/null +++ b/lc-continuity/mk4/modtcl/tcl8.3.4/doc/tcltest.n @@ -0,0 +1,759 @@ +'\" +'\" Copyright (c) 1990-1994 The Regents of the University of California +'\" Copyright (c) 1994-1997 Sun Microsystems, Inc. +'\" Copyright (c) 1998-1999 Scriptics Corporation +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: tcltest.n,v 1.1.1.1 2003/10/29 20:29:11 aleigh Exp $ +'\" +.so man.macros +.TH "Tcltest" n 8.2 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +Tcltest \- Test harness support code and utilities +.SH SYNOPSIS +\fBpackage require tcltest ?1.0?\fP +.sp +\fB::tcltest::test \fIname desc ?constraint? script expectedAnswer\fR +.sp +\fB::tcltest::cleanupTests \fI?runningMultipleTests?\fR +.sp +\fB::tcltest::getMatchingTestFiles\fR +.sp +\fB::tcltest::loadTestedCommands\fR +.sp +\fB::tcltest::makeFile \fIcontents name\fR +.sp +\fB::tcltest::removeFile \fIname\fR +.sp +\fB::tcltest::makeDirectory \fIname\fR +.sp +\fB::tcltest::removeDirectory \fIname\fR +.sp +\fB::tcltest::viewFile \fIname\fR +.sp +\fB::tcltest::normalizeMsg \fImsg\fR +.sp +\fB::tcltest::bytestring \fIstring\fR +.sp +\fB::tcltest::saveState\fR +.sp +\fB::tcltest::restoreState\fR +.sp +\fB::tcltest::threadReap\fR +.BE +.SH DESCRIPTION +.PP +The \fBtcltest\fR package provides the user with utility tools for +writing and running tests in the Tcl test suite. It can also be used +to create a customized test harness for an extension. +.PP +The Tcl test suite consists of multiple .test files, each of which +contains multiple test cases. Each test case consists of a call to +the test command, which specifies the name of test, a short +description, any constraints that apply to the test case, the script +to be run, and expected results. See the sections \fI"Tests,"\fR +\fI"Test Constraints,"\fR and \fI"Test Files and How to Run Them"\fR +for more details. +.PP +It is also possible to add to this test harness to create your own +customized test harness implementation. For more defails, see the +section \fI"How to Customize the Test Harness"\fR. +.PP +This approach to testing was designed and initially implemented by +Mary Ann May-Pumphrey of Sun Microsystems in the early 1990's. Many +thanks to her for donating her work back to the public Tcl release. +.SH COMMANDS +.TP +\fB::tcltest::test\fP \fIname desc ?constraints? script expectedAnswer\fR +The \fB::tcltest::test\fR command runs\fIscript\fR and compares +its result to \fIexpectedAnswer\fR. It prints an error message if the two do +not match. If \fB::tcltest::verbose\fR contains "p" or "s", it also prints +out a message if the test passed or was skipped. The test will be +skipped if it doesn't match the \fB::tcltest::match\fR variable, if it +matches an element in \fB::tcltest::skip\fR, or if one of the elements +of \fIconstraint\fR turns out not to be true. The +\fB::tcltest::test\fR command has no defined return values. See the +\fI"Writing a new test"\fR section for more details on this command. +.TP +\fB::tcltest::cleanupTests\fP \fI?runningMultipleTests?\fR +This command should be called at the end of a test file. It prints +statistics about the tests run and removes files that were created by +\fB::tcltest::makeDirectory\fR and \fB::tcltest::makeFile\fR. Names +of files and directories created outside of +\fB::tcltest::makeFile\fR and \fB::tcltest::makeDirectory\fR and +never deleted are printed to \fB::tcltest::outputChannel\fR. This command +also restores the original shell environment, as described by the ::env +array. \fIcalledFromAll\fR should be specified when +\fB::tcltest::cleanupTests\fR is called from an "all.tcl" file. Tcl files +files are generally used to run multiple tests. For more details on how to +run multiple tests, please see the section \fI"Running test files"\fR. +This proc has no defined return value. +.TP +\fB::tcltest::getMatchingTestFiles\fP +This command is used when you want to run multiple test files. It returns +the list of tests that should be sourced in an 'all.tcl' file. See the +section \fI"Running test files"\fR for more information. +.TP +\fB::tcltest::loadTestedCommands\fP +This command uses the script specified via the \fI-load\fR or +\fI-loadfile\fR to load the commands checked by the test suite. +Allowed to be empty, as the tested commands could have been compiled +into the interpreter running the test suite. +.TP +\fB::tcltest::makeFile\fP \fIcontents name\fR +Create a file that will be automatically be removed by +\fB::tcltest::cleanupTests\fR at the end of a test file. +This proc has no defined return value. +.TP +\fB::tcltest::removeFile\fP \fIname\fR +Force the file referenced by \fIname\fR to be removed. This file name +should be relative to \fI::tcltest::temporaryDirectory\fR. This proc has no +defined return values. +.TP +\fB::tcltest::makeDirectory\fP \fIname\fR +Create a directory named \fIname\fR that will automatically be removed +by \fB::tcltest::cleanupTests\fR at the end of a test file. This proc +has no defined return value. +.TP +\fB::tcltest::removeDirectory\fP \fIname\fR +Force the directory referenced by \fIname\fR to be removed. This proc +has no defined return value. +.TP +\fB::tcltest::viewFile\fP \fIfile\fR +Returns the contents of \fIfile\fR. +.TP +\fB::tcltest::normalizeMsg\fP \fImsg\fR +Remove extra newlines from \fImsg\fR. +.TP +\fB::tcltest::bytestring\fP \fIstring\fR +Construct a string that consists of the requested sequence of bytes, +as opposed to a string of properly formed UTF-8 characters using the +value supplied in \fIstring\fR. This allows the tester to create +denormalized or improperly formed strings to pass to C procedures that +are supposed to accept strings with embedded NULL types and confirm +that a string result has a certain pattern of bytes. +.TP +\fB::tcltest::saveState\fP +\fB::tcltest::restoreState\fP +Save and restore the procedure and global variable names. +A test file might contain calls to \fB::tcltest::saveState\fR and +\fB::tcltest:restoreState\fR if it creates or deletes global variables +or procs. +.TP +\fB::tcltest::threadReap\fP +\fB::tcltest::threadReap\fR only works if \fItestthread\fR is +defined, generally by compiling tcltest. If \fItestthread\fR is +defined, \fB::tcltest::threadReap\fR kills all threads except for the +main thread. It gets the ID of the main thread by calling +\fItestthread names\fR during initialization. This value is stored in +\fI::tcltest::mainThread\fR. \fB::tcltest::threadReap\fR returns the +number of existing threads at completion. +.SH TESTS +The \fBtest\fR procedure runs a test script and prints an error +message if the script's result does not match the expected result. +The following is the spec for the \fBtest\fR command: +.DS +test ??